bool CheckStopLoss_Takeprofit(ENUM_ORDER_TYPE type,double SL,double TP) { //--- get the SYMBOL_TRADE_STOPS_LEVEL level int stops_level=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL); if(stops_level!=0) { PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+ " not be nearer than %d points from the closing price",stops_level,stops_level); } //--- bool SL_check=false,TP_check=false; //--- check only two order types switch(type) { //--- Buy operation case ORDER_TYPE_BUY: { //--- check the StopLoss SL_check=(Bid-SL>stops_level*_Point); if(!SL_check) PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+ " (Bid=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)", EnumToString(type),SL,Bid-stops_level*_Point,Bid,stops_level); //--- check the TakeProfit TP_check=(TP-Bid>stops_level*_Point); if(!TP_check) PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+ " (Bid=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)", EnumToString(type),TP,Bid+stops_level*_Point,Bid,stops_level); //--- return the result of checking return(SL_check&&TP_check); } //--- Sell operation case ORDER_TYPE_SELL: { //--- check the StopLoss SL_check=(SL-Ask>stops_level*_Point); if(!SL_check) PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f "+ " (Ask=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)", EnumToString(type),SL,Ask+stops_level*_Point,Ask,stops_level); //--- check the TakeProfit TP_check=(Ask-TP>stops_level*_Point); if(!TP_check) PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f "+ " (Ask=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)", EnumToString(type),TP,Ask-stops_level*_Point,Ask,stops_level); //--- return the result of checking return(TP_check&&SL_check); } break; } //--- a slightly different function is required for pending orders return false; }

The checks a trading robot must pass before publication in the Market
- www.mql5.com
Before any product is published in the Market, it must undergo compulsory preliminary checks in order to ensure a uniform quality standard. This article considers the most frequent errors made by developers in their technical indicators and trading robots. An also shows how to self-test a product before sending it to the Market.
非常感谢您的帮助。我已将支票添加到我的代码中,并对盈利和止损设置进行了更正。
// 输入参数 input int MagicNumber=1; // 魔数(MagicNumber) input double Lots=0.1; // 每个订单的交易手数(Lots) input double MaxOrders=5; // 订单总手数上限(MaxOrders) input double StopLoss=50; // 止损点(Stop Loss-以点数为单位) input double TakeProfit=100; // 止盈点(Take Profit-以点数为单位) input int BollingerPeriod=20; // 布林带周期(BollingerPeriod) input double Deviation=2; // 布林带偏差(Deviation) input ENUM_TIMEFRAMES BollingerTimeframe=PERIOD_H1; // 布林带时间周期(BollingerTimeframe) // 全局变量 double UpperBand[], MiddleBand[], LowerBand[]; // 布林带的三个轨道 // 初始化函数 void OnInit() { // 初始化时的日志 Print("初始化..."); // 为轨道数组分配空间 ArraySetAsSeries(UpperBand, true); ArraySetAsSeries(MiddleBand, true); ArraySetAsSeries(LowerBand, true); } // 每个tick的处理函数 void OnTick() { // 检查是否有新的K线 static datetime lastBarTime = 0; datetime currentBarTime = iTime(_Symbol, BollingerTimeframe, 0); if(lastBarTime == currentBarTime) return; // 如果没有新的K线,不执行任何操作 lastBarTime = currentBarTime; // 更新最后的K线时间 // 计算布林带 if(!CalculateBollingerBands()) return; // 如果计算布林带失败,则退出 // 获取当前价格 double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // 检查并执行交易逻辑 CheckAndTrade(currentPrice); // 检查并平仓 CheckAndCloseOrders(currentPrice); } // 计算布林带函数 bool CalculateBollingerBands() { int handle = iBands(_Symbol, BollingerTimeframe, BollingerPeriod, Deviation, 0, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("无法获取布林带指标的句柄,错误码:", GetLastError()); return false; } if(CopyBuffer(handle, 0, 0, 1, UpperBand) <= 0 || CopyBuffer(handle, 1, 0, 1, MiddleBand) <= 0 || CopyBuffer(handle, 2, 0, 1, LowerBand) <= 0) { Print("复制布林带数据失败,错误码:", GetLastError()); return false; } IndicatorRelease(handle); // 释放指标句柄 return true; // 成功计算布林带 } // 检查并执行交易逻辑 void CheckAndTrade(double currentPrice) { if(PositionsTotal() >= MaxOrders) return; // 如果当前持仓数达到或超过最大订单数,则不再开新仓 double lastClose = iClose(_Symbol, BollingerTimeframe, 1); if(lastClose > MiddleBand[0] && currentPrice < MiddleBand[0]) // 当前价格低于中轨,上一根K线收盘价高于中轨,开空单 { if(OpenOrder(ORDER_TYPE_SELL, currentPrice)) Print("开空单成功"); } else if(lastClose < MiddleBand[0] && currentPrice > MiddleBand[0]) // 当前价格高于中轨,上一根K线收盘价低于中轨,开多单 { if(OpenOrder(ORDER_TYPE_BUY, currentPrice)) Print("开多单成功"); } } // 检查并平仓函数 void CheckAndCloseOrders(double currentPrice) { for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue; // 忽略非EA生成的订单 double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); if(positionType == POSITION_TYPE_BUY && currentPrice < UpperBand[0] && currentPrice < MiddleBand[0] && openPrice < currentPrice) { if(CloseOrder(ticket)) Print("平多单成功"); } else if(positionType == POSITION_TYPE_SELL && currentPrice > LowerBand[0] && currentPrice > MiddleBand[0] && openPrice > currentPrice) { if(CloseOrder(ticket)) Print("平空单成功"); } } } } // 平仓函数 bool CloseOrder(ulong ticket) { MqlTradeRequest request; MqlTradeResult result; request.action = TRADE_ACTION_DEAL; // 直接成交 request.position = ticket; // 订单票号 request.symbol = _Symbol; // 交易品种 request.volume = Lots; // 交易手数 request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; // 订单类型(反向) request.price = SymbolInfoDouble(_Symbol, (request.type == ORDER_TYPE_SELL) ? SYMBOL_BID : SYMBOL_ASK); // 平仓价格 if(!OrderSend(request, result)) { Print("平仓失败,错误码:", GetLastError()); return false; } return true; } // 检查止损和止盈设置是否符合经纪商的要求 bool CheckStopLoss_TakeProfit(ENUM_ORDER_TYPE type, double SL, double TP) { int stops_level = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); double minSL, maxTP; if(type == ORDER_TYPE_BUY) { minSL = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) - stops_level * point, _Digits); maxTP = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) + stops_level * point, _Digits); } else // ORDER_TYPE_SELL { minSL = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) + stops_level * point, _Digits); maxTP = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stops_level * point, _Digits); } bool slValid = (type == ORDER_TYPE_BUY) ? (SL > minSL) : (SL < minSL); bool tpValid = (type == ORDER_TYPE_BUY) ? (TP < maxTP) : (TP > maxTP); if(!slValid) PrintFormat("%s 止损 %f 太接近当前价格了。允许的最小值为: %f.", (type == ORDER_TYPE_BUY) ? "Buy" : "Sell", SL, minSL); if(!tpValid) PrintFormat("%s 止盈 %f 太接近当前价格了。允许的最大值为: %f.", (type == ORDER_TYPE_BUY) ? "Buy" : "Sell", TP, maxTP); return slValid && tpValid; } // 开仓函数 bool OpenOrder(ENUM_ORDER_TYPE type, double price) { int _Digits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); double _Lots = Lots; double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); if(_Lots < minVolume) { Print("指定的交易手数小于最小交易量要求,将交易手数调整为最小交易量。"); _Lots = minVolume; } double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); if(_Lots > maxVolume) { Print("指定的交易手数超过最大交易量要求,将交易手数调整为最大交易量。"); _Lots = maxVolume; } double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); if(fmod(_Lots, volumeStep) != 0) { Print("指定的交易手数不符合交易量步长要求,将进行调整。"); _Lots = NormalizeDouble((int(_Lots / volumeStep) + 1) * volumeStep, _Digits); } double SL = (type == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point; double TP = (type == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point; SL = NormalizeDouble(SL, _Digits); TP = NormalizeDouble(TP, _Digits); if (!CheckStopLoss_TakeProfit(type, SL, TP)) { Print("止损或止盈设置不符合经纪商要求,取消订单。"); return false; } MqlTradeRequest request; MqlTradeResult result; request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = _Lots; request.type = type; request.type_filling = ORDER_FILLING_IOC; request.price = NormalizeDouble(price, _Digits); request.sl = SL; request.tp = TP; request.magic = MagicNumber; request.comment = "This is a comment"; if (!OrderSend(request, result)) { Print("正在尝试发送订单: 交易类型(Symbol)=", request.symbol, ", 订单类型(Type)=", request.type, ", 订单手数(Volume)=", request.volume, ", 订单价格(Price)=", request.price, ", 止损(Stop Loss)=", request.sl, ", 止盈(Take Profit)=", request.tp); Print("订单发送失败,错误码:", GetLastError()); Print("交易商支持的交易类型:",SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE)); return false; } Print("订单发送成功: 交易类型(Symbol)=", request.symbol, ", 订单类型(Type)=", request.type, ", 订单手数(Volume)=", request.volume, ", 订单价格(Price)=", request.price, ", 止损(Stop Loss)=", request.sl, ", 止盈(Take Profit)=", request.tp); return true; }
But the problem has not been resolved, it still reports the error 4756.

Why Is MQL5 Market the Best Place for Selling Trading Strategies and Technical Indicators
- www.mql5.com
MQL5.community Market provides Expert Advisors developers with the already formed market consisting of thousands of potential customers. This is the best place for selling trading robots and technical indicators!
int handle = iBands(_Symbol, BollingerTimeframe, BollingerPeriod, Deviation, 0, PRICE_CLOSE);
Forth input parameter for iBands is bands_shift and not deviation.
You may check here.
Documentation on MQL5: Technical Indicators / iBands
- www.mql5.com
The function returns the handle of the Bollinger Bands® indicator. Parameters symbol [in] The symbol name of the security, the data of which...

You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register
这是我的代码:
这是日志。
![]()
起初,我以为是填充类型问题,所以我添加了相应的反馈。但是,根据反馈将其替换为 SYMBOL-FILLING-IOC 后,问题仍未解决。(我尝试了所有三种类型,但它们不起作用)
无论如何,请帮帮我,我真的找不到解决方案。