//+------------------------------------------------------------------+ //| ChannelPRO.mq5 | //| Professionally Enhanced by AI | //+------------------------------------------------------------------+ #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[ArrayMaximum(highArray)]; lowerChannel = lowArray[ArrayMinimum(lowArray)]; if(upperChannel <= lowerChannel) { Print("无效通道值!"); upperChannel = 0; lowerChannel = 0; } } //+------------------------------------------------------------------+ //| 趋势方向判断函数 | //+------------------------------------------------------------------+ bool IsBullishTrend() { double maArray[2], closeArray[2]; if(CopyBuffer(maHandle, 0, 0, 2, maArray) != 2 || CopyClose(_Symbol, _Period, 0, 2, closeArray) != 2) { Print("趋势判断数据获取失败"); return false; } return (closeArray[1] > maArray[1] && closeArray[0] > maArray[0]); } bool IsBearishTrend() { double maArray[2], closeArray[2]; if(CopyBuffer(maHandle, 0, 0, 2, maArray) != 2 || CopyClose(_Symbol, _Period, 0, 2, closeArray) != 2) { Print("趋势判断数据获取失败"); return false; } return (closeArray[1] < maArray[1] && closeArray[0] < maArray[0]); } //+------------------------------------------------------------------+ //| 获取ADX强度值 | //+------------------------------------------------------------------+ double GetADXValue() { double adxArray[1]; if(CopyBuffer(adxHandle, 0, 0, 1, adxArray) != 1) { Print("ADX值获取失败"); return 0; } return adxArray[0]; } //+------------------------------------------------------------------+ //| 计算头寸规模函数 | //+------------------------------------------------------------------+ 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[1], currentClose[1]; 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[0] * ATRMultiplier; sl = NormalizeDouble(sl, _Digits); tp = price + (price - sl) * 2; tp = NormalizeDouble(tp, _Digits); } else { sl = upperChannel + atrValue[0] * 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[1]; if(CopyClose(_Symbol, _Period, 0, 1, currentClose) != 1) { Print("当前价格获取失败"); return; } bool buySignal = currentClose[0] > upperChannel && bullish && adxValue > ADXThreshold; bool sellSignal = currentClose[0] < 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通道计算周期
ATRMultiplier 0.5-5.01.5止损ATR倍数
TrendMAPeriod 50-500200趋势判断EMA周期
风险管理 RiskPercent0.1-5.01.0单笔交易风险比例
MaxDailyTrades 0-10010每日最大交易次数
MaxDrawdown 0-10020.0账户最大回撤限制(%)
时间控制 TradeStartHour0-238允许交易开始时间
TradeEndHour 0-2320允许交易结束时间
移动止损 TrailATRMultiple1.0-5.02.0移动止损ATR倍数
TrailStep 10-20050止损移动步长(点)
订单执行 Slippage0-503最大允许滑点
FillType -FOK订单执行方式[size=16.002px]使用说明: 参数优化建议: 趋势市场:增大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时自动按倍数加仓
|