這是一個基於技術指標的波段交易策略,使用M20時間週期進行交易決策,結合多種技術分析工具來識別趨勢轉折和進出場時機。策略採用風險控制機制,限制每日交易次數並設定資金保護。
基礎概念
時間週期: M20(20分鐘)
風險控制:動態手數計算,風險百分比為1%
資金風控門檻:5000
商品平均點差限制:50點
交易限制: 每日限制1次進場
交易時段: 00:00-16:00(可配置)
停利停損: TP=4800點,SL=1480點
進出場策略
多單進場條件
LE_Cond = (Shrink && High[1] > a_BBUP[1] && Close[1] > Open[1]);
條件分析:
布林帶收縮(Shrink): 上下軌同時收縮,表示波動率降低,蓄勢待發
突破確認(High[1] > a_BBUP[1]): 最高價突破布林帶上軌
紅K確認(Close[1] > Open[1]): 收盤價高於開盤價,確認多頭動能
空單進場條件
SE_Cond = (CCI_HDiv_01() && Low[1] < Lowest_OHLC(Symbol(),時間週期,MODE_LOW,10,1) && 多重死叉確認());
條件分析:
CCI高點背離(CCI_HDiv_01): 價格創新高但CCI未創新高,出現背離信號
創10日新低: 最低價跌破10日最低點
多重死叉確認: 至少2個指標同時出現死叉信號
KD死叉(K線下穿D線)
MACD死叉(DIF下穿MACD線)
RVI死叉
ADX DI死叉
進場價格計算
多單進場價格
BuyPrice = LowD[1] + Range[2]*0.236;
計算方式: 前日最低點 + 第2根K棒區間的23.6%
空單進場價格(編號66)
ShortPrice = HighD[1] - Range[2]*0.236;
計算方式: 前日最高點 - 第2根K棒區間的23.6%
//+------------------------------------------------------------------+
//| MT5 自動交易程式 (Expert Advisor)
//| 基於技術指標的趨勢跟隨策略
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh> // 交易功能函式庫
#include <MagicMT5_函數庫V2.mqh> // 自定義函式庫
ENUM_TIMEFRAMES 時間週期 = PERIOD_M20; // 主要分析時間週期:20分鐘
ENUM_TIMEFRAMES 時間框架 = PERIOD_H4; // 相對大週期:4小時
//+------------------------------------------------------------------+
//| EA初始化函數
//+------------------------------------------------------------------+
int OnInit()
{
LoadEA = TimeCurrent(); // 記錄EA載入時間
return(INIT_SUCCEEDED); // 初始化成功
}
//+------------------------------------------------------------------+
//| 主要交易邏輯函數(每個價格跳動時執行)
//+------------------------------------------------------------------+
void OnTick()
{
// 資金風控檢查
if(AccountInfoDouble(ACCOUNT_BALANCE) < 資金風控)
{
Alert("********** 資金不足 *************");
return;
}
// 計算當前K棒位置和距離上次出場的K棒數
BarNumber = iBarShift(Symbol(),時間週期,LoadEA);
BarSinceExit = BarNumber - CloseOrderNo;
// 新K棒時執行一次性交易測試(僅在第1根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棒(); // 更新所有技術指標
交易時段賦值(); // 檢查是否在交易時段
}
// 更新市場價格和帳戶資訊
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 && SP <= 商品平均點差) // 進場條件成立且點差合理
{
// 確保空手且不在同一根K棒下單
if(多單部位() == 0 && 空單部位() == 0 && BarNumber != OrderBarNo)
{
// 確保距離上次出場超過1根K棒且當日未超過交易次數限制
if(BarSinceExit > 1 && EntriesToday(MagicNumber,Symbol()) < 1)
{
多單進場單號 = Buy_at_MARKET(Symbol(),Lots,TP,SL,"BUY MARKET",MagicNumber);
OrderBarNo = iBarShift(Symbol(),時間週期,LoadEA);
} // end of BarSinceExit > 1
} // end of 空手且不同根K棒() == true
} // end of LE_Cond == true
//+------------------------------------------------------------------+
//| 空單進場邏輯 |
//+------------------------------------------------------------------+
set_ShortCondition(); // 設定空單進場條件
if(SE_Cond == true && SP <= 商品平均點差) // 進場條件成立且點差合理
{
// 確保空手且不在同一根K棒下單
if(多單部位() == 0 && 空單部位() == 0 && BarNumber != OrderBarNo)
{
// 確保距離上次出場超過1根K棒且當日未超過交易次數限制
if(BarSinceExit > 1 && EntriesToday(MagicNumber,Symbol()) < 1)
{
空單進場單號 = Short_at_MARKET(Symbol(),Lots,TP,SL,"Short Market",MagicNumber);
OrderBarNo = iBarShift(Symbol(),時間週期,LoadEA);
} //end of BarSinceExit > 1
} // end of 空手且不同根K棒() == true
} // end of SE_Cond == true
} //end of 允許交易時段 == true
// 即使不在交易時段也允許停損停利
交易時段外也可停損停利();
JudgeNo = iBarShift(Symbol(),時間週期,LoadEA); // 更新判斷K棒編號
}
//+------------------------------------------------------------------+
//| 自訂函數庫
//+------------------------------------------------------------------+
// 計算多單部位數量
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棒時更新所有技術指標
//+------------------------------------------------------------------+
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_BBAND(); // 布林通道
set_MACD(); // MACD指標
set_KD(); // KD指標
set_ADX(); // ADX指標
set_CCI(); // CCI指標
set_RVI(); // RVI指標
set_ICHIMOKU(); // 一目均衡表
// 計算五日平均振幅
Day5Range = ((HighD[1] - LowD[1]) + (HighD[2] - LowD[2]) +
(HighD[3] - LowD[3]) + (HighD[4] - LowD[4]) +
(HighD[5] - LowD[5])) / 5;
}
//+------------------------------------------------------------------+
//| 交易時段判斷
//+------------------------------------------------------------------+
void 交易時段賦值()
{
允許交易時段 = (getTM_hour(TimeCurrent()) >= 0 && getTM_hour(TimeCurrent()) < 16);
}
//+------------------------------------------------------------------+
//| 停損停利執行(即使在非交易時段也可執行)
//+------------------------------------------------------------------+
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);
}
}
}
// 空單停損停利邏輯
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());
// 空單出場條件
// 達到最小獲利且一目均衡表金叉,或觸及停損
SX_Cond = ((SX_MinPF == true && CrossOver(a_ICHI_C[2],a_ICHI_B[2],a_ICHI_C[1],a_ICHI_B[1])) ||
(Close[1] <= 空單停損價格 && Ask > 空單停損價格));
// 執行空單平倉
if(SX_Cond == true && BarNumber != CloseOrderNo &&
SE_BarsSinceEntry(MagicNumber,空單進場單號,時間週期) > 0)
{
SX_CloseByTicket(空單進場單號,Lots);
if(空單部位() == 0)
{
CloseOrderNo = iBarShift(Symbol(),時間週期,LoadEA);
}
}
}
}
//+------------------------------------------------------------------+
//| 多單進場條件設定
//+------------------------------------------------------------------+
void set_BuyCondition()
{
// 布林帶收縮 + 突破上軌 + 紅K確認
LE_Cond = (Shrink && High[1] > a_BBUP[1] && Close[1] > Open[1]);
}
//+------------------------------------------------------------------+
//| 空單進場條件設定
//+------------------------------------------------------------------+
void set_ShortCondition()
{
// CCI高點背離 + 創10日新低 + 多重死叉確認
SE_Cond = (CCI_HDiv_01() && Low[1] < Lowest_OHLC(Symbol(),時間週期,MODE_LOW,10,1) && 多重死叉確認());
}
//+------------------------------------------------------------------+
//| 進出場條件判斷函數 |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ADX DI死叉檢測函數 |
//+------------------------------------------------------------------+
bool ADX_DI死叉()
{
// 檢測+DI下穿-DI的死叉信號
if(a_PLUSDI[2] >= a_MINUSDI[2] && a_PLUSDI[1] < a_MINUSDI[1])
{
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| RVI死叉檢測函數 |
//+------------------------------------------------------------------+
bool RVI_死叉()
{
// 檢測RVI主線下穿信號線的死叉信號
if(a_RVI_1[2] >= a_RVI_2[2] && a_RVI_1[1] < a_RVI_2[1])
{
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| 多重死叉確認函數 |
//+------------------------------------------------------------------+
bool 多重死叉確認()
{
int CrossDN_count = 0; // 死叉信號計數器
// 檢查KD死叉
if(a_KA2[1] < a_DA2[1] && a_KA2[2] >= a_DA2[2])
CrossDN_count++;
// 檢查MACD死叉
if(a_DIF[1] < a_MACD[1] && a_DIF[2] >= a_MACD[2])
CrossDN_count++;
// 檢查RVI死叉
if(RVI_死叉())
CrossDN_count++;
// 檢查ADX DI死叉
if(ADX_DI死叉())
CrossDN_count++;
// 至少2個指標同時出現死叉才確認信號
if(CrossDN_count >= 2)
{
return true;
}
return false;
}
回測結果
測試參數交易商品:XAUUSD(黃金)
樣本內區間:2019/1/1 ~ 2023/7/31
交易手數:固定0.1手
時間框架:20分鐘圖表
交易模式:波段交易
現在就加入《外匯實戰 MT5 EA基礎班》,用量化思維,開啟你的交易新紀元!
報名連結 =>> 外匯實戰 MT5 EA基礎班
★ ~~~ 早鳥優惠 ( 2025/11/13 前報名) ~~~ ★
🎁限量加碼 贈送 實戰EA *2
(XAUUSD *1 + NAS100 * 1)
(XAUUSD *1 + NAS100 * 1)
可攜伴2位參加文創手作聖誕樹 DIY才藝班
沒有留言:
張貼留言