MT5EA / 策略编译通过 · EX5 32KB 自动发布 1 1

黄金亚欧盘突破策略EA

taiyu1983·2 小时前发布

亚盘区间突破交易,欧盘开盘后突破做多空,止损1:2止盈,固定0.1手

Asian_Breakout_Gold_EA.mq5259
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#property copyright "XAUOF指标工坊"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>

//+------------------------------------------------------------------+
//| 可调参数                                                          |
//+------------------------------------------------------------------+
input int      InpMagicNumber = 888888;           // 魔术号(用于区分不同策略)
input double   InpLotSize = 0.1;                  // 固定手数
input int      InpAsianStartHour = 8;             // 亚盘开始时间(小时,北京时间)
input int      InpAsianEndHour = 14;              // 亚盘结束时间(小时,北京时间)
input int      InpTimezoneOffset = 8;             // 时区偏移(北京时间=8,UTC=0)
input double   InpRiskRewardRatio = 2.0;          // 止盈止损比例(倍数,默认2倍)
input bool     InpUseCloseBreakout = true;        // 使用收盘价确认突破(true=更保守,false=触及即突破)
input int      InpSlippage = 30;                  // 允许滑点(点)
input string   InpTradeComment = "亚欧盘突破";    // 订单备注

//+------------------------------------------------------------------+
//| 全局变量                                                          |
//+------------------------------------------------------------------+
CTrade trade;                    // 交易对象
datetime currentDate = 0;        // 当前日期(用于每日重置区间)
double asianHigh = 0;            // 亚盘最高价
double asianLow = 0;             // 亚盘最低价
bool rangeValid = false;         // 区间是否有效
bool tradedToday = false;        // 今天是否已交易(防止重复开仓)

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // 设置交易参数
   trade.SetExpertMagicNumber(InpMagicNumber);
   trade.SetDeviationInPoints(InpSlippage);
   trade.SetTypeFilling(ORDER_FILLING_FOK);
   trade.SetAsyncMode(false);
   
   // 参数有效性检查
   if(InpLotSize <= 0)
   {
      Print("错误:手数必须大于0");
      return INIT_PARAMETERS_INCORRECT;
   }
   
   if(InpAsianStartHour < 0 || InpAsianStartHour > 23 || InpAsianEndHour < 0 || InpAsianEndHour > 23)
   {
      Print("错误:时间必须在0-23之间");
      return INIT_PARAMETERS_INCORRECT;
   }
   
   if(InpRiskRewardRatio <= 0)
   {
      Print("错误:止盈止损比例必须大于0");
      return INIT_PARAMETERS_INCORRECT;
   }
   
   Print("亚欧盘突破EA初始化成功");
   Print("亚盘时段: ", InpAsianStartHour, ":00 - ", InpAsianEndHour, ":00(北京时间)");
   Print("固定手数: ", InpLotSize, " 止盈止损比例: 1:", InpRiskRewardRatio);
   
   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Comment("");
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 获取当前时间(转换为北京时间)
   datetime serverTime = TimeCurrent();
   MqlDateTime dt;
   TimeToStruct(serverTime, dt);
   
   // 转换为本地时区
   int localHour = (dt.hour + InpTimezoneOffset) % 24;
   
   // 检查是否是新的一天,重置数据
   datetime todayDate = serverTime - (serverTime % 86400); // 获取今天0点的时间戳
   if(todayDate != currentDate)
   {
      currentDate = todayDate;
      asianHigh = 0;
      asianLow = 0;
      rangeValid = false;
      tradedToday = false;
      Print("新的交易日开始,重置亚盘区间");
   }
   
   // 亚盘时段:记录最高最低价
   bool isAsianSession = IsAsianSession(localHour);
   if(isAsianSession)
   {
      double high = iHigh(_Symbol, PERIOD_CURRENT, 0);
      double low = iLow(_Symbol, PERIOD_CURRENT, 0);
      
      if(asianHigh == 0 || asianLow == 0)
      {
         // 第一次记录
         asianHigh = high;
         asianLow = low;
      }
      else
      {
         // 更新区间
         if(high > asianHigh) asianHigh = high;
         if(low < asianLow) asianLow = low;
      }
      
      rangeValid = true;
   }
   
   // 欧盘时段:检查突破信号
   if(!isAsianSession && rangeValid && !tradedToday)
   {
      // 检查当前是否已有持仓
      if(PositionSelect(_Symbol))
      {
         // 已有持仓,不再开新仓
         return;
      }
      
      double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      
      // 计算止损距离
      double stopDistance = asianHigh - asianLow;
      if(stopDistance <= 0) return;
      
      // 做多信号:突破区间上沿
      bool longSignal = false;
      if(InpUseCloseBreakout)
      {
         // 使用收盘价突破
         double prevClose = iClose(_Symbol, PERIOD_CURRENT, 1);
         double currClose = iClose(_Symbol, PERIOD_CURRENT, 0);
         longSignal = (currClose > asianHigh && prevClose <= asianHigh);
      }
      else
      {
         // 触及即突破
         double currHigh = iHigh(_Symbol, PERIOD_CURRENT, 0);
         longSignal = (currHigh > asianHigh);
      }
      
      // 做空信号:突破区间下沿
      bool shortSignal = false;
      if(InpUseCloseBreakout)
      {
         double prevClose = iClose(_Symbol, PERIOD_CURRENT, 1);
         double currClose = iClose(_Symbol, PERIOD_CURRENT, 0);
         shortSignal = (currClose < asianLow && prevClose >= asianLow);
      }
      else
      {
         double currLow = iLow(_Symbol, PERIOD_CURRENT, 0);
         shortSignal = (currLow < asianLow);
      }
      
      // 执行做多
      if(longSignal)
      {
         double sl = asianLow;
         double tp = currentAsk + (stopDistance * InpRiskRewardRatio);
         
         if(trade.Buy(InpLotSize, _Symbol, currentAsk, sl, tp, InpTradeComment))
         {
            Print("做多开仓成功 | 价格:", currentAsk, " 止损:", sl, " 止盈:", tp);
            tradedToday = true;
         }
         else
         {
            Print("做多开仓失败,错误代码:", GetLastError());
         }
      }
      
      // 执行做空
      if(shortSignal)
      {
         double sl = asianHigh;
         double tp = currentPrice - (stopDistance * InpRiskRewardRatio);
         
         if(trade.Sell(InpLotSize, _Symbol, currentPrice, sl, tp, InpTradeComment))
         {
            Print("做空开仓成功 | 价格:", currentPrice, " 止损:", sl, " 止盈:", tp);
            tradedToday = true;
         }
         else
         {
            Print("做空开仓失败,错误代码:", GetLastError());
         }
      }
   }
   
   // 显示当前状态
   string status = "";
   status += "========== 亚欧盘突破EA ==========\n";
   status += "魔术号: " + IntegerToString(InpMagicNumber) + "\n";
   status += "亚盘时段: " + IntegerToString(InpAsianStartHour) + ":00 - " + IntegerToString(InpAsianEndHour) + ":00\n";
   status += "当前时间: " + IntegerToString(localHour) + ":00(本地)\n";
   status += "------------------------------------\n";
   
   if(rangeValid)
   {
      status += "亚盘高点: " + DoubleToString(asianHigh, _Digits) + "\n";
      status += "亚盘低点: " + DoubleToString(asianLow, _Digits) + "\n";
      status += "区间点数: " + DoubleToString(asianHigh - asianLow, _Digits) + "\n";
   }
   else
   {
      status += "区间状态: 未建立\n";
   }
   
   status += "------------------------------------\n";
   status += "今日已交易: " + (tradedToday ? "是" : "否") + "\n";
   
   // 显示当前持仓
   if(PositionSelect(_Symbol))
   {
      long posType = PositionGetInteger(POSITION_TYPE);
      double posProfit = PositionGetDouble(POSITION_PROFIT);
      status += "持仓方向: " + (posType == POSITION_TYPE_BUY ? "做多" : "做空") + "\n";
      status += "当前盈亏: " + DoubleToString(posProfit, 2) + "\n";
   }
   else
   {
      status += "当前持仓: 无\n";
   }
   
   Comment(status);
}

