Why is it so HARD to do lot sizing based on SL(points) and Percent Risk?

 

Hi I have been searching the web for a golden lot sizing function. I've tried MQL libraries, and even tutorials. Nothing works right.


I'd like to be able to take the following formulas and generate a lot size that is a percentage of risk defined of the user. For example, if the user defines 5% risk on a $1000 account he will be risking $50 from the trade.

SL = 20 Points (for example)

Risk = .05 (5%)

RiskAount = AccountEquity() * Risk

PricePerPoint = unknown (?)


If RiskAmount also is,

     RiskAmount = SL * PricePerPoint * Lots

Then, (using some basic Algebra)

     (RiskAmount/Lots) = SL * PricePerPoint

     (1/Lots) = (SL * PricePerPoint) / RiskAmount

     (Lots) = RiskAmount / (SL * PricePerPoint)

Given that the lot size is unknown but the amount we'd like to risk is. This would me that the size of the SL would shorten the number of lots as the SL becomes broader and increase the lots as it tightens.

The problem is I don't know who MT4 calculates the cost per point/pip. It clearly does this in the chart but why is there no standard function to give us this much needed valuable information.


** Correct me if I made a mistake. **


Thanks in advance.
 
Also this should be for more than just USD. For example, if the deposit currency is Bitcoin.
 
Not hard at all. For MT4:
  1. In code: Risk depends on your initial stop loss, lot size, and the value of the pair.
    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. Account Balance * 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.
    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=0.1 Lots maximum.
  2. Use a GUI EA like mine (for MT4): Indicators: 'Money Manager Graphic Tool' indicator by 'takycard' Forum - Page 6
 
whroeder1:
Not hard at all. For MT4:
  1. In code: Risk depends on your initial stop loss, lot size, and the value of the pair.
    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. Account Balance * 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.
    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=0.1 Lots maximum.
  2. Use a GUI EA like mine (for MT4): Indicators: 'Money Manager Graphic Tool' indicator by 'takycard' Forum - Page 6

Ok thanks a lot. That helped very much. This is what I came up with.

int sl=80;
double risk=.01; // 1%
double risk_amt=AccountBalance()*risk;
double delta=PriceUtil::DeltaValuePerLot(Symbol())*Point;
double lots=NormalizeDouble(risk_amt/sl/delta,2); // Volume

// Tested with deposit currency USD and with BIT
   

Note: I already have other code that verifies lot size with MODE_MINLOT and MODE_MAXLOT as well as the margin level which I use as follows.

int sl=20;
double risk=.02; // 2%
double lots=LotsFromRisk(sl,risk);
double minlot=MarketInfo(NULL,MODE_MINLOT);
double maxlot=MarketInfo(NULL,MODE_MAXLOT);

// Trim lot
lots=MathMin(lots,maxlot);

// Calculate margin level
double equity=AccountEquity();
double margin=AccountMargin();
double margin_level=margin!=0 ? (equity/margin)*100 : 0; // %

if(lots>=minlot)
{
        if(margin_level==0 || margin_level>=MIN_MARGIN_LEVEL)
        {
                // Place order
        }
}
Reason: