2025年8月12日 星期二

MT5 EA交易策略開發教學[12]

策略概述

本文詳細介紹一個基於MT5平台的Expert Advisor(EA)開發,結合三線系統與一目均衡表的複合交易策略。該策略適用於外匯市場,特別是黃金(XAUUSD)交易,通過技術指標組合實現自動化交易。

關鍵特色

  • ✅ 多重技術指標確認機制
  • ✅ 動態資金管理
  • ✅ POC與VWAP價格定位
  • ✅ 完整風險控制系統
  • ✅ 15分鐘時間框架策略

進出場策略

多單進場條件

多單策略採用三重確認機制:

// 多單進場條件:三線多頭排列 + 突破三線最高值 + 短均線>長均線
LE_Cond = (TrendDir3L == 1 && Close[1] > Max3L && a_Avg7[1] > a_Avg13[1]);

條件分析:

  1. 三線多頭排列 (TrendDir3L == 1):7日、13日、21日移動平均線呈現多頭排列
  2. 突破確認 (Close[1] > Max3L):收盤價突破三線系統最高值
  3. 短線優勢 (a_Avg7[1] > a_Avg13[1]):7日均線高於13日均線

空單進場條件

空單策略基於一目均衡表系統:

// 空單進場條件:一目均衡表基準線下穿轉換線 + 收盤價<基準線
SE_Cond = (CrossUnder(a_ICHI_B[2], a_ICHI_C[2], a_ICHI_B[1], a_ICHI_C[1]) 
&& Close[1] < a_ICHI_B[1]);

條件分析:

  1. 基準線下穿轉換線:一目均衡表趨勢轉空信號
  2. 價格確認:收盤價低於基準線,確認空頭趨勢

進場價格計算

  • 多單進場價格:POC上方0.382倍ATR距離
  • 空單進場價格:VWAP下方0.236倍ATR距離

EA核心程式碼

初始化設定

// 引入必要的函數庫
#include <Trade\Trade.mqh>           // MT5交易函數庫
#include <MagicMT5_函數庫V2.mqh>     // 自定義函數庫

// 時間框架設定
ENUM_TIMEFRAMES  時間週期 = PERIOD_M15 ;  // 主要交易時間框架(15分鐘)
ENUM_TIMEFRAMES  時間框架 = PERIOD_H4;    // 相對大週期(4小時)

//+------------------------------------------------------------------+
//| EA初始化函數                                                      |
//+------------------------------------------------------------------+
int OnInit()
  {
   LoadEA = TimeCurrent();            // 記錄EA載入時間
   return(INIT_SUCCEEDED);            // 返回初始化成功
  }

主要交易邏輯

//+------------------------------------------------------------------+
//| 主要交易邏輯函數,每個Tick都會執行                                |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 資金風控檢查
   if(AccountInfoDouble(ACCOUNT_BALANCE) < 資金風控)
     {
      Alert("**********  資金不足 *************");  // 資金不足警告
      return;                         // 停止執行
     }

   // 計算當前K線位置和出場後經過的K線數
   BarNumber = iBarShift(Symbol(),時間週期,LoadEA);
   BarSinceExit = BarNumber-CloseOrderNo ;
   
   // 測試用:每根新K線都進行一次買入和立即平倉
   if((BarNumber == 1 && BarNumber != JudgeNo))
     {
      多單進場單號 = Buy_at_MARKET(Symbol(),Lots,0,0,"1st_K",MagicNumber) ;
      LX_CloseByTicket(多單進場單號,Lots) ;
      CloseOrderNo =  iBarShift(Symbol(),時間週期,LoadEA);
      FastSma = MathMin(LenA1, LenB1);  // 設定快速移動平均線週期
      SlowSma = MathMax(LenA1, LenB1);  // 設定慢速移動平均線週期
     }

   // 新K線時執行的函數
   if(BarNumber != JudgeNo)
     {
      換K棒();                        // 更新K線數據和指標
      交易時段賦值();                 // 判斷是否在交易時段
     }

   // 獲取即時市場資訊
   Ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);           // 當前賣價
   Bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);           // 當前買價
   AccountBalance=AccountInfoDouble(ACCOUNT_BALANCE);    // 帳戶餘額
   Tickvalue=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE);  // 點值
   SP = NormalizeDouble(MathAbs(Ask-Bid),Digits()) ;    // 買賣價差

//+------------------------------------------------------------------+

//|計算交易手數

