- www.mql5.com
void TrailingStop(ulong ticket, int TrailingStart, int TrailingStep) { if(!Posicion.SelectByTicket(ticket)) return; //--- long stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL); double priceLevel = stopLevel * Point(); //--- long freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL); double priceFreezeLevel = freezeLevel * Point(); //--- double precioEntrada = Posicion.PriceOpen(); //--- Si la posición es BUY if(Posicion.PositionType() == POSITION_TYPE_BUY) { double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID); if(bid - precioEntrada > TrailingStart * Point()) { if(bid - Posicion.StopLoss() > TrailingStep * Point()) { double nuevoSL = bid - TrailingStep * Point(); nuevoSL = NormalizeDouble(nuevoSL, Digits()); //--- if(nuevoSL <= Posicion.StopLoss()) return; //--- if(bid - Posicion.StopLoss() <= priceFreezeLevel) return; //--- if(bid - nuevoSL <= priceLevel) return; //--- MqlTradeRequest request; MqlTradeCheckResult checkResult; ZeroMemory(request); ZeroMemory(checkResult); request.action = TRADE_ACTION_SLTP; request.position = Posicion.Ticket(); request.sl = nuevoSL; request.tp = Posicion.TakeProfit(); //--- if(OrderCheck(request, checkResult)) { Trade.PositionModify(Posicion.Ticket(), nuevoSL, Posicion.TakeProfit()); } } } } //--- Si la posición es SELL else { double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); if(precioEntrada - ask > TrailingStart * Point()) { if(Posicion.StopLoss() == 0 || Posicion.StopLoss() - ask > TrailingStep * Point()) { double nuevoSL = ask + TrailingStep * Point(); nuevoSL = NormalizeDouble(nuevoSL, Digits()); //--- if(Posicion.StopLoss() != 0 && nuevoSL >= Posicion.StopLoss()) return; //--- if(Posicion.StopLoss() - ask <= priceFreezeLevel) return; //--- if(nuevoSL - ask <= priceLevel) return; //--- MqlTradeRequest request; MqlTradeCheckResult checkResult; ZeroMemory(request); ZeroMemory(checkResult); request.action = TRADE_ACTION_SLTP; request.position = Posicion.Ticket(); request.sl = nuevoSL; request.tp = Posicion.TakeProfit(); //--- if(OrderCheck(request, checkResult)) { Trade.PositionModify(Posicion.Ticket(), nuevoSL, Posicion.TakeProfit()); } } } } }
I have added the function OrderCheck(...) and it still generates the same error [Modification failed due to order or position being close to market]. I can't seem to figure out what I'm doing wrong.
No not like this. Paste this code at the beginning of the EA. After this, erroneous orders will not be issued.
#include <Trade\Trade.mqh> class CTrade2 : public CTrade { public: virtual bool OrderSend( const MqlTradeRequest &request, MqlTradeResult &result ) { return(this.OrderCheck(request, this.m_check_result) && CTrade::OrderSend(request, result)); } }; #define CTrade CTrade2
Forum on trading, automated trading systems and testing trading strategies
Can someone explain this or is anyone in a similar situation?
Fernando Carreiro, 2023.10.06 11:18
Are you applying the following ...
Setting the TakeProfit and StopLoss levels within the SYMBOL_TRADE_STOPS_LEVEL minimum level Attempt to modify order or position within the SYMBOL_TRADE_FREEZE_LEVEL freeze level
Forum on trading, automated trading systems and testing trading strategies
getting error "Invalid Price Length 13" when placing an order
Fernando Carreiro, 2023.06.17 23:15
Also pay attention to the following ... courtesy of Vladimir Karputov
Forum on trading, automated trading systems and testing trading strategies
Tick size vs Point(), can be a little tricky in Multicurrency EA
Fernando Carreiro, 2022.03.09 12:11
Tick Size and Point Size can be very different especially on stocks and other symbols besides forex.
Always use Tick Size to adjust and align your prices, not the point size. In essence, make sure that your price quotes, are properly aligned to the Tick size (see following examples).
... double tickSize = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE ); ... double normalised_price = round( price / tick_size ) * tick_size; ... // Or use a function double Round2Ticksize( double price ) { double tick_size = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE ); return( round( price / tick_size ) * tick_size ); };
Thank you, Fernando. I had checked 2 of the three topics you shared. I hadn't seen the one about Tick Size Vs Point(). I implemented that change and also rounding to avoid using Digits(), but despite that, the validation error still occurs. I'm sharing the code using tickSize instead of Point() and keeping OrderCheck(...) since I see it makes sense to use it with TRADE_ACTION_SLTP where it is. I also changed the names of some variables and the comments to English for better understanding.
If anyone sees where my mistake is, I would appreciate it.
void TrailingStop(ulong ticket, int TrailingStart, int TrailingStep) { // Retrieve the minimum price change for the symbol double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); // Check if the position with the given ticket exists, return if not if(!Position.SelectByTicket(ticket)) return; // Calculate the minimum stop level and its equivalent in price long stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL); double priceLevel = stopLevel * tickSize; // Calculate the freezing level and its equivalent in price long freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL); double priceFreezeLevel = freezeLevel * tickSize; // Get the entry price of the position double entryPrice = Position.PriceOpen(); // If the position is a BUY if(Position.PositionType() == POSITION_TYPE_BUY) { double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID); // Check if the bid price has moved enough to start trailing if(bid - entryPrice > TrailingStart * tickSize) { // Check if the bid price has moved a step from the current SL if(bid - Position.StopLoss() > TrailingStep * tickSize) { // Calculate the new stop loss double newSL = bid - TrailingStep * tickSize; newSL = round(newSL / tickSize) * tickSize; // Verify the new SL is not moving backwards if(newSL <= round(Position.StopLoss() / tickSize) * tickSize) return; // Verify if the SL change is not within the freeze level if(bid - Position.StopLoss() <= priceFreezeLevel) return; // Verify if the SL change is not within the minimum stop level if(bid - newSL <= priceLevel) return; // Prepare the trade request and check result MqlTradeRequest request; MqlTradeCheckResult checkResult; ZeroMemory(request); ZeroMemory(checkResult); request.action = TRADE_ACTION_SLTP; request.position = Position.Ticket(); request.sl = newSL; request.tp = Position.TakeProfit(); // Check and execute the order if(OrderCheck(request, checkResult)) // Modify the position with the new SL Trade.PositionModify(Position.Ticket(), newSL, Position.TakeProfit()); } } } // If the position is a SELL else { double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); // Check if the ask price has moved enough to start trailing if(entryPrice - ask > TrailingStart * tickSize) { // Check if the ask price has moved a step from the current SL if(Position.StopLoss() == 0 || Position.StopLoss() - ask > TrailingStep * tickSize) { // Calculate the new stop loss double newSL = ask + TrailingStep * tickSize; newSL = round(newSL / tickSize) * tickSize; // Verify the new SL is not moving backwards if(Position.StopLoss() != 0 && newSL >= round(Position.StopLoss() / tickSize) * tickSize) return; // Verify if the SL change is not within the freeze level if(Position.StopLoss() != 0 && Position.StopLoss() - ask <= priceFreezeLevel) return; // Verify if the SL change is not within the minimum stop level if(newSL - ask <= priceLevel) return; // Prepare the trade request and check result MqlTradeRequest request; MqlTradeCheckResult checkResult; ZeroMemory(request); ZeroMemory(checkResult); request.action = TRADE_ACTION_SLTP; request.position = Position.Ticket(); request.sl = newSL; request.tp = Position.TakeProfit(); // Check and execute the order if(OrderCheck(request, checkResult)) // Modify the position with the new SL Trade.PositionModify(Position.Ticket(), newSL, Position.TakeProfit()); } } } }
Thanks, I've implemented the CTrade2 class at the beginning of the code, but it still didn't work. I'm starting to believe that the issue lies in the validation system.
If you put a breakpoint inside this function, does it stop?
Forum on trading, automated trading systems and testing trading strategies
Validation state: Validation completed with errors
fxsaber, 2023.11.23 21:39
#include <Trade\Trade.mqh> class CTrade2 : public CTrade { public: virtual bool OrderSend( const MqlTradeRequest &request, MqlTradeResult &result ) { DebugBreak(); return(this.OrderCheck(request, this.m_check_result) && CTrade::OrderSend(request, result)); } }; #define CTrade CTrade2
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
I'm having issues validating an update to an EA, and I can't figure out what I'm doing wrong. The problem is with the trailing stop, and even though I validate the SYMBOL_TRADE_FREEZE_LEVEL and SYMBOL_TRADE_STOPS_LEVEL, I still get the error "[Modification failed due to order or position being close to market]." I hope you can help me. Regards.