feat: 突破交易策略

This commit is contained in:
zhangyangbin
2026-05-18 09:17:40 +08:00
parent c585afb8d4
commit 7dce510996
5 changed files with 121 additions and 16 deletions
+39 -16
View File
@@ -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 number0表示手工单
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());
}
}
}
}
+82
View File
@@ -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 类型:多单
情况2EA自动开了1个多单(magic=20260516
- EA检测到magic != 0,确认是EA自己开的单
- 不会平仓,正常管理(移动止损等)
情况3:其他EA开的单(magic=99999
- EA检测到magic != 0,确认不是手工单
- 不会平仓,但也不会管理
```
**注意事项:**
1. **仅处理当前品种**
- 只平掉当前EA运行品种的手工单
- 不会影响其他品种的手工单
2. **实时检测**
- 每个Tick都会检查
- 手工单会在极短时间内被平掉
3. **与其他功能的关系**
- 不影响EA自身的开仓逻辑
- 不影响EA的风险管理功能
- 可配合所有其他参数使用
4. **平仓失败处理**
- 如果平仓失败(网络问题等),会打印错误日志
- 下一个Tick会继续尝试平仓
### 反向突破容忍度(新功能)⭐
**问题背景:**
Binary file not shown.
Binary file not shown.
Binary file not shown.