//+------------------------------------------------------------------+
   // 動態手數計算
   if(動態計算手數 == true)
     {
      Lots = get_dynamic_lot_size(是否偶數單,Symbol(),風險百分比,AccountBalance,SL) ;
      Lots = MathMin(0.3,MathMax(0.01,Lots)) ;  // 限制手數範圍0.01-0.3
     }

   // 在允許的交易時段內執行交易邏輯
   if(允許交易時段 == true)
     {
      //+------------------------------------------------------------------+
      //|多單進場邏輯
      //+------------------------------------------------------------------+
      set_BuyCondition();             // 設定多單進場條件
      if(LE_Cond == true)            // 如果多單進場條件滿足
        {
         // 檢查是否空手且不在同一根K線下單
         if(多單部位() == 0 && 空單部位() == 0 && BarNumber != OrderBarNo)
           {
            買入價格 = Get_BuyPrice() ;  // 計算多單進場價格

            // 出場後至少間隔1根K線且今日進場次數小於1次
            if(BarSinceExit > 1 && EntriesToday(MagicNumber,Symbol()) < 1)
              {

                  if(Close[1] < 買入價格)  // 前一根收盤價低於買入價格
                    {
                     // 下突破買入停損單
                     多單進場單號 = Buy_at_STOP(Symbol(),MagicNumber,買入價格,Lots,TP,SL,"BUY STOP",3600) ;
                     OrderBarNo = iBarShift(Symbol(),時間週期,LoadEA);  // 記錄下單K線
                    }
              
              } // end of BarSinceExit > 1
           } // end of 空手且不同根K棒
        } // end of LE_Cond == true
        
      //+------------------------------------------------------------------+
      //|空單進場邏輯
      //+------------------------------------------------------------------+
      set_ShortCondition() ;          // 設定空單進場條件
      if(SE_Cond == true)            // 如果空單進場條件滿足
        {
         // 檢查是否空手且不在同一根K線下單
         if(多單部位() == 0 && 空單部位() == 0 && BarNumber != OrderBarNo)
           {
            賣出價格 = Get_ShortPrice();  // 計算空單進場價格

            // 出場後至少間隔1根K線且今日進場次數小於1次
            if(BarSinceExit > 1 && EntriesToday(MagicNumber,Symbol()) < 1)
              {

                  if(Close[1] > 賣出價格)  // 前一根收盤價高於賣出價格
                    {
                     // 下突破賣出停損單
                     空單進場單號 = Short_at_STOP(Symbol(),MagicNumber,賣出價格,Lots,TP,SL,"Short STOP",3600) ;
                     OrderBarNo = iBarShift(Symbol(),時間週期,LoadEA);  // 記錄下單K線
                    }

              } //end of BarSinceExit > 1
           } // end of 空手且不同根K棒
        } // end of SE_Cond == true
     } //end of 允許交易時段 == true

   交易時段外也可停損停利();          // 即使非交易時段也執行停損停利
   JudgeNo = iBarShift(Symbol(),時間週期,LoadEA);  // 更新判斷K線編號

  } //end of onTick

自訂函數庫

部位計算函數

//+------------------------------------------------------------------+
//| 計算空單部位數量                                                  
//+------------------------------------------------------------------+
int 多單部位()
  {
   int count;
   count = get_TradeCounts(Symbol(), MagicNumber,POSITION_TYPE_BUY) ;  // 獲取買入部位數量
   return count ;
  }

//+------------------------------------------------------------------+
//| 計算空單部位數量                                                  
//+------------------------------------------------------------------+
int 空單部位()
  {
   int count;
   count = get_TradeCounts(Symbol(), MagicNumber,POSITION_TYPE_SELL) ; // 獲取賣出部位數量
   return count ;
  }

換K棒函數

//+------------------------------------------------------------------+
//| 換K棒時執行的函數,更新所有指標和數據                             |
//+------------------------------------------------------------------+
void 換K棒()
  {
   // 新K線時刪除所有掛單
   if(total_pending_order_count(Symbol(), MagicNumber,-1) != 0)
     {
      delete_pending_orders_all(Symbol(), MagicNumber, -1, 0x0000ff);  // 刪除所有掛單
     }
   
   // 更新基礎數據
   Set_OHLC_Bar_Series();    // 設定K線數據陣列
   Set_OHLC_Day_Series();    // 設定日線數據陣列
   Get_OHLC_Bar(30) ;        // 獲取30根K線數據
   Get_OHLC_Day(15) ;        // 獲取15日數據
   set_BarInfo();            // 設定K線資訊(實體、影線等)
   set_ATR();                // 計算ATR指標

   // 更新技術指標
   set_MACD();               // 計算MACD指標
   set_ThreeLine() ;         // 計算三線系統(移動平均線)
   FixBarHL();               // 計算固定週期高低點
   set_ICHIMOKU();           // 計算一目均衡表指標

   // 計算自定義指標
   計算VWAP() ;              // 計算成交量加權平均價
   計算POC() ;               // 計算控制點

   // 計算五日平均振幅
   Day5Range = ((HighD[1] - LowD[1])+(HighD[2] - LowD[2])+(HighD[3] - LowD[3])+(HighD[4] - LowD[4])+(HighD[5] - LowD[5]))/5;
  }

交易時段管理

//+------------------------------------------------------------------+
//| 判斷當前是否在交易時段                                            |
//+------------------------------------------------------------------+
void 交易時段賦值()
  {
   if(交易時段編號 == 6)
      允許交易時段 = (getTM_hour(TimeCurrent()) >= 6 && getTM_hour(TimeCurrent()) < 22);  // 6點到22點
  }

停損停利機制

完整出場邏輯函數

//+------------------------------------------------------------------+
//| 停損停利邏輯,即使非交易時段也會執行                              |
//+------------------------------------------------------------------+
void 交易時段外也可停損停利()
  {
   // 多單停損停利邏輯
   if(多單部位() > 0)
     {
      //+------------------------------------------------------------------+
      //|    多單出場方法
      //+------------------------------------------------------------------+
      double 多單最小停利 = 0.0;
      bool LX_MinPF = false ;
      多單進場價格 = LE_EntryPrice(MagicNumber,多單進場單號);      // 獲取多單進場價格
      多單最小停利 = NormalizeDouble(多單進場價格 + SP*3,Digits()) ;  // 最小獲利目標
      LX_MinPF = Bid > 多單最小停利 ;                             // 是否達到最小獲利
      
      多單停利價格 = NormalizeDouble(多單進場價格 + TP * Point(),Digits()) ;  // 計算停利價格
      多單停損價格 = NormalizeDouble(多單進場價格 - SL * Point(),Digits()) ;  // 計算停損價格

      // 多單出場方式:達到最小獲利且MACD向下穿越零軸,或觸及停損

         LX_Cond = ((LX_MinPF == true && CrossUnder(a_MACD[2],0,a_MACD[1],0)) || 
                   (Close[1] >= 多單停損價格 && Bid < 多單停損價格)) ;

      // 多單出場執行
      if(LX_Cond == true && BarNumber != CloseOrderNo && LE_BarsSinceEntry(MagicNumber,多單進場單號,時間週期) > 0)
        {
         LX_CloseByTicket(多單進場單號,Lots) ;  // 平倉多單

         if(多單部位() == 0)          // 如果多單已全部平倉
           {
            CloseOrderNo = iBarShift(Symbol(),時間週期,LoadEA) ;  // 記錄平倉K線
           }
        }
     } // end of 多單部位() > 0

   // 空單停損停利邏輯
   if(空單部位() > 0)
     {
      //+------------------------------------------------------------------+
      //|    空單出場方法
      //+------------------------------------------------------------------+
      double 空單最小停利 = 0.0;
      bool SX_MinPF = false ;
      空單進場價格 = SE_EntryPrice(MagicNumber,空單進場單號);      // 獲取空單進場價格
      空單最小停利 = NormalizeDouble(空單進場價格 - SP*3,Digits()) ;  // 最小獲利目標
      SX_MinPF = Ask < 空單最小停利 ;                             // 是否達到最小獲利
      
      空單停利價格 = NormalizeDouble(空單進場價格 - TP * Point(),Digits()) ;  // 計算停利價格
      空單停損價格 = NormalizeDouble(空單進場價格 + SL * Point(),Digits()) ;  // 計算停損價格

      // 空單出場方式:綜合停損停利機制

         bool SXcond21,SXcond22,SXcond23 ;
         // 計算持倉期間最低價
         空單最低價 = iLow(Symbol(),時間週期, iLowest(Symbol(),時間週期,MODE_LOW,SE_BarsSinceEntry(MagicNumber,空單進場單號,時間週期),1));
         空單最低價 = NormalizeDouble(空單最低價,Digits()) ;
         
         SXcond21 = (Close[1] >= 空單停利價格 && Ask < 空單停利價格) ;     // 觸及停利
         SXcond22 = (SE_BarsSinceEntry(MagicNumber,空單進場單號,時間週期) == 1 && 
                    Close[1] <= 空單停損價格 && Ask > 空單停損價格) ;       // 第一根K線停損
         SXcond23 = (SE_BarsSinceEntry(MagicNumber,空單進場單號,時間週期) > 1 && 
                    Close[1] <= (空單最低價 + SL * Point()) && 
                    Ask > (空單最低價 + SL * Point())) ;                   // 追蹤停損
         
         SX_Cond = (SXcond21 == true || SXcond22 == true || SXcond23 == true) ;       

      // 空單出場執行
      if(SX_Cond == true && BarNumber != CloseOrderNo && SE_BarsSinceEntry(MagicNumber,空單進場單號,時間週期) > 0)
        {
         SX_CloseByTicket(空單進場單號,Lots) ;  // 平倉空單

         if(空單部位() == 0)          // 如果空單已全部平倉
           {
            CloseOrderNo = iBarShift(Symbol(),時間週期,LoadEA) ;  // 記錄平倉K線
           }
        }
     } // end of 空單部位() > 0
  } // end of 交易時段外也可停損停利()

