OrderCalcProfit() problem

 

I have run into an intermittent problem with the OrderCalcProfit() function, can anyone help me see what might be causing it? I am using OrderCalcProfit() to determine the lot-size of a position such that it has a given risk based on percentage of my account. e.g. I want each trade to lose 0.5% of my account if the stoploss is hit.

Occasionally, this function will compute a value for profit of 0, despite having valid inputs, returning true and no error being signaled via GetLastError().

I have spent quite a while reading through other posts before making my own, I do believe this is an issue that isn't obviously talked about elsewhere. This post is the closet I could find: https://www.mql5.com/en/forum/430265/page2#comment_43066510

Here is some code to illustrate the problem. I caveat, that most of the time it works OK, but about 25-50% of the time in a live account I get the issue described.

double LotsFixedRiskDollars(const ENUM_ORDER_TYPE order_type, const string symbol, const double entry, const double stoploss, const double risk)
{
    double lots_min = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
    double lots_max = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
    double lots_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
    double profit;

    if ((order_type != ORDER_TYPE_BUY) && (order_type != ORDER_TYPE_SELL))
    {
        ERROR("order_type must be ORDER_TYPE_BUY or ORDER_TYPE_SELL");
        return -1.0;
    }
    else if (OrderCalcProfit(order_type, symbol, lots_max, entry, stoploss, profit))
    {
        double lots_rough = MathRound(risk * lots_max / (-profit * lots_step));
        double lots_aligned = MathMin(MathMax(lots_rough * lots_step, lots_min), lots_max);
        return lots_aligned;
    }
    else
    {
        ERROR("OrderCalcProfit() returned false, using minimum lot-size as a fail-safe");
        return lots_min;
    }
}

As an example, here are some parameters from a trade this EA attempted to execute today:

  • order_type = ORDER_TYPE_SELL
  • symbol = "GPBJPY.a"
  • entry = 194.072
  • stoploss = 194.595
  • risk = 22.29 (computed from 0.5% of account balance)

While I don't fully understand the problem, I have diagnosed a number of characteristics of when it goes wrong:

  • OrderCalcProfit() returns true, but profit is set to 0.0 - this is really the root cause, but I don't understand why it is happening
  • This leads to a division by zero (uncaught) and lots_rough is set to infinity
  • Then, lots_aligned is set to lots_max (equivalent to SYMBOL_VOLUME_MAX)
  • The order is built and executed, but rejected by the server as my account doesn't have enough money

Any ideas what might cause this? I have a chart open on the symbol that is being traded. Data is being received from the server and plotted on the chart. The previous trade might have worked fine, but arbitrary ones unfold as I describe above. This is all in an EA where I access pricing data via iHigh()/iLow() methods.

SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) sometimes zero
SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) sometimes zero
  • 2022.08.23
  • Fernando Carreiro
  • www.mql5.com
Hi guys, need an advise. I use tickvalue for calculating lot size...
 
Bill M:

I have run into an intermittent problem with the OrderCalcProfit() function, can anyone help me see what might be causing it? I am using OrderCalcProfit() to determine the lot-size of a position such that it has a given risk based on percentage of my account. e.g. I want each trade to lose 0.5% of my account if the stoploss is hit.

Occasionally, this function will compute a value for profit of 0, despite having valid inputs, returning true and no error being signaled via GetLastError().

I have spent quite a while reading through other posts before making my own, I do believe this is an issue that isn't obviously talked about elsewhere. This post is the closet I could find: https://www.mql5.com/en/forum/430265/page2#comment_43066510

Here is some code to illustrate the problem. I caveat, that most of the time it works OK, but about 25-50% of the time in a live account I get the issue described.

As an example, here are some parameters from a trade this EA attempted to execute today:

  • order_type = ORDER_TYPE_SELL
  • symbol = "GPBJPY.a"
  • entry = 194.072
  • stoploss = 194.595
  • risk = 22.29 (computed from 0.5% of account balance)

While I don't fully understand the problem, I have diagnosed a number of characteristics of when it goes wrong:

  • OrderCalcProfit() returns true, but profit is set to 0.0 - this is really the root cause, but I don't understand why it is happening
  • This leads to a division by zero (uncaught) and lots_rough is set to infinity
  • Then, lots_aligned is set to lots_max (equivalent to SYMBOL_VOLUME_MAX)
  • The order is built and executed, but rejected by the server as my account doesn't have enough money

Any ideas what might cause this? I have a chart open on the symbol that is being traded. Data is being received from the server and plotted on the chart. The previous trade might have worked fine, but arbitrary ones unfold as I describe above. This is all in an EA where I access pricing data via iHigh()/iLow() methods.

Please print all the values used with OrderCalcProfit(), then show us the output log when it returns 0.
 
Alain Verleyen #:
Please print all the values used with OrderCalcProfit(), then show us the output log when it returns 0.

Thanks for looking! I have updated the code with a print statement that provides what you ask for.

