Formula to calculate risk lotsize

 

I try to create a code which will work on all instrument to calculate the right lotsize based on 1 percent risk, but my current code show me only a right lotsize for forex currencys, when i put the indicator on bitcoin chart i get to big lotsize, can you help to make a working code which will calculate always correct, also on share and cryptos or anything else?

//+------------------------------------------------------------------+
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

    int Stoplos=iATR(Symbol(),PERIOD_H1,10,0) * SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE);
    Stoplos = Stoplos / MarketInfo(Symbol(),MODE_DIGITS);
    Alert(Stoplos);
    if(Stoplos<12) 
    {
      if(Stoplos<12)Stoplos=12;
    }
    double Percent=1;
    double ticksize=MarketInfo(Symbol(),MODE_TICKVALUE)*10;
    double AllowedLose=(AccountEquity()/100)*Percent;
    double Lotsize=NormalizeDouble((AllowedLose/Stoplos)/ticksize,2);

    Comment("Lotgröße: ", Lotsize);


//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
our topic has been moved to the section: MQL4 and MetaTrader 4
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
 

Please search 🔍 before you post. Your question has already been discussed multiple times on the forum.

Here are some references, but please do a search and read other posts ...

Forum on trading, automated trading systems and testing trading strategies

Code for Risk Management

William Roeder, 2021.02.20 17:58

Risk depends on your initial stop loss, lot size, and the value of the symbol. It does not depend on margin and leverage. No SL means you have infinite risk. Never risk more than a small percentage of your trading funds, certainly less than 2% per trade, 6% total.

  1. You place the stop where it needs to be — where the reason for the trade is no longer valid. E.g. trading a support bounce the stop goes below the support.

  2. AccountBalance * percent/100 = RISK = OrderLots * (|OrderOpenPrice - OrderStopLoss| * DeltaPerLot + CommissionPerLot) (Note OOP-OSL includes the spread, and DeltaPerLot is usually around $10/pip but it takes account of the exchange rates of the pair vs. your account currency.)

  3. Do NOT use TickValue by itself - DeltaPerLot and verify that MODE_TICKVALUE is returning a value in your deposit currency, as promised by the documentation, or whether it is returning a value in the instrument's base currency.
              MODE_TICKVALUE is not reliable on non-fx instruments with many brokers - MQL4 programming forum 2017.10.10
              Is there an universal solution for Tick value? - Currency Pairs - General - MQL5 programming forum 2018.02.11
              Lot value calculation off by a factor of 100 - MQL5 programming forum 2019.07.19

  4. You must normalize lots properly and check against min and max.

  5. You must also check FreeMargin to avoid stop out

Most pairs are worth about $10 per PIP. A $5 risk with a (very small) 5 PIP SL is $5/$10/5 or 0.1 Lots maximum.

Forum on trading, automated trading systems and testing trading strategies

How to calculate proper lot size ?

Fernando Carreiro, 2022.02.11 19:28

This is untested, uncompiled code, only to serve as a guide for you to further study and implement depending on your own requirements ...

// Calculate Max Lot Size based on Maximum Risk
double dblLotsRisk( double dbStopLoss, double dbRiskRatio )
{
   double
      dbLotsMinimum  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN       ),
      dbLotsMaximum  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX       ),
      dbLotsStep     = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP      ),
      dbTickSize     = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE  ),
      dbTickValue    = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_VALUE ),
      dbValueAccount = fmin( fmin( 
                       AccountInfoDouble( ACCOUNT_EQUITY      )  , 
                       AccountInfoDouble( ACCOUNT_BALANCE     ) ),
                       AccountInfoDouble( ACCOUNT_MARGIN_FREE ) ),
      dbValueRisk    = dbValueAccount * dbRiskRatio,
      dbLossOrder    = dbStopLoss * dbTickValue / dbTickSize,
      dbCalcLot      = fmin(  dbLotsMaximum,                  // Prevent too greater volume
                       fmax(  dbLotsMinimum,                  // Prevent too smaller volume
                       round( dbValueRisk / dbLossOrder       // Calculate stop risk
                       / dbLotsStep ) * dbLotsStep ) );       // Align to step value

   return ( dbCalcLot );
};
 
    double ticksize=MarketInfo(Symbol(),MODE_TICKVALUE)*10;
Tick value is not tick size.
 
Fernando Carreiro #:

Please search 🔍 before you post. Your question has already been discussed multiple times on the forum.

Here are some references, but please do a search and read other posts ...

I think that function also dont work right, if i give the function a 100 for stoploss and 1 for risk, then it give me for USDCAD someting like 0.12 lot but for bitcoin chart it give me 10 lot, that can not be right.

And what i want would be to give the function a atr value, because 100 pips is also on every chart different

I know people often ask this questions and for you moderators, you dont like to see same questions again and again, but think this way there is also a reason why some things are ask again and again the answers in other topics have not work and the more often you answer something the bigger the chance other will find it and see it and dont ask it always, its not easy to find solutions for metatrader codeing