進場價格計算函數

//+------------------------------------------------------------------+
//| 根據編號計算多單進場價格
//+------------------------------------------------------------------+
double Get_BuyPrice()
  {
   double BuyPrice=0.0 ;

   // POC 相關價格計算
      BuyPrice = POC_價格 + a_ATR[2]*0.382; // POC上方0.382倍ATR距離進場

   return NormalizeDouble(BuyPrice,Digits()) ;  // 標準化小數位數
  } // end of get BuyPrice

//+------------------------------------------------------------------+
//| 根據編號計算空單進場價格
//+------------------------------------------------------------------+
double Get_ShortPrice()
  {
   double ShortPrice=0.0 ;

      ShortPrice = VWAP_價格 - a_ATR[2]*0.236; // VWAP下方0.236倍ATR距離進場

   return NormalizeDouble(ShortPrice,Digits()) ;  // 標準化小數位數
  } // end of get ShortPrice

//+------------------------------------------------------------------+
//|多單進場條件設定
//+------------------------------------------------------------------+
void set_BuyCondition()
  {
   // 多單模組編號:三線趨勢向上+突破三線最高值+短均線大於長均線
      LE_Cond = (TrendDir3L == 1 && Close[1] > Max3L && a_Avg7[1] > a_Avg13[1]) ;
  }

//+------------------------------------------------------------------+
//| 空單進場條件設定
//+------------------------------------------------------------------+
void set_ShortCondition()
  {
   // 空單模組編號:一目均衡表基準線向下突破轉換線+收盤價低於基準線
      SE_Cond = (CrossUnder(a_ICHI_B[2], a_ICHI_C[2], a_ICHI_B[1], a_ICHI_C[1]) && Close[1] < a_ICHI_B[1]) ;
  }

K線數據處理

數據陣列設定

//+--------------------------------------------------------+
//| 設定 開高低收 陣列序列
//+--------------------------------------------------------+
// K線價格陣列變數
double Open[], High[], Low[], Close[],Range[],Body[],UPshadow[],DNshadow[] ;  // 基本OHLC和K線資訊
double BigOpen[], BigHigh[], BigLow[], BigClose[] ;       // 大週期OHLC
double OpenD[], HighD[], LowD[], CloseD[] ;              // 日線OHLC
long Volume[],BigVolume[] ;                               // 成交量

//+------------------------------------------------------------------+
//| 設定K線數據陣列為時間序列模式
//+------------------------------------------------------------------+
void Set_OHLC_Bar_Series()
  {
   ArraySetAsSeries(Open,true);      // 開盤價陣列設為時間序列
   ArraySetAsSeries(High,true);      // 最高價陣列設為時間序列
   ArraySetAsSeries(Low,true);       // 最低價陣列設為時間序列
   ArraySetAsSeries(Close,true);     // 收盤價陣列設為時間序列
   ArraySetAsSeries(Volume,true);    // 成交量陣列設為時間序列
  }

