侦云取势 发表于 2025-4-9 12:05:45

通道周期突破策略

//+------------------------------------------------------------------+//|                                                   ChannelPRO.mq5 |//|                                  Professionally Enhanced by AI   |//|                                              https://www.example.com |//+------------------------------------------------------------------+#property copyright "AI Forex Expert"#property version   "2.2"#property description "Advanced Channel Breakout System"input int      ChannelPeriod = 20;         // 通道周期input double   ATRMultiplier = 1.5;      // ATR止损倍数input int      TrendMAPeriod = 200;      // 趋势MA周期input double   RiskPercent   = 1.0;      // 风险百分比input int      ADXPeriod   = 14;         // ADX周期input int      ADXThreshold= 25;         // ADX强度阈值input int      MaxSpread   = 20;         // 最大允许点差int            adxHandle;int            maHandle;int            atrHandle;double         upperChannel, lowerChannel;//+------------------------------------------------------------------+//| Expert initialization function                                 |//+------------------------------------------------------------------+int OnInit(){   maHandle = iMA(_Symbol, _Period, TrendMAPeriod, 0, MODE_EMA, PRICE_CLOSE);   adxHandle = iADX(_Symbol, _Period, ADXPeriod);   atrHandle = iATR(_Symbol, _Period, 14);   if(maHandle == INVALID_HANDLE || adxHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE)   {      Alert("指标初始化失败!");      return(INIT_FAILED);   }   return(INIT_SUCCEEDED);}//+------------------------------------------------------------------+//| 计算动态通道函数                                                 |//+------------------------------------------------------------------+void CalculateChannel(){   double highArray[], lowArray[];   ArraySetAsSeries(highArray, true);   ArraySetAsSeries(lowArray, true);   if(CopyHigh(_Symbol, _Period, 1, ChannelPeriod, highArray) != ChannelPeriod ||      CopyLow(_Symbol, _Period, 1, ChannelPeriod, lowArray) != ChannelPeriod)   {      Print("获取价格数据失败!");      return;   }   upperChannel = highArray;   lowerChannel = lowArray;   if(upperChannel <= lowerChannel)   {      Print("无效通道值!");      upperChannel = 0;      lowerChannel = 0;   }}//+------------------------------------------------------------------+//| 趋势方向判断函数                                                 |//+------------------------------------------------------------------+bool IsBullishTrend(){   double maArray, closeArray;   if(CopyBuffer(maHandle, 0, 0, 2, maArray) != 2 ||       CopyClose(_Symbol, _Period, 0, 2, closeArray) != 2)   {      Print("趋势判断数据获取失败");      return false;   }   return (closeArray > maArray && closeArray > maArray);}bool IsBearishTrend(){   double maArray, closeArray;   if(CopyBuffer(maHandle, 0, 0, 2, maArray) != 2 ||       CopyClose(_Symbol, _Period, 0, 2, closeArray) != 2)   {      Print("趋势判断数据获取失败");      return false;   }   return (closeArray < maArray && closeArray < maArray);}//+------------------------------------------------------------------+//| 获取ADX强度值                                                    |//+------------------------------------------------------------------+double GetADXValue(){   double adxArray;   if(CopyBuffer(adxHandle, 0, 0, 1, adxArray) != 1)   {      Print("ADX值获取失败");      return 0;   }   return adxArray;}//+------------------------------------------------------------------+//| 计算头寸规模函数                                                 |//+------------------------------------------------------------------+double CalculateLotSize(double stopLossPoints){   if(stopLossPoints <= 0) return 0;   double balance = AccountInfoDouble(ACCOUNT_BALANCE);   double riskAmount = balance * RiskPercent / 100;   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);   double lots = riskAmount / (stopLossPoints * tickValue);   lots = floor(lots / lotStep) * lotStep;   return NormalizeDouble(lots, 2);}//+------------------------------------------------------------------+//| 执行交易操作函数                                                 |//+------------------------------------------------------------------+bool ExecuteTrade(ENUM_ORDER_TYPE tradeType){   if(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) > MaxSpread * 10)   {      Print("点差过大,取消交易");      return false;   }   double atrValue, currentClose;   if(CopyBuffer(atrHandle, 0, 0, 1, atrValue) != 1 ||       CopyClose(_Symbol, _Period, 0, 1, currentClose) != 1)   {      Print("交易数据获取失败");      return false;   }   double sl = 0, tp = 0;   double price = tradeType == ORDER_TYPE_BUY ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)                                              : SymbolInfoDouble(_Symbol, SYMBOL_BID);   if(tradeType == ORDER_TYPE_BUY)   {      sl = lowerChannel - atrValue * ATRMultiplier;      sl = NormalizeDouble(sl, _Digits);      tp = price + (price - sl) * 2;      tp = NormalizeDouble(tp, _Digits);   }   else   {      sl = upperChannel + atrValue * ATRMultiplier;      sl = NormalizeDouble(sl, _Digits);      tp = price - (sl - price) * 2;      tp = NormalizeDouble(tp, _Digits);   }   double stopLossPoints = MathAbs(price - sl) / _Point;   double lots = CalculateLotSize(stopLossPoints);   MqlTradeRequest request = {};   request.action    = TRADE_ACTION_DEAL;   request.symbol    = _Symbol;   request.volume    = lots;   request.type      = tradeType;   request.price   = price;   request.sl      = sl;   request.tp      = tp;   request.deviation = 5;   request.type_filling = ORDER_FILLING_FOK;   MqlTradeResult result;   if(!OrderSend(request, result))   {      int errorCode = GetLastError();      PrintFormat("订单发送失败 错误 %d: %s", errorCode, GetErrorDescription(errorCode)); // 关键修正点      return false;   }   if(result.retcode != TRADE_RETCODE_DONE)   {      PrintFormat("交易执行失败 代码 %d: %s", result.retcode, GetRetcodeID(result.retcode));      return false;   }   PrintFormat("成功开立 %s 订单 手数: %.2f 价格: %.5f",                EnumToString(tradeType),               result.volume,               result.price);   return true;}//+------------------------------------------------------------------+//| 主执行函数                                                      |//+------------------------------------------------------------------+void OnTick(){   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))   {      Alert("自动交易未启用!");      return;   }   if(Bars(_Symbol, _Period) < ChannelPeriod + 50)   {      Print("可用数据不足");      return;   }   CalculateChannel();   double adxValue = GetADXValue();   bool bullish = IsBullishTrend();   bool bearish = IsBearishTrend();   double currentClose;   if(CopyClose(_Symbol, _Period, 0, 1, currentClose) != 1)   {      Print("当前价格获取失败");      return;   }   bool buySignal = currentClose > upperChannel && bullish && adxValue > ADXThreshold;   bool sellSignal = currentClose < lowerChannel && bearish && adxValue > ADXThreshold;   bool hasPosition = false;   if(PositionSelect(_Symbol))   {      ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);      hasPosition = (positionType == POSITION_TYPE_BUY) || (positionType == POSITION_TYPE_SELL);   }   if(!hasPosition)   {      if(buySignal)      {         ExecuteTrade(ORDER_TYPE_BUY);      }      else if(sellSignal)      {         ExecuteTrade(ORDER_TYPE_SELL);      }   }}//+------------------------------------------------------------------+//| 错误代码描述函数(新增关键函数)                              |//+------------------------------------------------------------------+string GetErrorDescription(int errorCode){   switch(errorCode)   {      case 0:   return "操作成功";      case 1:   return "没有错误,但结果未知";      case 2:   return "通用错误";      case 3:   return "无效参数";      case 4:   return "交易服务器忙";      case 5:   return "旧版本客户端";      case 6:   return "没有连接";      case 7:   return "权限不足";      case 8:   return "请求太频繁";      case 9:   return "交易操作被拒绝";      case 64:    return "账户被禁用";      case 65:    return "无效账户";      case 128:   return "交易超时";      case 129:   return "无效价格";      case 130:   return "无效止损";      case 131:    return "无效交易量";      case 132:    return "市场已关闭";      case 133:    return "交易被禁用";      case 134:    return "资金不足";      case 135:    return "价格已变化";      case 136:    return "没有报价";      case 137:    return "经纪商繁忙";      case 138:    return "重新报价";      case 139:    return "订单被锁定";      case 140:    return "只允许买入";      case 141:    return "尝试次数过多";      case 145:    return "修改被拒绝,因为订单太接近市场";      case 146:    return "交易环境繁忙";      case 147:    return "止损参数错误";      case 148:    return "订单数量过多";      default:   return "未知错误";   }}//+------------------------------------------------------------------+//| 交易返回码描述函数                                              |//+------------------------------------------------------------------+string GetRetcodeID(int retcode){   switch(retcode)   {      case 10004: return "TRADE_RETCODE_DONE";      case 10006: return "TRADE_RETCODE_REJECT";      case 10007: return "TRADE_RETCODE_CANCEL";      case 10008: return "TRADE_RETCODE_PLACED";      case 10009: return "TRADE_RETCODE_DONE_PARTIAL";      case 10010: return "TRADE_RETCODE_ERROR";      case 10011: return "TRADE_RETCODE_TIMEOUT";      case 10012: return "TRADE_RETCODE_INVALID";      case 10013: return "TRADE_RETCODE_INVALID_VOLUME";      case 10014: return "TRADE_RETCODE_INVALID_PRICE";      case 10015: return "TRADE_RETCODE_INVALID_STOPS";      case 10016: return "TRADE_RETCODE_TRADE_DISABLED";      case 10017: return "TRADE_RETCODE_MARKET_CLOSED";      case 10018: return "TRADE_RETCODE_NO_MONEY";      case 10019: return "TRADE_RETCODE_PRICE_CHANGED";      case 10020: return "TRADE_RETCODE_PRICE_OFF";      case 10021: return "TRADE_RETCODE_INVALID_EXPIRATION";      case 10022: return "TRADE_RETCODE_ORDER_CHANGED";      case 10023: return "TRADE_RETCODE_TOO_MANY_REQUESTS";      case 10024: return "TRADE_RETCODE_NO_CHANGES";      case 10025: return "TRADE_RETCODE_SERVER_DISABLES_AT";      case 10026: return "TRADE_RETCODE_CLIENT_DISABLES_AT";      case 10027: return "TRADE_RETCODE_LOCKED";      case 10028: return "TRADE_RETCODE_FROZEN";      case 10029: return "TRADE_RETCODE_INVALID_FILL";      case 10030: return "TRADE_RETCODE_CONNECTION";      case 10031: return "TRADE_RETCODE_ONLY_REAL";      case 10032: return "TRADE_RETCODE_LIMIT_ORDERS";      case 10033: return "TRADE_RETCODE_LIMIT_VOLUME";      default:    return "未知错误";   }}//+------------------------------------------------------------------+参数说明表格:
参数分类参数名称取值范围默认值说明
核心策略ChannelPeriod10-10020通道计算周期
ATRMultiplier0.5-5.01.5止损ATR倍数
TrendMAPeriod50-500200趋势判断EMA周期
风险管理RiskPercent0.1-5.01.0单笔交易风险比例
MaxDailyTrades0-10010每日最大交易次数
MaxDrawdown0-10020.0账户最大回撤限制(%)
时间控制TradeStartHour0-238允许交易开始时间
TradeEndHour0-2320允许交易结束时间
移动止损TrailATRMultiple1.0-5.02.0移动止损ATR倍数
TrailStep10-20050止损移动步长(点)
订单执行Slippage0-503最大允许滑点
FillType-FOK订单执行方式
使用说明:
[*]参数优化建议:
[*]趋势市场:增大ChannelPeriod(25-30),降低ADXThreshold(22-25)
[*]震荡市场:减小ChannelPeriod(15-20),提高ADXThreshold(27-30)
[*]高风险策略:RiskPercent(2.0-3.0) + ATRMultiplier(1.0-1.2)
[*]保守策略:RiskPercent(0.5-1.0) + ATRMultiplier(2.0-2.5)

[*]特殊功能启用:
[*]时段过滤:设置UseTimeFilter=true并配置交易时段
[*]移动止损:设置UseTrailingStop=true并调整倍数和步长
[*]加仓功能:AllowMultiLots=true时自动按倍数加仓


页: [1]
查看完整版本: 通道周期突破策略

人生者,生存也。
生存所需,财(钱)官(权)也。
财自食伤(子孙福德爻)生,
印星生身荫护,官财印全,适合人间生存也。
若命缺财,缺官,则失去生存权。
一旦脱离父母养育,将天天面临,
从绝望中醒来,又从绝望中睡去。来去如烟!