//+------------------------------------------------------------------+
//| 判断是否在亚盘时段                                                |
//+------------------------------------------------------------------+
bool IsAsianSession(int hour)
{
   if(InpAsianStartHour < InpAsianEndHour)
   {
      // 不跨日,例如 8:00 - 14:00
      return (hour >= InpAsianStartHour && hour < InpAsianEndHour);
   }
   else
   {
      // 跨日,例如 22:00 - 02:00
      return (hour >= InpAsianStartHour || hour < InpAsianEndHour);
   }
}
//+------------------------------------------------------------------+

作品说明

问题说明

你给的是 Pine Script 代码(TradingView 专用语言),但要求编译的是 MQL5(MetaTrader 5 专用语言)。这是两种完全不同的编程语言,语法和函数库都不兼容。

我现在重新用 MQL5 写一个完整的黄金亚欧盘突破 EA,实现相同的交易逻辑:

  • 亚盘时段(北京时间 8:00-14:00)记录最高最低价
  • 欧盘开盘后突破区间上沿做多、下沿做空
  • 止损放在区间另一侧,止盈是止损的 2 倍
  • 固定手数 0.1,魔术号区分,同时只持一单

使用说明

1. 安装方法

  • 打开 MetaEditor(在 MT5 中按 F4)
  • 点击"文件" → "新建" → "EA交易(Expert Advisor)"
  • 删除模板代码,粘贴上面的完整代码
  • 点击"编译"按钮(F7),确保 0 错误 0 警告
  • 在 MT5 图表上右键 → "EA交易" → "Asian_Breakout_Gold_EA" → 拖拽到图表