//+------------------------------------------------------------------+
//| 獲取指定數量的K線數據
//+------------------------------------------------------------------+
void Get_OHLC_Bar(int argCount)
  {
   get_OpenData(Symbol(),時間週期,argCount,Open) ;     // 獲取開盤價數據
   get_HighData(Symbol(),時間週期,argCount,High) ;     // 獲取最高價數據
   get_LowData(Symbol(),時間週期,argCount,Low) ;       // 獲取最低價數據
   get_CloseData(Symbol(),時間週期,argCount,Close) ;   // 獲取收盤價數據
   get_VolumeData(Symbol(),時間週期,argCount,Volume) ; // 獲取成交量數據
  }

//+------------------------------------------------------------------+
//| 設定日線數據陣列為時間序列模式
//+------------------------------------------------------------------+
void Set_OHLC_Day_Series()
  {
   ArraySetAsSeries(OpenD,true);     // 日線開盤價陣列設為時間序列
   ArraySetAsSeries(HighD,true);     // 日線最高價陣列設為時間序列
   ArraySetAsSeries(LowD,true);      // 日線最低價陣列設為時間序列
   ArraySetAsSeries(CloseD,true);    // 日線收盤價陣列設為時間序列
  }

//+------------------------------------------------------------------+
//| 獲取指定數量的日線數據
//+------------------------------------------------------------------+
void Get_OHLC_Day(int argCount)
  {
   get_OpenData(Symbol(),PERIOD_D1,argCount,OpenD) ;   // 獲取日線開盤價
   get_HighData(Symbol(),PERIOD_D1,argCount,HighD) ;   // 獲取日線最高價
   get_LowData(Symbol(),PERIOD_D1,argCount,LowD) ;     // 獲取日線最低價
   get_CloseData(Symbol(),PERIOD_D1,argCount,CloseD) ; // 獲取日線收盤價
  }

//+------------------------------------------------------------------+
//| 計算K線資訊(實體、影線、振幅等)
//+------------------------------------------------------------------+
void set_BarInfo()
  {
   // 調整陣列大小並設為時間序列
   ArrayResize(Range,ArraySize(Open)) ;      // 振幅陣列
   ArraySetAsSeries(Range,true) ;
   ArrayResize(Body,ArraySize(Open)) ;       // 實體陣列
   ArraySetAsSeries(Body,true) ;
   ArrayResize(UPshadow,ArraySize(Open)) ;   // 上影線陣列
   ArraySetAsSeries(UPshadow,true) ;
   ArrayResize(DNshadow,ArraySize(Open)) ;   // 下影線陣列
   ArraySetAsSeries(DNshadow,true) ;

   // 計算每根K線的各項數據
   for(int i = 0; i < ArraySize(Open)-1; i=i+1)
     {
      Range[i] = High[i]-Low[i];                          // 振幅 = 最高價 - 最低價
      Body[i] = MathAbs(Close[i]-Open[i]);                // 實體 = |收盤價 - 開盤價|
      UPshadow[i] = High[i]-MathMax(Close[i],Open[i]);    // 上影線 = 最高價 - max(收盤價,開盤價)
      DNshadow[i] = MathMin(Close[i],Open[i])-Low[i];     // 下影線 = min(收盤價,開盤價) - 最低價
     }
  }

技術指標計算

//+------------------------------------------------------------------

// 計算ATR(平均真實波動範圍)指標

//+---------------------------------------------------------

double a_ATR[] ;                              // ATR指標陣列
void set_ATR()
  {
   int h_ATR ;                                // ATR指標句柄
   h_ATR = iATR(Symbol(),時間週期,LenB2);     // 創建ATR指標,週期為LenB2
   ArraySetAsSeries(a_ATR, true);            // 設為時間序列
   get_IndexData(h_ATR,0,0,5,a_ATR) ;        // 獲取5個ATR數值
  }

//+------------------------------------------------------------------+

//| 計算MACD指標

