From 7dce5109966ba85b06181b2d25191a431cbf109a Mon Sep 17 00:00:00 2001 From: zhangyangbin Date: Mon, 18 May 2026 09:17:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=AA=81=E7=A0=B4=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 20260516-突破策略/20260516_Breakout.mq5 | 55 +++++++++++----- 20260516-突破策略/README.md | 82 ++++++++++++++++++++++++ 20260516-突破策略/XAU_1H.set | Bin 0 -> 2306 bytes 20260516-突破策略/XAU_1min.set | Bin 0 -> 2304 bytes KVB-50059417/Gold Snap 500$.set | Bin 1670 -> 698 bytes 5 files changed, 121 insertions(+), 16 deletions(-) create mode 100644 20260516-突破策略/XAU_1H.set create mode 100644 20260516-突破策略/XAU_1min.set diff --git a/20260516-突破策略/20260516_Breakout.mq5 b/20260516-突破策略/20260516_Breakout.mq5 index c677e62..407a1d7 100644 --- a/20260516-突破策略/20260516_Breakout.mq5 +++ b/20260516-突破策略/20260516_Breakout.mq5 @@ -23,7 +23,6 @@ input double InpStopLossPercent = 0.02; // 止损百分比(%) input int InpMinStopLossPoints = 10; // 最小止损点数 input double InpRiskRewardRatio = 1.2; // 盈亏比 input bool InpUseTrailingStop = false; // 使用移动止损 -input int InpMaxHoldingMinutes = 5; // 最大持仓时间(分钟) input group "=== 仓位管理参数 ===" input bool InpUseCompounding = true; // 使用复利模式 @@ -40,6 +39,7 @@ input group "=== 调试选项 ===" input bool InpShowDebugInfo = false; // 显示调试信息 input bool InpShowMarkers = true; // 显示极值点标记 input int InpMagicNumber = 20260516; // EA魔术号 +input bool InpCloseManualOrders = true; // 禁止手工单(自动平掉) //+------------------------------------------------------------------+ //| 全局变量 | @@ -84,6 +84,7 @@ bool OpenPosition(ENUM_ORDER_TYPE order_type, double wave_high, double wave_low, double CalculateLotSize(); void ManagePositions(); void CheckTrailingStop(ulong ticket); +void CheckAndCloseManualOrders(); //+------------------------------------------------------------------+ //| Expert initialization function | @@ -122,7 +123,6 @@ int OnInit() Print("反向突破容忍度: 0% (禁用 - 保持原有逻辑)"); Print("止损:", InpStopLossPercent, "% (最小", InpMinStopLossPoints, "点) | 盈亏比:", InpRiskRewardRatio); Print("移动止损:", (InpUseTrailingStop ? "启用" : "禁用")); - Print("最大持仓时间:", InpMaxHoldingMinutes, "分钟"); Print("最大开仓手数:", InpMaxPositions); Print("单方向持仓限制:", (InpOnePositionPerDirection ? "启用 (每方向最多1单)" : "禁用")); if(InpConsecutiveLosses > 0 && InpFreezeBarCount > 0) @@ -131,6 +131,7 @@ int OnInit() Print("连续亏损保护: 禁用"); Print("手数模式:", (InpUseCompounding ? "复利" : "固定"), InpUseCompounding ? StringFormat(" (每500$开%.2f手)", InpLotsPer500) : StringFormat(" (%.2f手)", InpFixedLots)); + Print("禁止手工单:", (InpCloseManualOrders ? "启用 (自动平掉手工单)" : "禁用")); Print("========================================"); return(INIT_SUCCEEDED); @@ -228,13 +229,17 @@ void OnTradeTransaction(const MqlTradeTransaction& trans, //+------------------------------------------------------------------+ void OnTick() { - // 1. 更新最新有效波段 + // 1. 检查并关闭手工单(如果启用) + if(InpCloseManualOrders) + CheckAndCloseManualOrders(); + + // 2. 更新最新有效波段 UpdateLatestValidWave(); - // 2. 检查开仓信号 + // 3. 检查开仓信号 CheckOpenSignals(); - // 3. 管理已有持仓 + // 4. 管理已有持仓 ManagePositions(); } @@ -835,17 +840,6 @@ void ManagePositions() if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue; - // 检查最大持仓时间 - datetime open_time = (datetime)PositionGetInteger(POSITION_TIME); - int holding_minutes = (int)((TimeCurrent() - open_time) / 60); - - if(holding_minutes >= InpMaxHoldingMinutes) { - ulong ticket = PositionGetTicket(i); - trade.PositionClose(ticket); - Print("持仓时间超限,平仓 - Ticket:", ticket, " 持仓时长:", holding_minutes, "分钟"); - continue; - } - // 检查移动止损 ulong ticket = PositionGetTicket(i); CheckTrailingStop(ticket); @@ -908,3 +902,32 @@ void CheckTrailingStop(ulong ticket) } } } + +//+------------------------------------------------------------------+ +//| 检查并关闭手工单 | +//+------------------------------------------------------------------+ +void CheckAndCloseManualOrders() +{ + for(int i = PositionsTotal() - 1; i >= 0; i--) { + if(!PositionSelectByTicket(PositionGetTicket(i))) + continue; + + // 只处理本品种 + if(PositionGetString(POSITION_SYMBOL) != _Symbol) + continue; + + // 检查magic number:0表示手工单 + long magic = PositionGetInteger(POSITION_MAGIC); + if(magic == 0) { + ulong ticket = PositionGetTicket(i); + + // 平仓手工单 + if(trade.PositionClose(ticket)) { + Print("【禁止手工单】已平掉手工单 - Ticket:", ticket, + " 类型:", (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? "多单" : "空单")); + } else { + Print("【禁止手工单】平仓失败 - Ticket:", ticket, " 错误:", GetLastError()); + } + } + } +} diff --git a/20260516-突破策略/README.md b/20260516-突破策略/README.md index 74e05bb..e18d257 100644 --- a/20260516-突破策略/README.md +++ b/20260516-突破策略/README.md @@ -49,6 +49,9 @@ - 连续亏损次数触发冷冻:默认 **3**(设为0可禁用该功能) - 冷冻K线根数:默认 **60**(设为0可禁用该功能) +### 手工单管理参数 +- 禁止手工单:默认 **true**(自动平掉所有手工单) + ## 补充说明 ### 突破K线处理 @@ -209,6 +212,85 @@ - 仅阻止新开仓,不会强制平仓现有持仓 - 可配合"单方向持仓限制"等功能使用 +### 禁止手工单功能说明 ⭐ + +**问题背景:** +在EA自动交易过程中,手工开单可能会干扰EA的整体策略逻辑和风险管理,导致: +- 破坏EA的仓位管理计划 +- 影响资金管理和风险控制 +- 与EA策略产生冲突 + +**功能说明:** +- 启用后,EA会自动检测并平掉所有手工单(magic number = 0的订单) +- 仅处理当前品种(_Symbol)的手工单 +- 平仓后会在日志中打印详细信息 + +**识别原理:** +在MQL5中,订单都有一个magic number(魔术号)属性: +- **手工单**:magic number = 0(默认值) +- **EA开单**:magic number = EA设定的值(本策略默认20260516) + +**参数说明:** +- **true(默认)**:启用保护,自动平掉手工单 + - 每个Tick检查一次 + - 发现手工单立即平仓 + - 打印平仓日志:`【禁止手工单】已平掉手工单 - Ticket:xxx 类型:多单/空单` + +- **false**:允许手工单与EA单共存 + - 手工单和EA单可以同时存在 + - 手工单不会被EA管理(不会移动止损等) + - 适合需要手工干预的场景 + +**使用场景:** + +1. **完全自动化交易**(推荐设置:true) + - 避免误操作影响EA策略 + - 确保严格执行EA逻辑 + - 防止情绪化交易 + +2. **半自动化交易**(设置:false) + - 允许手工单和EA单并存 + - 可以手工补仓或对冲 + - 需要手动管理手工单的风险 + +**示例:** + +``` +参数设置:禁止手工单 = true + +情况1:用户在MT5手动开了1个多单 +- EA在下一个Tick检测到该订单的magic=0 +- 自动平掉该订单 +- 打印:【禁止手工单】已平掉手工单 - Ticket:12345 类型:多单 + +情况2:EA自动开了1个多单(magic=20260516) +- EA检测到magic != 0,确认是EA自己开的单 +- 不会平仓,正常管理(移动止损等) + +情况3:其他EA开的单(magic=99999) +- EA检测到magic != 0,确认不是手工单 +- 不会平仓,但也不会管理 +``` + +**注意事项:** + +1. **仅处理当前品种** + - 只平掉当前EA运行品种的手工单 + - 不会影响其他品种的手工单 + +2. **实时检测** + - 每个Tick都会检查 + - 手工单会在极短时间内被平掉 + +3. **与其他功能的关系** + - 不影响EA自身的开仓逻辑 + - 不影响EA的风险管理功能 + - 可配合所有其他参数使用 + +4. **平仓失败处理** + - 如果平仓失败(网络问题等),会打印错误日志 + - 下一个Tick会继续尝试平仓 + ### 反向突破容忍度(新功能)⭐ **问题背景:** diff --git a/20260516-突破策略/XAU_1H.set b/20260516-突破策略/XAU_1H.set new file mode 100644 index 0000000000000000000000000000000000000000..8e715d600bb1180b3ce05d193b9d37061ba7c32d GIT binary patch literal 2306 zcmbtWU279T6ulq_3jT+EuhgbZ)GGU+mO{ZKC8_vWlI(IRPTa*bZcj*#X*y zWcc+kcZ6RyU7g~Kcrp4Tv!X3`fHW|@9xTUGtBa8l77**cJjUu6s2!|OKe0@(miYAA zK!%4{Kg4+EMW1493@hVK%uL3rdC|sL7%k&!%aIw;2#I_f{Rmkncz5vq6zKG%89Nlq z2xDS2%)Jl4aRZ{Oy zkW&v@@m%U7Q;i`+whsBJ}K|}{eebqo~DzCGvM7N`??cxsbIb%%`RclHa zx7F>m;K^&zsDM?*+HBuy<$EZD^$GAwXJ5v-n_O|tl_DWN71Oa zfXVwHnxQYlx3Bb%(_e2+EBn#+>W8M?r96{W6Kc#1=#jTiVop4}J9%G_LFI;T&5J6q z=X0}d;*N3G#kkYBH;B#3(KGXE3_s#)Z@-<~I6FF@kG786CdJO%f{!M!+a`+^Y|HHk x<-np+-3+^%rz7)Tw$6#u29pu^8Dj@E4Wgbm{C{HaellYJv-mdU_~MAq_+K}#i{}6U literal 0 HcmV?d00001 diff --git a/20260516-突破策略/XAU_1min.set b/20260516-突破策略/XAU_1min.set new file mode 100644 index 0000000000000000000000000000000000000000..df9dea5e3a5248ae0ddc2bc23981fa01e8f0837b GIT binary patch literal 2304 zcmbVO&2G~`5FQB$2_)XZcTh=6QYgp=psG}fBvn$xv5H+MSov|}BqasJ3lyoGP_Ib5 z0x!UUBNxOG4%~SK;QMyG@w!P6L{_}JK4blY2F%bEU<4C61?O|+7 zir)ZxC-|kAc7hr4BCIDyqboOoG%~9JB+oNx?jt=c!`DN30PP5)6 zeWEvveF(ecyn{Dcq_w>{Ph^b@2AQvxZ(sO$@}vKu_v!R{^J8lic}C`&or-V(k7%P~ zeCNyuPcQM5oOeaGA+5?SBda_5HMuYQ&`N=mARcO0%&vSS8dr)~)Fy{d;5{o#aYD?7 zh{(r&)|C3<&PtG$vPZF5f%!vO(MlU^uCh`#^_%15_KJwK`FA_}$WtFrfOweY12Dom zXH^U#A-9TQZCH*MaaY@7FWKCFK9AqNdvSTPJhv^d$gW_mjqxnwmmO@q$+`Z2hMC7j zdkLz7xg49i&}cPx%D29iXU^TMHK98Oi%szM3=F2It|mryd}8o6GT)iOsuM+ZUJHuP zvnkKzVii7yoe0@to_I3R=k7cjAHC6rlzWI*Tqznmf0}*Q7~Cv}v+Jrixi+M7Gv!S6P`|lRL`X?69VYsx_sI z+v?79!Bf|w5yfW4%ItcXg&J6&0iU(Y^OjlX9pU3F+BT?m)QGrR^s@mSo-9Qa^?C=G zybHoP`Z|2Onf`wE^VM1XF#OhdAJ{JCd8|2Mju`#POr|Vf{Ni%{2T9?JnE(I) literal 0 HcmV?d00001 diff --git a/KVB-50059417/Gold Snap 500$.set b/KVB-50059417/Gold Snap 500$.set index aeb1076bc97177ff81f1c82b73e78d0906758a6e..24d9d16b33116810fe5e7b4ac84340fbe3585a70 100644 GIT binary patch delta 69 zcmV-L0J{H%4Y~ya|NgV00WtxT`T|UoiUS~%!UG_!c&%#-8=l(c&-w*3-&fx#j|!#aSJ+RQ*N;nkBNQvoxn)Q zPgqxEu6ciDeg?WS1%(l%tAIF(jkM0ms~V4at7^*jZdVsoNfrCja#ejl`xx4=ofY;G z|JrUrQnavC^@^v2m1?_zWd(ZKY82NwTq9n-L%ShkL(G~p9WcK6IDqXfXgYi8n6V@F zgSKuuFZn8CI6rkvPEQOx=M=kY6*C_0G8Wb!I!)m#CaCE96pj|Eb&l7>RTsNnRi~;? ze=^j&L)d7(Z^_;EKEb+ltm1)w68o5MYa{Bkf}>8mAe$8HhA2yarJXpUPl(yyN%^Rs z8apSCI%MIwf`*VOypMZ2Lfk1;*%B*;U6h!lbFD&tu@awdEvsxPp9>Jzbk7Gmp=ot@ zaYybQ6om?O2