2. 参数调整

  • 魔术号:默认 888888,如果同时运行多个 EA,需要设置不同的魔术号避免冲突
  • 固定手数:默认 0.1 手,根据账户大小调整(小账户建议 0.01-0.05)
  • 亚盘时段:默认 8:00-14:00(北京时间),可根据观察到的箱体形成时段调整
  • 时区偏移:北京时间=8,纽约时间=-5,伦敦时间=0(夏令时需+1)
  • 止盈倍数:默认 2 倍(风险回报比 1:2),激进可调到 1.5,保守可调到 3
  • 突破确认方式:勾选=收盘价突破(更保守),不勾选=触及即突破(更激进)

3. 信号识别

  • 右上角信息面板实时显示:当前亚盘区间、是否已交易、持仓状态
  • 亚盘时段(8:00-14:00):EA 会持续记录最高价和最低价
  • 欧盘时段(14:00 之后):价格突破区间上沿触发做多,突破下沿触发做空
  • 止损自动设置在区间另一侧,止盈是止损距离的 2 倍
  • 每天只交易一次,开仓后不再接受新信号,直到第二天重置

4. 重要注意事项

  • ⚠️ 时区设置至关重要:MT5 服务器时间通常是 UTC+2 或 UTC+3(夏令时),需要根据你的经纪商调整"时区偏移"参数。如果经纪商服务器是 UTC+3,北京时间是 UTC+8,那么偏移应该设置为 8-3=5
  • ⚠️ 先在模拟账户测试:至少观察 1-2 周,确认亚盘区间识别准确、开仓时机正确
  • ⚠️ 窄区间风险:如果亚盘波动极小(区间<10 点),假突破概率大,建议手动暂停 EA
  • ⚠️ 滑点和点差:黄金点差通常较大(3-5 美元),实际成交价可能与信号价有偏差
  • ⚠️ 单笔限制:代码已实现"每天只交易一次"和"同时只持一单"的逻辑,防止过度交易
  • 建议配合资金管理:账户余额 < $1000 用 0.01 手,$1000-$5000 用 0.05 手,$5000+ 用 0.1 手
  • 如果连续亏损 3 天,暂停 EA 并检查市场环境(震荡市不适合突破策略)

