feat: 突破交易策略
This commit is contained in:
@@ -23,7 +23,6 @@ input double InpStopLossPercent = 0.02; // 止损百分比(%)
|
|||||||
input int InpMinStopLossPoints = 10; // 最小止损点数
|
input int InpMinStopLossPoints = 10; // 最小止损点数
|
||||||
input double InpRiskRewardRatio = 1.2; // 盈亏比
|
input double InpRiskRewardRatio = 1.2; // 盈亏比
|
||||||
input bool InpUseTrailingStop = false; // 使用移动止损
|
input bool InpUseTrailingStop = false; // 使用移动止损
|
||||||
input int InpMaxHoldingMinutes = 5; // 最大持仓时间(分钟)
|
|
||||||
|
|
||||||
input group "=== 仓位管理参数 ==="
|
input group "=== 仓位管理参数 ==="
|
||||||
input bool InpUseCompounding = true; // 使用复利模式
|
input bool InpUseCompounding = true; // 使用复利模式
|
||||||
@@ -40,6 +39,7 @@ input group "=== 调试选项 ==="
|
|||||||
input bool InpShowDebugInfo = false; // 显示调试信息
|
input bool InpShowDebugInfo = false; // 显示调试信息
|
||||||
input bool InpShowMarkers = true; // 显示极值点标记
|
input bool InpShowMarkers = true; // 显示极值点标记
|
||||||
input int InpMagicNumber = 20260516; // EA魔术号
|
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();
|
double CalculateLotSize();
|
||||||
void ManagePositions();
|
void ManagePositions();
|
||||||
void CheckTrailingStop(ulong ticket);
|
void CheckTrailingStop(ulong ticket);
|
||||||
|
void CheckAndCloseManualOrders();
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Expert initialization function |
|
//| Expert initialization function |
|
||||||
@@ -122,7 +123,6 @@ int OnInit()
|
|||||||
Print("反向突破容忍度: 0% (禁用 - 保持原有逻辑)");
|
Print("反向突破容忍度: 0% (禁用 - 保持原有逻辑)");
|
||||||
Print("止损:", InpStopLossPercent, "% (最小", InpMinStopLossPoints, "点) | 盈亏比:", InpRiskRewardRatio);
|
Print("止损:", InpStopLossPercent, "% (最小", InpMinStopLossPoints, "点) | 盈亏比:", InpRiskRewardRatio);
|
||||||
Print("移动止损:", (InpUseTrailingStop ? "启用" : "禁用"));
|
Print("移动止损:", (InpUseTrailingStop ? "启用" : "禁用"));
|
||||||
Print("最大持仓时间:", InpMaxHoldingMinutes, "分钟");
|
|
||||||
Print("最大开仓手数:", InpMaxPositions);
|
Print("最大开仓手数:", InpMaxPositions);
|
||||||
Print("单方向持仓限制:", (InpOnePositionPerDirection ? "启用 (每方向最多1单)" : "禁用"));
|
Print("单方向持仓限制:", (InpOnePositionPerDirection ? "启用 (每方向最多1单)" : "禁用"));
|
||||||
if(InpConsecutiveLosses > 0 && InpFreezeBarCount > 0)
|
if(InpConsecutiveLosses > 0 && InpFreezeBarCount > 0)
|
||||||
@@ -131,6 +131,7 @@ int OnInit()
|
|||||||
Print("连续亏损保护: 禁用");
|
Print("连续亏损保护: 禁用");
|
||||||
Print("手数模式:", (InpUseCompounding ? "复利" : "固定"),
|
Print("手数模式:", (InpUseCompounding ? "复利" : "固定"),
|
||||||
InpUseCompounding ? StringFormat(" (每500$开%.2f手)", InpLotsPer500) : StringFormat(" (%.2f手)", InpFixedLots));
|
InpUseCompounding ? StringFormat(" (每500$开%.2f手)", InpLotsPer500) : StringFormat(" (%.2f手)", InpFixedLots));
|
||||||
|
Print("禁止手工单:", (InpCloseManualOrders ? "启用 (自动平掉手工单)" : "禁用"));
|
||||||
Print("========================================");
|
Print("========================================");
|
||||||
|
|
||||||
return(INIT_SUCCEEDED);
|
return(INIT_SUCCEEDED);
|
||||||
@@ -228,13 +229,17 @@ void OnTradeTransaction(const MqlTradeTransaction& trans,
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OnTick()
|
void OnTick()
|
||||||
{
|
{
|
||||||
// 1. 更新最新有效波段
|
// 1. 检查并关闭手工单(如果启用)
|
||||||
|
if(InpCloseManualOrders)
|
||||||
|
CheckAndCloseManualOrders();
|
||||||
|
|
||||||
|
// 2. 更新最新有效波段
|
||||||
UpdateLatestValidWave();
|
UpdateLatestValidWave();
|
||||||
|
|
||||||
// 2. 检查开仓信号
|
// 3. 检查开仓信号
|
||||||
CheckOpenSignals();
|
CheckOpenSignals();
|
||||||
|
|
||||||
// 3. 管理已有持仓
|
// 4. 管理已有持仓
|
||||||
ManagePositions();
|
ManagePositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,17 +840,6 @@ void ManagePositions()
|
|||||||
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber)
|
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber)
|
||||||
continue;
|
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);
|
ulong ticket = PositionGetTicket(i);
|
||||||
CheckTrailingStop(ticket);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
- 连续亏损次数触发冷冻:默认 **3**(设为0可禁用该功能)
|
- 连续亏损次数触发冷冻:默认 **3**(设为0可禁用该功能)
|
||||||
- 冷冻K线根数:默认 **60**(设为0可禁用该功能)
|
- 冷冻K线根数:默认 **60**(设为0可禁用该功能)
|
||||||
|
|
||||||
|
### 手工单管理参数
|
||||||
|
- 禁止手工单:默认 **true**(自动平掉所有手工单)
|
||||||
|
|
||||||
## 补充说明
|
## 补充说明
|
||||||
|
|
||||||
### 突破K线处理
|
### 突破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会继续尝试平仓
|
||||||
|
|
||||||
### 反向突破容忍度(新功能)⭐
|
### 反向突破容忍度(新功能)⭐
|
||||||
|
|
||||||
**问题背景:**
|
**问题背景:**
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user