//+------------------------------------------------------------------+
double a_DIF[], a_MACD[], a_OSC[] ;          // MACD相關指標陣列
void set_MACD()
  {
   int MacdLen, FastLen, SlowLen ;           // MACD參數
   int h_DIF,h_MACD ;                        // MACD指標句柄
   
   // 計算MACD參數
   MacdLen = MathMax(LenA1,LenB1) ;          // 信號線週期
   if(MacdLen > 15)
      MacdLen = 15 ;                         // 限制最大值為15
   FastLen = (int)MathRound(MacdLen*1.33) ;  // 快線週期
   SlowLen = (int)MathRound(MacdLen*2.66) ;  // 慢線週期

   // 創建MACD指標
   h_DIF = iMACD(Symbol(),時間週期,FastLen,SlowLen,MacdLen,PRICE_WEIGHTED);   // DIF線
   ArraySetAsSeries(a_DIF, true);
   h_MACD = iMACD(Symbol(),時間週期,FastLen,SlowLen,MacdLen,PRICE_WEIGHTED);  // MACD線
   ArraySetAsSeries(a_MACD, true);

   // 獲取MACD數據
   get_IndexData(h_DIF,0,0,10,a_DIF) ;       // 獲取DIF數據
   get_IndexData(h_MACD,1,0,10,a_MACD) ;     // 獲取MACD數據

   // 計算OSC線(柱狀圖)
   ArraySetAsSeries(a_OSC, true);
   ArrayResize(a_OSC,ArraySize(a_DIF)) ;

   for(int i = 0;i < ArraySize(a_OSC); i++)
     {
      a_OSC[i] = a_DIF[i]-a_MACD[i] ;        // OSC = DIF - MACD
     }
  }

//+------------------------------------------------------------------+

//| 計算三線系統(多條移動平均線)

//+------------------------------------------------------------------+
double a_Avg7[],a_Avg13[],a_Avg21[],a_Avg60[],Max3L,Min3L ;  // 移動平均線陣列和極值
int TrendDir3L ;                             // 三線趨勢方向
void set_ThreeLine()
  {
   int h_Avg7,h_Avg13,h_Avg21,h_Avg60 ;     // 移動平均線句柄
   
   // 創建各週期移動平均線
   h_Avg7 = iMA(Symbol(),時間週期,7,0,MODE_SMA,PRICE_CLOSE) ;   // 7週期移動平均線
   ArraySetAsSeries(a_Avg7,true) ;
   h_Avg13 = iMA(Symbol(),時間週期,13,0,MODE_SMA,PRICE_CLOSE) ; // 13週期移動平均線
   ArraySetAsSeries(a_Avg13,true) ;
   h_Avg21 = iMA(Symbol(),時間週期,21,0,MODE_SMA,PRICE_CLOSE) ; // 21週期移動平均線
   ArraySetAsSeries(a_Avg21,true) ;
   h_Avg60 = iMA(Symbol(),時間週期,60,0,MODE_SMA,PRICE_CLOSE) ; // 60週期移動平均線
   ArraySetAsSeries(a_Avg60,true) ;

   // 獲取移動平均線數據
   get_IndexData(h_Avg7,0,0,5,a_Avg7) ;      // 獲取7週期MA數據
   get_IndexData(h_Avg13,0,0,5,a_Avg13) ;    // 獲取13週期MA數據
   get_IndexData(h_Avg21,0,0,5,a_Avg21) ;    // 獲取21週期MA數據
   get_IndexData(h_Avg60,0,0,5,a_Avg60) ;    // 獲取60週期MA數據

   // 計算三線系統的最高和最低值
   Max3L = MathMax(a_Avg7[1],MathMax(a_Avg13[1],a_Avg21[1])) ;  // 三線最高值
   Min3L = MathMin(a_Avg7[1],MathMin(a_Avg13[1],a_Avg21[1])) ;  // 三線最低值
   
   // 判斷三線趨勢方向
   if(a_Avg7[1] > a_Avg13[1] && a_Avg13[1] > a_Avg21[1])        // 7>13>21,多頭排列
      TrendDir3L = 1 ;
   else
      if(a_Avg7[1] < a_Avg13[1] && a_Avg13[1] < a_Avg21[1])     // 7<13<21,空頭排列
         TrendDir3L = -1 ;
      else
         TrendDir3L = 0 ;                                        // 其他情況,盤整
  }

//+------------------------------------------------------------------+

//| 計算固定週期高低點

//+------------------------------------------------------------------+
double FixLenH,FixLenL,FixLenHL,FixLen33,FixLen67 ;  // 固定週期價格變數
int FixLenHPB,FixLenLPB ;                            // 高低點距今K線數
void FixBarHL()
  {
   FixLenH = Highest_OHLC(Symbol(),時間週期,MODE_HIGH,60,2) ;    // 60週期內最高價(從第2根K線開始)
   FixLenL = Lowest_OHLC(Symbol(),時間週期,MODE_LOW,60,2) ;     // 60週期內最低價(從第2根K線開始)
   FixLenHL = FixLenH - FixLenL ;                               // 高低價差
   FixLen33 = FixLenL+FixLenHL*0.33 ;                           // 低點+33%位置
   FixLen67 = FixLenL+FixLenHL*0.67 ;                           // 低點+67%位置
   FixLenHPB = BarsLast(High[1] = FixLenH,時間週期) ;           // 最高點距今K線數
   FixLenLPB = BarsLast(Low[1] = FixLenL,時間週期) ;            // 最低點距今K線數
  }

