I'm trying to write some modules for calculating trailing stop-loss in MQL5. The issue I'm having is that, whenever I attempt to retrieve the stop-loss for a position, I get a value of zero. I know the position doesn't have a stop-loss of zero because the journal shows that it was generated with a non-zero SL:
CS 0 12:59:55.438 Trade 2022.01.03 17:00:00 market sell 0.1 EURUSD sl: 1.13358 (1.13062 / 1.13063 / 1.13062)
CS 0 12:59:55.438 Trades 2022.01.03 17:00:00 deal #2 sell 0.1 EURUSD at 1.13062 done (based on order #2)
CS 0 12:59:55.438 Trade 2022.01.03 17:00:00 deal performed [#2 sell 0.1 EURUSD at 1.13062]
CS 0 12:59:55.438 Trade 2022.01.03 17:00:00 order performed sell 0.1 at 1.13062 [#2 sell 0.1 EURUSD at 1.13062]
Furthermore, when I check the stop-loss of the position immediately after I enter it, by doing:
for (int i = 0; i < PositionsTotal(); i++) {
if (PositionGetSymbol(i) != Symbol()) {
continue;
}
ulong ticket = PositionGetTicket(i);
PositionSelectByTicket(ticket);
PrintFormat("Position %d, Current SL: %f", ticket, PositionGetDouble(POSITION_SL));
}
This prints the following:
CS 0 12:59:55.439 test (EURUSD,H1) 2022.01.03 17:00:00 Position 2, Current SL: 1.133580
So, I can see that it's working, but only for the tick when the position was generated. Anytime after that, I get this:
CS 0 12:59:55.441 test (EURUSD,H1) 2022.01.03 18:00:00 Position 2, Current SL: 0.000000
So, what's going on here?
It turns out that this issue was caused by a completely separate problem. This is the code that was doing my trailing stop logic:
ExitResult Exit() {
ExitResult result;
result.Result = EXIT_RESULT_CONTINUE;
if (!m_calculator.Enabled()) {
return result;
}
for (int i = 0; i < PositionsTotal(); i++) {
if (PositionGetSymbol(i) != Symbol()) {
continue;
}
ulong ticket = PositionGetTicket(i);
PositionSelectByTicket(ticket);
double newSL;
ENUM_POSITION_TYPE pType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
int errCode = m_calculator.Calculate(i, pType, newSL);
if (errCode != 0) {
result.ErrorCode = errCode;
result.Result = EXIT_RESULT_ERROR;
break;
}
double existingSL = PositionGetDouble(POSITION_SL);
if ((pType == POSITION_TYPE_BUY && newSL > existingSL) || (pType == POSITION_TYPE_SELL && newSL < existingSL)) {
result.Order = CreateSltp(m_magic, ticket);
result.Order.sl = newSL;
result.Order.tp = PositionGetDouble(POSITION_TP);
result.Result = EXIT_RESULT_EXIT;
break;
}
}
return result;
}
The issue here was that, if newSL
was not modified by the call to Calculate
, then it would contain its default value of 0. So, for any sell position, this would guarantee that the stop-loss would eventually be set to 0.
All I had to do was include a Boolean flag in Calculate
that would be true if the rule modified newSL
and false otherwise. This fixed the issue.