double LotsFixedRiskDollars(const ENUM_ORDER_TYPE order_type, const string symbol, const double entry,
                            const double stoploss, const double risk)
{
    double lots_min = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
    double lots_max = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
    double lots_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
    double profit;

    if ((order_type != ORDER_TYPE_BUY) && (order_type != ORDER_TYPE_SELL))
    {
        ERROR("order_type must be ORDER_TYPE_BUY or ORDER_TYPE_SELL");
        return -1.0;
    }
    else if (OrderCalcProfit(order_type, symbol, lots_max, entry, stoploss, profit))
    {
        double lots_rough = MathRound(risk * lots_max / (-profit * lots_step));
        double lots_aligned = MathMin(MathMax(lots_rough * lots_step, lots_min), lots_max);

        PrintFormat("LOTS INFO!!! (%s,%s,%f,%f,%f) (%f,%f,%f,%f) (%f,%f)",
                    EnumToString(order_type), symbol, entry, stoploss, risk,
                    lots_min, lots_max, lots_step, profit,
                    lots_rough, lots_aligned);

        return lots_aligned;
    }
    else
    {
        ERROR("OrderCalcProfit() returned false");
        return -1.0;
    }
}

Here are three examples that happened earlier today. I cannot recreate the problem on demand, but have recent examples to reference.

2024.10.09 07:00:02.111 Range Breakout (DE40.a,M30)     LOTS INFO!!! (ORDER_TYPE_BUY,DE40.a,19099.500000,19055.500000,22.292500) (0.100000,250.000000,0.100000,-0.000000) (inf,250.000000)
2024.10.09 07:00:02.191 Range Breakout (GBPJPY.a,M30)   LOTS INFO!!! (ORDER_TYPE_BUY,GBPJPY.a,194.595000,194.072000,22.292500) (0.010000,100.000000,0.010000,-0.000000) (inf,100.000000)
2024.10.09 07:00:04.031 Range Breakout (GBPJPY.a,M30)   LOTS INFO!!! (ORDER_TYPE_SELL,GBPJPY.a,194.072000,194.595000,22.292500) (0.010000,100.000000,0.010000,-0.000000) (inf,100.000000)
 
Bill M #: Thanks for looking! I have updated the code with a print statement that provides what you ask for. Here are three examples that happened earlier today. I cannot recreate the problem on demand, but have recent examples to reference.

Is this perhaps running in an Indicator?

I ask because, as far as I remember, the function does not run correctly in an Indicator, only on an EA and Script.

 
Fernando Carreiro #:

Is this perhaps running in an Indicator?

I ask because, as far as I remember, the function does not run correctly in an Indicator, only on an EA and Script.

No, this is run in an EA.

This particular code is being invoked from OnTick(). Ideally, this is determining the lot size of an order that the EA will submit.

 
Bill M #:

Thanks for looking! I have updated the code with a print statement that provides what you ask for.

Here are three examples that happened earlier today. I cannot recreate the problem on demand, but have recent examples to reference.

Why are you running OrderCalcProfit with lots_max ?
 
Bill M #:

Thanks for looking! I have updated the code with a print statement that provides what you ask for.

Here are three examples that happened earlier today. I cannot recreate the problem on demand, but have recent examples to reference.

What is your account currency ?

You said occasionally it returns 0.0, is it for the same symbol (GBPJPY.a for example) ?

 
Alain Verleyen #: Why are you running OrderCalcProfit with lots_max ?
It is probably based on my example code. I use it for a slightly higher precision instead of using 1.0. It is just a personal preference, but it is not the reason for the issue.
 
Alain Verleyen #:
Why are you running OrderCalcProfit with lots_max ?

To calculate the lot size for a desired risk amount in account equity/balance.

I have followed the pattern from @Fernando Carreiro, for example: https://www.mql5.com/en/forum/430265/page2#comment_41590903

By calculating the loss associated with hitting stop-loss for a maximum volume trade, you can then scale the lot-size back down to a multiple of SYMBOL_VOLUME_STEP that is as close as possible to your desired risk.

SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) sometimes zero
SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) sometimes zero
  • 2022.08.23
  • Fernando Carreiro
  • www.mql5.com
Hi guys, need an advise. I use tickvalue for calculating lot size...
 
Alain Verleyen #:

What is your account currency ?

You said occasionally it returns 0.0, is it for the same symbol (GBPJPY.a for example) ?

My account currency is AUD.

I do not trade any symbol in that currency though.

So far I have noticed this problem with DE40.a (German stock index) and some FX pairs (GBPJPY.a, GBPUSD.a, USDJPY.a)

 
Bill M #:

My account currency is AUD.

I do not trade any symbol in that currency though.

So far I have noticed this problem with DE40.a (German stock index) and some FX pairs (GBPJPY.a, GBPUSD.a, USDJPY.a)

Just as a test—do you have the AUDUSD symbol active on your Market Watch, and if not, can you please enable it, and try again?