AI 解读根据源码逐行分析写成,供参考,以实际运行为准

这是什么

这是一个基于亚盘区间突破的 MT5 自动交易 EA,专为黄金等波动品种设计。它在北京时间 8:00-14:00 记录最高最低价形成箱体,欧盘开盘后(14:00 之后)价格突破箱体上沿做多、下沿做空,止损设在箱体另一端,止盈是止损距离的 2 倍。每天只交易一次,固定 0.1 手开仓。

逻辑原理

亚盘时段(默认 8:00-14:00)黄金通常窄幅震荡形成箱体,EA 持续记录这段时间内的最高价和最低价作为区间上下沿。到欧盘时段(14:00 之后),流动性增加波动放大,当价格突破区间上沿时做多,突破下沿时做空。

开仓逻辑有两种:默认使用收盘价确认突破(前一根 K 线收盘价在区间内,当前根收盘价突破区间),更保守防假突破;也可切换为触及即突破(当前 K 线最高价超过上沿或最低价跌破下沿),更激进。

止损直接设在区间另一端(做多时止损=亚盘低点,做空时止损=亚盘高点),止盈距离是止损的 2 倍(默认 1:2 风险回报比)。开仓后当天不再接受新信号,直到第二天凌晨重置区间。同一时间只持一单,有仓位时不再开新仓。

参数说明

  • 魔术号 InpMagicNumber(默认 888888):区分不同 EA 的订单标识,同时运行多个 EA 时必须设置不同值。
  • 固定手数 InpLotSize(默认 0.1):每次开仓手数,小账户建议 0.01-0.05,大账户可用 0.1-0.5。
  • 亚盘开始时间 InpAsianStartHour(默认 8):亚盘区间起始小时,北京时间 8 点。
  • 亚盘结束时间 InpAsianEndHour(默认 14):亚盘区间结束小时,北京时间 14 点,之后开始监测突破。
  • 时区偏移 InpTimezoneOffset(默认 8):关键参数,北京时间相对 UTC 的偏移量(UTC+8=8)。MT5 服务器时间通常是 UTC+2 或 UTC+3,需根据经纪商调整,例如服务器 UTC+3 时偏移应设 8-3=5。
  • 止盈止损比例 InpRiskRewardRatio(默认 2.0):止盈是止损距离的倍数,默认 2 倍即 1:2,激进可调 1.5,保守可调 3。
  • 收盘价确认突破 InpUseCloseBreakout(默认 true):勾选用收盘价确认突破更保守,不勾选触及即突破更激进。
  • 允许滑点 InpSlippage(默认 30):允许的最大滑点点数,黄金点差大时可放宽到 50。
  • 订单备注 InpTradeComment(默认"亚欧盘突破"):订单注释文字。

怎么用

在 MT5 中按 F4 打开 MetaEditor,新建 EA 文件,粘贴代码后按 F7 编译。拖到黄金图表上(XAUUSD 或 GOLD),在弹出窗口勾选"允许自动交易",点击确定。右上角会显示实时信息面板,包括亚盘区间高低点、今日是否已交易、当前持仓状态。

建议先在模拟账户跑 1-2 周观察,重点检查时区设置是否正确(区间时间是否对应实际亚盘)、突破时机是否合理。确认无误后再用小手数(0.01-0.05)实盘测试。EA 自动处理开平仓和止盈止损,无需人工干预。

建议使用 M5 或 M15 周期图表,太小的周期(M1)容易被噪音触发假突破,太大的周期(H1)反应滞后错过最佳入场点。

适用场景

适合黄金(XAUUSD)这类亚盘震荡、欧美盘放量的品种,也可用于原油(XTIUSD / XBRUSD)、欧美(EURUSD)等。最佳周期是 M5-M15,能兼顾信号及时性和过滤噪音。

