As requested in post #2 by @Carl Schreiber, please have your code output to the log the relevant data of the modification attempt. Print the Bid price, Ask price, position's Open price, previous stops and the new stops, Stops Level, Freeze Level, and show us the log output for when the trailing fails.
In your code you are not checking for the stops not being different. If you try to update stops with the same values, it will also report an error. So please add that condition to your code.
Also, on a different note, prices should be aligned to the tick size, not normalised to the number of digits. In the case of many currency pairs, where tick size and point size are the same, this issue does not appear, but the method is incorrect and you should correct it for the case of other symbols. So please read the following post ... https://www.mql5.com/en/forum/390453#comment_28220035
As requested in post #2 by @Carl Schreiber, please have your code output to the log the relevant data of the modification attempt. Print the Bid price, Ask price, position's Open price, previous stops and the new stops, Stops Level, Freeze Level, and show us the log output for when the trailing fails.
In your code you are not checking for the stops are not different. If you try to update stops with the same values, it will also report an error. So please add that condition to your code.
Also, on a different note, prices should be aligned to the tick size, not normalised to the number of digits. In the case of many currency pairs, where tick size and point size are the same, this issue does not appear, but the method is incorrect and you should correct it for the case of other symbols. So please read the following post ... https://www.mql5.com/en/forum/390453#comment_28220035
Ok so this is my code part that involves stop loss and take profit...I've tried to modify it with ticks but it gives me the same error in the tester....now I'm going to paste that
void CalculateSLTP(double current_price, double &sl, double &tp)
{
// Ottieni il valore dell'ATRint atrHandle = iATR(_Symbol, 0, ATR_Period);
if (atrHandle == INVALID_HANDLE)
{
Print("Errore nell'ottenere l'handle ATR: ", GetLastError());
return;
}
// Copia il buffer dei dati ATRdouble atrBuffer[];
ArraySetAsSeries(atrBuffer, true);
int copied = CopyBuffer(atrHandle, 0, 0, 1, atrBuffer);
if (copied <= 0)
{
Print("Errore nel copiare i dati ATR, numero di dati copiati: ", copied);
Print("Codice errore: ", GetLastError());
IndicatorRelease(atrHandle);
return;
}
// Verifica il valore dell'ATRdouble atrValue = atrBuffer[0];
Print("ATR copiato correttamente: ", atrValue);
// Calcolo della distanza per SL e TPdouble stop_distance = atrValue * ATRMultiplier;
double target_distance = stop_distance * RiskRewardRatio;
// Arrotonda le distanze al tick sizedouble tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
stop_distance = MathRound(stop_distance / tick_size) * tick_size;
target_distance = MathRound(target_distance / tick_size) * tick_size;
Print("Distanza SL (arrotondata al tick): ", stop_distance);
Print("Distanza TP (arrotondata al tick): ", target_distance);
// Ottieni il livello minimo di stop dal brokerdouble stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * tick_size;
Print("Livello minimo di distanza per SL/TP: ", stop_level);
if (atrValue <= 0 || stop_distance < stop_level)
{
Print("ERRORE: ATR troppo basso o distanza SL inferiore al livello minimo.");
IndicatorRelease(atrHandle);
return;
}
// Calcolo SL e TP in base al tipo di ordineif (OrderType == ORDER_TYPE_BUY)
{
sl = current_price - stop_distance;
tp = current_price + target_distance;
}
elseif (OrderType == ORDER_TYPE_SELL)
{
sl = current_price + stop_distance;
tp = current_price - target_distance;
}
// Arrotonda i valori di SL e TP al tick size
sl = MathRound(sl / tick_size) * tick_size;
tp = MathRound(tp / tick_size) * tick_size;
Print("SL calcolato: ", sl, ", TP calcolato: ", tp);
IndicatorRelease(atrHandle);
}
// Funzione per aprire una posizionevoid OpenTrade(int order_type)
{
Print("Apertura di un nuovo trade...");
// Variabili per SL e TPdouble sl = 0;
double tp = 0;
// Ottieni il prezzo correntedouble current_price = (order_type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
// Calcola SL e TP
CalculateSLTP(current_price, sl, tp);
// Ottieni la dimensione del tick per il simbolo correntedouble tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); // Ottieni la dimensione del tick// Calcola la distanza minima dal prezzo correntedouble stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * tick_size; // Distanza minima richiesta dal brokerif (stop_level <= 0)
{
Print("Errore nel recupero del livello minimo di stop. Stop level impostato a valore predefinito.");
stop_level = 10 * tick_size; // Valore predefinito
}
// Calcola il lotto minimo e massimodouble min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
// Calcola la distanza dello stop loss in tick (non in punti)double stop_loss_distance = MathAbs(current_price - sl) / tick_size; // Ora è diviso per tick_size// Calcola la dimensione del lottodouble lot_size = 0.3;
// Verifica la distanza minima di SL/TP in base alla dimensione del tickif (MathAbs(sl - current_price) < stop_level) // Distanza minima per SL
{
sl = current_price + stop_level; // Allineato alla dimensione del tick
}
if (MathAbs(tp - current_price) < stop_level) // Distanza minima per TP
{
tp = current_price + stop_level; // Allineato alla dimensione del tick
}
// Controlla che SL e TP siano diversiif (MathAbs(sl - tp) < 0.0001) // Ad esempio, se sono troppo vicini
{
Print("SL e TP sono troppo vicini, aggiustamento...");
tp = sl + 0.001; // Aggiungi una distanza minima
}
// Allineamento dei prezzi per il tipo di ordine
sl = round(sl / tick_size) * tick_size; // Allinea SL alla dimensione del tick
tp = round(tp / tick_size) * tick_size; // Allinea TP alla dimensione del tickif (order_type == ORDER_TYPE_BUY)
{
Print("Tentativo di apertura ordine BUY...");
if (trade.Buy(lot_size, _Symbol, current_price, sl, tp))
{
Print("Ordine BUY aperto con successo.");
}
else
{
int error_code = GetLastError(); // Ottieni il codice errorePrint("Errore nell'aprire ordine BUY. Codice errore: ", error_code);
}
}
elseif (order_type == ORDER_TYPE_SELL)
{
Print("Tentativo di apertura ordine SELL...");
if (trade.Sell(lot_size, _Symbol, current_price, sl, tp))
{
Print("Ordine SELL aperto con successo.");
}
else
{
int error_code = GetLastError(); // Ottieni il codice errorePrint("Errore nell'aprire ordine SELL. Codice errore: ", error_code);
}
}
}
// Funzione per calcolare SL e TP in ticksvoid CalculateSLTP(int current_price_ticks, int &sl_ticks, int &tp_ticks)
{
// Logica di calcolo per SL e TP// (Aggiungere la logica del calcolo per il trailing stop e gli altri criteri di entrata)
sl_ticks = current_price_ticks - 10; // esempio di SL a 10 tick sotto il prezzo
tp_ticks = current_price_ticks + 20; // esempio di TP a 20 tick sopra il prezzo
}
CS016:11:13.004new trend following 2 (GBPUSD,H1)2024.01.02 15:18:12 DEBUG: No condition met for opening order.
CS016:11:13.004new trend following 2 (GBPUSD,H1)2024.01.02 15:18:12 Calculating RSI value...
CS016:11:13.004new trend following 2 (GBPUSD,H1)2024.01.02 15:18:12 RSI successfully copied: 29.983356134781133
CS016:11:13.004new trend following 2 (GBPUSD,H1)2024.01.02 15:18:12 Calculating MACD values...
If the error is the generalised "Invalid request", then please report to the log the actual trading result error code using the ResultRetcode() method.
On a separate unrelated issue, don't keep instantiating and releasing the Indicator on every call. Instantiate it once on in OnInit() and then reuse the handle when needed.
If the error is the generalised "Invalid request", then please report to the log the actual trading result error code using the ResultRetcode() method.
On a separate unrelated issue, don't keep instantiating and releasing the Indicator on every call. Instantiate it once on in OnInit() and then reuse the handle when needed.
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 DEBUG: BUY condition satisfied (RSI < RSI_Oversold: true, MACD Main > MACD Signal: false, ADX > ADX Threshold: true, BID Price < Lower Band: 1.26425, ASK Price: 1.26425)
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 A position already exists for the symbol: GBPUSD
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 Calling the ApplyTrailingStop() function
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 DEBUG: BID Price: 1.2641200000000001, ASK Price: 1.26425
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 DEBUG: Stop level: 0.0, Freeze level: 0.0
CS 208:39:10.852 Trades 2024.01.0215:25:45 failed modify #2 buy 0.3 GBPUSD sl: 1.26060, tp: 1.27588 -> sl: 1.26212, tp: 1.27588 [Invalid request]
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 Error updating SL/TP. Error code: 10013
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 Error description: Invalid request
CS 008:39:10.852 new trend following 5 (GBPUSD,H1) 2024.01.0215:25:45 DEBUG: Error updating trailing stop BUY. Error code: 4756
This is the log....the retcode gives me 10013 which is also invalid request.
During the test, even when the price rises significantly on the chart, the log doesn't show any attempt to apply the trailing stop. The log only sporadically shows the trailing stop being attempted, and even then, it happens only immediately after opening an order.
Do you need me to share the part of the code where the trailing stop is implemented in the OnTick function?
// Get the current order ticket (for pending orders)ulong ticket = PositionGetInteger(POSITION_TICKET);
// Check if the position is pending using OrderSelect()if (OrderSelect(ticket))
{
long order_type = OrderGetInteger(ORDER_TYPE); // Order type// If the order is pending (BUY_LIMIT, SELL_LIMIT, BUY_STOP, SELL_STOP)if (order_type == ORDER_TYPE_BUY_LIMIT || order_type == ORDER_TYPE_SELL_LIMIT ||
order_type == ORDER_TYPE_BUY_STOP || order_type == ORDER_TYPE_SELL_STOP)
{
Print("DEBUG: The position is a pending order. Trailing stop cannot be applied.");
return;
}
}
You are mixing up the concepts of Positions and Orders. Don't think in the MT4 way. An open position is NEVER a "pending order". It is just an open position currently in the market, irrespective of what order created it.
Creating a robust trading robot cannot be done without an understanding of the mechanisms of the MetaTrader 5 trading system. The client terminal receives the information about the positions, orders, and deals from the trading server. To handle this data properly using the MQL5, it's necessary to have a good understanding of the interaction between the MQL5-program and the client terminal.
// Function to apply the trailing stop with checks for pending orders and freeze levelvoid ApplyTrailingStop()
{
// Check if the position is active (not pending)if (!PositionSelect(_Symbol))
{
Print("DEBUG: No active position for the symbol ", _Symbol);
return;
}
// Get the current order ticket (for pending orders)ulong ticket = PositionGetInteger(POSITION_TICKET);
...
// Trailing stop calculation for BUY
...
// Modify the trailing stop only if the new distance is validif (trade.PositionModify(_Symbol, trailing_stop_price, PositionGetDouble(POSITION_TP)))
...
The "PositionModify" method call you are using is for "netting" accounts, not "hedging" accounts. Which account type are you using?
For "hedging" accounts you should be using the method with a position ticket ...
Modifies position parameters by the specified ticket.
bool PositionModify(
constulong ticket, // position ticketdouble sl, // Stop Loss price double tp // Take Profit price
)
Pietroalutto1 #:thank you for the answer. I use hedging account
Then your entire "ApplyTrailingStop()" logic should be redesigned. It is assuming "netting" or single position, which on a "hedging" account is not the case.
You need to go through all the currently open positions, filtering by Symbol and Magic Number and then applying the trailing stop to each that fits your conditions.
Then your entire "ApplyTrailingStop()" logic should be redesigned. It is assuming "netting" or single position, which on a "hedging" account is not the case.
You need to go through all the currently open positions, filtering by Symbol and Magic Number and then applying the trailing stop to each that fits your conditions.
Creating a robust trading robot cannot be done without an understanding of the mechanisms of the MetaTrader 5 trading system. The client terminal receives the information about the positions, orders, and deals from the trading server. To handle this data properly using the MQL5, it's necessary to have a good understanding of the interaction between the MQL5-program and the client terminal.
Ok so this is my code part that involves stop loss and take profit...I've tried to modify it with ticks but it gives me the same error in the tester....now I'm going to paste that
And this is the tester
This is the log....the retcode gives me 10013 which is also invalid request.
During the test, even when the price rises significantly on the chart, the log doesn't show any attempt to apply the trailing stop. The log only sporadically shows the trailing stop being attempted, and even then, it happens only immediately after opening an order.
Do you need me to share the part of the code where the trailing stop is implemented in the OnTick function?
Pietroalutto1 #:
You are mixing up the concepts of Positions and Orders. Don't think in the MT4 way. An open position is NEVER a "pending order". It is just an open position currently in the market, irrespective of what order created it.
The part I marked in red is useless. Take it out.
Please read the following article ...
The "PositionModify" method call you are using is for "netting" accounts, not "hedging" accounts. Which account type are you using?
For "hedging" accounts you should be using the method with a position ticket ...
The "PositionModify" method call you are using is for "netting" accounts, not "hedging" accounts. Which account type are you using?
For "hedging" accounts you should be using the method with a position ticket ...
thank you for the answer. I use hedging account
I paste the modified code so you can tell me if there are errors:
Then your entire "ApplyTrailingStop()" logic should be redesigned. It is assuming "netting" or single position, which on a "hedging" account is not the case.
You need to go through all the currently open positions, filtering by Symbol and Magic Number and then applying the trailing stop to each that fits your conditions.
Your EA's logic needs to be redesigned.
Then your entire "ApplyTrailingStop()" logic should be redesigned. It is assuming "netting" or single position, which on a "hedging" account is not the case.
You need to go through all the currently open positions, filtering by Symbol and Magic Number and then applying the trailing stop to each that fits your conditions.
Your EA's logic needs to be redesign
or maybe I can change to a netting account
No, don't be lazy! Make your code work properly for both types of accounts.
Study how to properly handle the trade functionality on MT5 ...