if somebody find a really good working function please share, i will also try more test and try to post here if i find a good function

 
Metatrader Account #:

I think that function also dont work right, if i give the function a 100 for stoploss and 1 for risk, then it give me for USDCAD someting like 0.12 lot but for bitcoin chart it give me 10 lot, that can not be right.

And what i want would be to give the function a atr value, because 100 pips is also on every chart different

I know people often ask this questions and for you moderators, you dont like to see same questions again and again, but think this way there is also a reason why some things are ask again and again the answers in other topics have not work and the more often you answer something the bigger the chance other will find it and see it and dont ask it always, its not easy to find solutions for metatrader codeing

if somebody find a really good working function please share, i will also try more test and try to post here if i find a good function

If you want to claim that it does not work, then please provide actual data (output to the log) for the contract specifications of the symbol you are testing, namely these ...

      dbLotsMinimum  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN       ),
      dbLotsMaximum  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX       ),
      dbLotsStep     = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP      ),
      dbTickSize     = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE  ),
      dbTickValue    = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_VALUE ),

And besides the above, also show what values you are using for

double dbStopLoss, 
double dbRiskRatio

Without this information, your claim has no weight. Just like in science, you need to show real world values.

 
Fernando Carreiro #:

If you want to claim that it does not work, then please provide actual data (output to the log) for the contract specifications of the symbol you are testing, namely these ...

And besides the above, also show what values you are using for

Without this information, your claim has no weight. Just like in science, you need to show real world values.

I have attach a picture where you can see what your function does show for every value.

I am calling the function with this parameters: dblLotsRisk(100, 1);

On Bitcoin chart it give me to much lotsize, normaly it should give something smaller then what he give for USDCAD

I just can guess on share or other charts simular problems can happen, i think it is also important to use Contract Size in calculations, because sometimes that is also different at other brokers, i would really like to have a right working functions for this risk based lotsize calculations on metatrader.

Files:
alert.png  31 kb
 
Metatrader Account #: I have attach a picture where you can see what your function does show for every value. I am calling the function with this parameters: dblLotsRisk(100, 1); On Bitcoin chart it give me to much lotsize, normaly it should give something smaller then what he give for USDCAD. I just can guess on share or other charts simular problems can happen, i think it is also important to use Contract Size in calculations, because sometimes that is also different at other brokers, i would really like to have a right working functions for this risk based lotsize calculations on metatrader.

Please note that the parameter "dbStopLoss" is in price quote difference not in points, and "dbRiskRatio" is a ratio, not a percentage (1.0 means 100% risk)

So, your value of "100", is a stop-loss of 100.00 price difference or 10000 points/ticks in BTCUSD.

Given that the tick value is 0.01, one lot for a stop size of 100.00, is valued at 100.00 (in account balance).

So, if your risk amount is 960796.04..., then you would need 9607.9604 lots.

Since the allowed maximum is 10 lots, that is the result.

The function worked correctly. There is no error.

 
Fernando Carreiro #:

Please note that the parameter "dbStopLoss" is in price quote difference not in points, and "dbRiskRatio" is a ratio, not a percentage (1.0 means 100% risk)

So, your value of "100", is a stop-loss of 100.00 price difference or 10000 points/ticks in BTCUSD.

Given that the tick value is 0.01, one lot for a stop size of 100.00, is valued at 100.00 (in account balance).

So, if your risk amount is 960796.04..., then you would need 9607.9604 lots.

Since the allowed maximum is 100 lots, that is the result.

The function worked correctly. There is no error.


Can you give a example how i can use your function if i give the function a ATR value, if the atr in EURUSD is 0.0012 or in bitcoin chart the atr is 100, can your function calculate then a lotsize for that ATR value which does risk 1 percent?

Such function would be usefull, if you must write always different number in points then its to difficult, because every chart have to much different points, but using a ATR indicator number would be great

 
Metatrader Account #: Can you give a example how i can use your function if i give the function a ATR value, if the atr in EURUSD is 0.0012 or in bitcoin chart the atr is 100, can your function calculate then a lotsize for that ATR value which does risk 1 percent? Such function would be usefull, if you must write always different number in points then its to difficult, because every chart have to much different points, but using a ATR indicator number would be great

If you want a stop-loss of the size of one ATR with 1% risk, then...

double m_dbStopLoss  = dbATR, // One ATR value obtained elsewhere in the code
       m_dbRiskRatio = 0.01;  // 1% = 1/100 = 0.01
       m_dbLots      = dblLotsRisk( m_dbStopLoss, m_dbRiskRatio );
 
Fernando Carreiro #:

If you want a stop-loss of the size of one ATR with 1% risk, then...

Thank you for the example, it looks correct on Forex and Crypto when i call your function this way:

dblLotsRisk(iATR(Symbol(),PERIOD_H1,10,0), 0.01);

On chart lie US30 i think it also calculate correct but i get 1 lot because of minimum lotsize.

Reason: