Good evening, I am trying to create my own expert advisor for the U.S. indices, I have implemented various controls and they seem to work well, such as whether a symbol is valid, whether the market is closed or open, the program shows me the moving averages and RSI correctly but when it tries to open any trade (either buy or sell) it returns this following error:
2024.07.22 18:09:04.749 TradingBotDanny (US500Cash,M1) CTrade::OrderSend: market sell 0.10 US500Cash sl: 5539.76 tp: 5539.31 [invalid stops].
I attach below my code:
- Detecting Stop Loss
- [WARNING CLOSED!] Any newbie question, so as not to clutter up the forum. Professionals, don't go by. Can't go anywhere without you.
- Invalid volume with take profit = 0
Danny01_: Good evening, I am trying to create my own expert advisor for the U.S. indices, I have implemented various controls and they seem to work well, such as whether a symbol is valid, whether the market is closed or open, the program shows me the moving averages and RSI correctly but when it tries to open any trade (either buy or sell) it returns this following error: 2024.07.22 18:09:04.749 TradingBotDanny (US500Cash,M1) CTrade::OrderSend: market sell 0.10 US500Cash sl: 5539.76 tp: 5539.31 [invalid stops]. I attach below my code:
Try using the function below to normalize SL and TP, instead of NormalizeDouble():
//+--------------------------------------------------------------------------------------------------------------------+ //| This function normalizes and adjusts the price to the TICK SIZE | //+--------------------------------------------------------------------------------------------------------------------+ bool NormalizePrice(string symbol, double &price) { //--- Local variables long decimal_digits = 0; double tick_size = 0.0; //--- Get the minimal price change if(!SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE, tick_size)) { Print(__FUNCTION__, " - Error getting the SYMBOL_TRADE_TICK_SIZE: ", GetLastError(), " - ", symbol); return(false); } //--- Get the number of decimal digits if(!SymbolInfoInteger(symbol, SYMBOL_DIGITS, decimal_digits)) { Print(__FUNCTION__, " - Error getting the SYMBOL_DIGITS: ", GetLastError(), " - ", symbol); return(false); } //--- Return the price normalized if(tick_size == 0.0) { price = NormalizeDouble(price, (int)decimal_digits); } //--- Return the price normalized and adjusted to the TICK SIZE else { price = NormalizeDouble(MathRound(price / tick_size) * tick_size, (int)decimal_digits); } //--- Successful normalization return(true); }
Vinicius Pereira De Oliveira #:
Try using the function below to normalize SL and TP, instead of NormalizeDouble():
//+------------------------------------------------------------------+ //| ScalpingEAWithMarketCheck.mq5 | //| Copyright 2024, Your Name | //| https://www.yourwebsite.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Your Name" #property link "https://www.yourwebsite.com" #property version "1.04" #property strict #include <Trade\Trade.mqh> // Declaration of global variables CTrade trade; input int FastEMAPeriod = 9; // Fast EMA period input int SlowEMAPeriod = 21; // Slow EMA period input int RSIPeriod = 14; // RSI period input double LotSize = 0.1; // Lot size input double StopLossPips = 10.0; // Stop Loss in pips input double TakeProfitPips = 20.0; // Take Profit in pips input string TradingSymbols = "US500Cash,US30Cash"; // Symbols for trading static datetime lastPrintTime = 0; static double lastFastEMA = 0; static double lastSlowEMA = 0; static double lastRSI = 0; // Handles for indicators int FastEMAHandle; int SlowEMAHandle; int RSIHandle; // Arrays for indicator values double FastEMABuffer[]; double SlowEMABuffer[]; double RSIBuffer[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Initialization of indicator handles FastEMAHandle = iMA(_Symbol, PERIOD_CURRENT, FastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); SlowEMAHandle = iMA(_Symbol, PERIOD_CURRENT, SlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); RSIHandle = iRSI(_Symbol, PERIOD_CURRENT, RSIPeriod, PRICE_CLOSE); if(FastEMAHandle == INVALID_HANDLE || SlowEMAHandle == INVALID_HANDLE || RSIHandle == INVALID_HANDLE) { Print("Error initializing indicators"); return INIT_FAILED; } // Setting arrays as time series ArraySetAsSeries(FastEMABuffer, true); ArraySetAsSeries(SlowEMABuffer, true); ArraySetAsSeries(RSIBuffer, true); // Check if the current symbol is valid for trading if(!IsValidSymbol()) { Print("Invalid symbol for trading: ", _Symbol); return INIT_FAILED; } if(!IsMarketOpen()) { Print("Initialization completed, but the market is currently closed."); } else { Print("Initialization completed successfully. The market is open."); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(FastEMAHandle); IndicatorRelease(SlowEMAHandle); IndicatorRelease(RSIHandle); Print("Expert Advisor deinitialized"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(!IsMarketOpen()) { return; } if(!UpdateIndicators()) { Print("Error updating indicators"); return; } PrintIndicatorValues(); if(PositionsTotal() == 0) { CheckAndOpenPosition(); } } //+------------------------------------------------------------------+ //| Check if the current symbol is valid for trading | //+------------------------------------------------------------------+ bool IsValidSymbol() { string symbols[]; StringSplit(TradingSymbols, ',', symbols); for(int i = 0; i < ArraySize(symbols); i++) { if(StringCompare(_Symbol, CustomTrim(symbols[i]), false) == 0) { return true; } } return false; } //+------------------------------------------------------------------+ //| Custom function to remove whitespace | //+------------------------------------------------------------------+ string CustomTrim(string str) { int start = 0; int end = StringLen(str) - 1; // Remove spaces at the beginning while(start <= end && StringGetCharacter(str, start) == ' ') start++; // Remove spaces at the end while(end >= start && StringGetCharacter(str, end) == ' ') end--; // Extract the substring without spaces return StringSubstr(str, start, end - start + 1); } static datetime lastAlertTime = 0; //+------------------------------------------------------------------+ //| Check if the market is open | //+------------------------------------------------------------------+ bool IsMarketOpen() { MqlDateTime dt; TimeToStruct(TimeLocal(), dt); string dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; bool isOpen = false; string message = ""; // Check for Saturday and Sunday if(dt.day_of_week == 0 || dt.day_of_week == 6) { message = "Market closed: " + dayNames[dt.day_of_week]; } // Check for opening hours from Monday to Friday else if(dt.day_of_week >= 1 && dt.day_of_week <= 5) { if(dt.hour >= 0 && dt.hour < 22) { isOpen = true; } else { message = "Market closed: Outside trading hours"; } } // If the market is closed and we haven't sent an alert in the last 60 minutes if(!isOpen && TimeLocal() - lastAlertTime > 60 * 60) { Alert(message); Print(message); lastAlertTime = TimeLocal(); } return isOpen; } //+------------------------------------------------------------------+ //| Update indicator values | //+------------------------------------------------------------------+ bool UpdateIndicators() { return (CopyBuffer(FastEMAHandle, 0, 0, 2, FastEMABuffer) == 2 && CopyBuffer(SlowEMAHandle, 0, 0, 2, SlowEMABuffer) == 2 && CopyBuffer(RSIHandle, 0, 0, 2, RSIBuffer) == 2); } //+------------------------------------------------------------------+ //| Print indicator values | //+------------------------------------------------------------------+ void PrintIndicatorValues() { datetime currentTime = TimeLocal(); // Ensure we have valid data before accessing the arrays if(ArraySize(FastEMABuffer) > 0 && ArraySize(SlowEMABuffer) > 0 && ArraySize(RSIBuffer) > 0) { if(MathAbs(FastEMABuffer[0] - lastFastEMA) > 0.0001 || MathAbs(SlowEMABuffer[0] - lastSlowEMA) > 0.0001 || MathAbs(RSIBuffer[0] - lastRSI) > 0.1 || currentTime - lastPrintTime > 300) { Print("Symbol: ", _Symbol); Print("Fast EMA: ", FastEMABuffer[0], ", Slow EMA: ", SlowEMABuffer[0]); Print("RSI: ", RSIBuffer[0]); lastFastEMA = FastEMABuffer[0]; lastSlowEMA = SlowEMABuffer[0]; lastRSI = RSIBuffer[0]; lastPrintTime = currentTime; } } else { Print("Error: Indicator data not available"); } } //+------------------------------------------------------------------+ //| Check and open a position if necessary | //+------------------------------------------------------------------+ void CheckAndOpenPosition() { // Check if automatic trading is enabled if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print("Error: Automatic trading is disabled. Enable it in the MetaTrader terminal."); return; } if(IsBuySignal()) { OpenBuyPosition(StopLossPips, TakeProfitPips); } else if(IsSellSignal()) { OpenSellPosition(StopLossPips, TakeProfitPips); } } //+------------------------------------------------------------------+ //| Open a buy position | //+------------------------------------------------------------------+ void OpenBuyPosition(double stopLossPips, double takeProfitPips) { if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print("Error: Automatic trading is disabled. Unable to open a buy position."); return; } double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double pointSize = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); // Get the minimum stop level in points and increase it slightly long stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL); double minStopDistance = (stopLevel + 5) * pointSize; // Add 5 extra points // Calculate stop loss and take profit prices double stopLossPrice = askPrice - (stopLossPips * pointSize); double takeProfitPrice = askPrice + (takeProfitPips * pointSize); // Normalize prices using the new function if(!NormalizePrice(_Symbol, stopLossPrice) || !NormalizePrice(_Symbol, takeProfitPrice) || !NormalizePrice(_Symbol, askPrice)) { Print("Error in price normalization"); return; } // Ensure that stop loss and take profit respect the minimum distance if (askPrice - stopLossPrice < minStopDistance) { stopLossPrice = askPrice - minStopDistance; if(!NormalizePrice(_Symbol, stopLossPrice)) { Print("Error in Stop Loss normalization"); return; } Print("Stop Loss adjusted to respect minimum distance"); } if (takeProfitPrice - askPrice < minStopDistance) { takeProfitPrice = askPrice + minStopDistance; if(!NormalizePrice(_Symbol, takeProfitPrice)) { Print("Error in Take Profit normalization"); return; } Print("Take Profit adjusted to respect minimum distance"); } // Check if stops are valid before opening the position if (askPrice - stopLossPrice >= minStopDistance && takeProfitPrice - askPrice >= minStopDistance) { Print("Attempting to open buy position - Ask: ", askPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); if(!trade.Buy(LotSize, _Symbol, askPrice, stopLossPrice, takeProfitPrice, "Scalping EA Buy")) { Print("Error opening buy position: ", GetLastError()); Print("Ask: ", askPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); Print("Minimum required distance: ", minStopDistance); Print("Current SL distance: ", askPrice - stopLossPrice, " Current TP distance: ", takeProfitPrice - askPrice); } else { Print("Buy position opened successfully"); Print("Entry: ", askPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); } } else { Print("Unable to open position: Invalid stop loss or take profit"); Print("Ask: ", askPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); Print("Minimum required distance: ", minStopDistance); Print("Current SL distance: ", askPrice - stopLossPrice, " Current TP distance: ", takeProfitPrice - askPrice); } } //+------------------------------------------------------------------+ //| Open a sell position | //+------------------------------------------------------------------+ void OpenSellPosition(double stopLossPips, double takeProfitPips) { if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print("Error: Automatic trading is disabled. Unable to open a sell position."); return; } double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); double pointSize = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); // Get the minimum stop level in points and increase it slightly long stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL); double minStopDistance = (stopLevel + 5) * pointSize; // Add 5 extra points // Calculate stop loss and take profit prices double stopLossPrice = bidPrice + (stopLossPips * pointSize); double takeProfitPrice = bidPrice - (takeProfitPips * pointSize); // Normalize prices using the new function if(!NormalizePrice(_Symbol, stopLossPrice) || !NormalizePrice(_Symbol, takeProfitPrice) || !NormalizePrice(_Symbol, bidPrice)) { Print("Error in price normalization"); return; } // Ensure that stop loss and take profit respect the minimum distance if (stopLossPrice - bidPrice < minStopDistance) { stopLossPrice = bidPrice + minStopDistance; if(!NormalizePrice(_Symbol, stopLossPrice)) { Print("Error in Stop Loss normalization"); return; } Print("Stop Loss adjusted to respect minimum distance"); } if (bidPrice - takeProfitPrice < minStopDistance) { takeProfitPrice = bidPrice - minStopDistance; if(!NormalizePrice(_Symbol, takeProfitPrice)) { Print("Error in Take Profit normalization"); return; } Print("Take Profit adjusted to respect minimum distance"); } // Check if stops are valid before opening the position if (stopLossPrice - bidPrice >= minStopDistance && bidPrice - takeProfitPrice >= minStopDistance) { Print("Attempting to open sell position - Bid: ", bidPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); if(!trade.Sell(LotSize, _Symbol, bidPrice, stopLossPrice, takeProfitPrice, "Scalping EA Sell")) { Print("Error opening sell position: ", GetLastError()); Print("Bid: ", bidPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); Print("Minimum required distance: ", minStopDistance); Print("Current SL distance: ", stopLossPrice - bidPrice, " Current TP distance: ", bidPrice - takeProfitPrice); } else { Print("Sell position opened successfully"); Print("Entry: ", bidPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); } } else { Print("Unable to open position: Invalid stop loss or take profit"); Print("Bid: ", bidPrice, " SL: ", stopLossPrice, " TP: ", takeProfitPrice); Print("Minimum required distance: ", minStopDistance); Print("Current SL distance: ", stopLossPrice - bidPrice, " Current TP distance: ", bidPrice - takeProfitPrice); } } //+------------------------------------------------------------------+ //| This function normalizes and adjusts the price to the TICK SIZE | //+------------------------------------------------------------------+ bool NormalizePrice(string symbol, double &price) { //--- Local variables long decimal_digits = 0; double tick_size = 0.0; //--- Get the minimal price change if(!SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE, tick_size)) { Print(__FUNCTION__, " - Error getting the SYMBOL_TRADE_TICK_SIZE: ", GetLastError(), " - ", symbol); return(false); } //--- Get the number of decimal digits if(!SymbolInfoInteger(symbol, SYMBOL_DIGITS, decimal_digits)) { Print(__FUNCTION__, " - Error getting the SYMBOL_DIGITS: ", GetLastError(), " - ", symbol); return(false); } //--- Return the price normalized if(tick_size == 0.0) { price = NormalizeDouble(price, (int)decimal_digits); } //--- Return the price normalized and adjusted to the TICK SIZE else { price = NormalizeDouble(MathRound(price / tick_size) * tick_size, (int)decimal_digits); } //--- Successful normalization return(true); } //+------------------------------------------------------------------+ //| Check for buy signal | //+------------------------------------------------------------------+ bool IsBuySignal() { return (FastEMABuffer[1] > SlowEMABuffer[1] && FastEMABuffer[0] <= SlowEMABuffer[0] && RSIBuffer[0] < 70); } //+------------------------------------------------------------------+ //| Check for sell signal | //+------------------------------------------------------------------+ bool IsSellSignal() { return (FastEMABuffer[1] < SlowEMABuffer[1] && FastEMABuffer[0] >= SlowEMABuffer[0] && RSIBuffer[0] > 30); }Replacing the NormalizeDouble() function with NormalizePrice I keep getting the same error
![The Craziest & Most Affordable Hosting Deal Ever! The Craziest & Most Affordable Hosting Deal Ever!](https://c.mql5.com/36/84/the-craziest-most-affordable-hosting.jpg)
Indices markets don't use the same symbol margin initial as in forex markets, it's an entirely different exchange. The points in indices means something different... you have 10 in the input for stoplosspips, try 10000, and you'll see how narrow the stop loss will still be
In EURUSD and other currency pairs, 1 standard lot is equal to 100,000 units of the base currency. In US30, 1 standard lot is equal to 1 unit of the base currency...but varies between brokers.
In MT4 and MT5 right click a symbol in the Market Watch window and click Specification. The Contract Size field tells how many units are in one lot, from this you can get an idea for how the SL and TP should be calculated![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
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