策略在趋势初期效果好,欧盘单边突破时能吃到较大波段。不适合全天震荡市(区间内反复穿越不成趋势)和重大新闻前后(价格剧烈跳空导致止损失效)。如果亚盘区间极窄(小于 10 点),假突破概率大,建议当天暂停 EA。

固定手数 + 固定止损距离的方式在大波动日风险可控,但小波动日可能频繁触及止损。适合日内波段交易风格,不适合超短线剥头皮(滑点和点差侵蚀利润)。

风险提示

时区配置风险:时区偏移设置错误会导致区间记录时段完全错位,例如把欧盘当亚盘记录。必须根据经纪商服务器时间(通常在图表左下角显示)反推偏移量,用 TimeCurrent() 对比北京时间验证。

滑点和点差:黄金点差通常 3-5 美元,重大新闻时可能扩大到 10+ 美元。实际成交价可能偏离信号价,尤其是市价单在快速行情中滑点明显。代码允许 30 点滑点,不够时可调大但要接受更差的入场价。

假突破:亚盘区间窄时(波动小于 10 点),欧盘初期容易出现扫单式假突破(突破后立即回撤)。代码已用收盘价确认减少此类风险,但无法完全避免。连续亏损 2-3 天时应暂停观察市场状态。

单日单次限制:代码限制每天只交易一次,开仓后即使止损出场也不再进场。这防止过度交易,但也可能错过当天后续机会。如果希望止损后可再次入场,需修改 tradedToday 的重置逻辑。

止盈比例固定:1:2 风险回报比在趋势日能充分获利,但震荡日可能因止盈过远而回吐浮盈最终触发止损。如果市场波动减小,可手动调整比例到 1.5 或 1:1。

无持仓管理:代码不做移动止损、分批止盈等持仓优化,完全依赖初始止盈止损。大波动日可能提前止盈离场错失后续利润。需要高级功能的交易者需自行修改代码或手动管理。

常见问题

时区偏移怎么设置?我的 MT5 显示的是 GMT+2
MT5 服务器时间通常是 UTC+2(冬令时)或 UTC+3(夏令时),北京时间是 UTC+8。如果你的服务器是 GMT+2,偏移量应设为 8-2=6;如果是 GMT+3(夏令时),应设为 8-3=5。可以在 EA 运行时对比面板显示的"当前时间"和实际北京时间验证。
为什么有时候明明突破了但 EA 没开仓?
代码默认使用收盘价确认突破(InpUseCloseBreakout=true),必须前一根 K 线收盘价在区间内、当前根收盘价突破区间才触发。如果只是 K 线影线触及区间但收盘价未突破,不会开仓。可以把参数改为 false 切换为触及即突破,但假信号会增多。
可以用在黄金以外的品种吗?参数需要调整吗?
代码没有限制品种,理论上可用于任何有亚盘震荡特征的品种(原油、欧美等)。但不同品种的波动幅度和点差不同,固定手数和时段可能不适用。例如欧美点差小可以用更大手数,原油可能需要调整亚盘时段为美盘休市时间。建议先模拟测试再实盘。
这个 EA 会重绘历史信号吗?
不会。区间在亚盘结束时已确定,突破信号基于实时价格判断,不依赖未来数据。但历史回测时由于时区转换和服务器时间差异,回测结果可能与实盘略有不同。测试时以模拟盘实时运行为准。
止损被打后当天还能再进场吗?
不能。代码设定每天只交易一次(tradedToday=true 后不再检测信号),即使止损出场也要等第二天重置。这是为了防止震荡市反复开仓亏损。如果想允许多次进场,需要修改 tradedToday 的逻辑或在止损后手动重置变量。

Asian Session Breakout EA for MT5

An automated EA that tracks Asian session (8:00-14:00 Beijing time) high/low range and enters long/short trades on European session breakouts. Features 1:2 risk-reward ratio, fixed lot size, and one-trade-per-day limit for gold intraday trading.

Source code is shown above. Compiled EX5 files are available to VIP members.

评论

后可以留言,比如反馈用着怎么样、想加什么功能。

还没有人评论,来抢个沙发。