//+------------------------------------------------------------------+

//| 計算一目均衡表指標

//+------------------------------------------------------------------+
double a_ICHI_B[],a_ICHI_C[],a_ICHI_SA[],a_ICHI_SB[],a_ICHI_LC[] ;  // 一目均衡表各線陣列
void set_ICHIMOKU()
  {
   int h_ICHI_C,h_ICHI_B,h_ICHI_SA,h_ICHI_SB,h_ICHI_LC ;       // 一目均衡表指標句柄
   
   // 創建一目均衡表指標(參數:9,26,52)
   h_ICHI_C = iIchimoku(Symbol(),時間週期,9,26,52);             // 轉換線
   ArraySetAsSeries(a_ICHI_C, true);
   h_ICHI_B = iIchimoku(Symbol(),時間週期,9,26,52);             // 基準線
   ArraySetAsSeries(a_ICHI_B, true);
   h_ICHI_SA = iIchimoku(Symbol(),時間週期,9,26,52);            // 先行帶A
   ArraySetAsSeries(a_ICHI_SA, true);
   h_ICHI_SB = iIchimoku(Symbol(),時間週期,9,26,52);            // 先行帶B
   ArraySetAsSeries(a_ICHI_SB, true);
   h_ICHI_LC = iIchimoku(Symbol(),時間週期,9,26,52);            // 遲行帶
   ArraySetAsSeries(a_ICHI_LC, true);

   // 獲取一目均衡表各線數據
   get_IndexData(h_ICHI_C,0,0,5,a_ICHI_C) ;     // 轉換線數據
   get_IndexData(h_ICHI_B,1,0,5,a_ICHI_B) ;     // 基準線數據
   get_IndexData(h_ICHI_SA,2,0,5,a_ICHI_SA) ;   // 先行帶A數據
   get_IndexData(h_ICHI_SB,3,0,5,a_ICHI_SB) ;   // 先行帶B數據
   get_IndexData(h_ICHI_LC,4,0,5,a_ICHI_LC) ;   // 遲行帶數據
  }

//+------------------------------------------------------------------+

//| VWAP(成交量加權平均價)計算

//+------------------------------------------------------------------+
double VWAP_價格;                                // VWAP價格變數

void 計算VWAP()
  {
   double 價格量積累 = 0;                        // 價格*成交量的累計值
   long 總量 = 0;                               // 總成交量

   // 計算過去20根K線的VWAP
   for(int i = 1; i <= 20; i++)
     {
      double 典型價格 = (High[i] + Low[i] + Close[i]) / 3;  // 典型價格HLC/3
      價格量積累 += 典型價格 * Volume[i];                   // 累計價格*成交量
      總量 += Volume[i];                                   // 累計成交量
     }

   if(總量 > 0)
      VWAP_價格 = 價格量積累 / 總量;                       // VWAP = 總價格量/總量
  }

//+------------------------------------------------------------------+

//|POC(控制點)計算

//+------------------------------------------------------------------+
double POC_價格;                                 // POC價格變數

void 計算POC()
  {
   // 簡化版本:找到成交量最大的價格水平
   long max_volume = 0;                          // 最大成交量
   POC_價格 = Close[1];                          // 初始化為前一根收盤價

   // 搜尋過去20根K線中成交量最大的價格
   for(int i = 1; i <= 20; i++)
     {
      if(Volume[i] > max_volume)                 // 如果當前成交量更大
        {
         max_volume = Volume[i];                 // 更新最大成交量
         POC_價格 = (High[i] + Low[i] + Close[i]) / 3;  // 該K線的典型價格作為POC
        }
     }
  }
回測結果

測試參數

  • 交易商品:XAUUSD(黃金)
  • 樣本內區間:2019/1/1 ~ 2023/7/31
  • 交易手數:固定0.1手
  • 時間框架:15分鐘圖表
  • 交易模式:波段交易



沒有留言:

張貼留言