Best practice for accurate monetary value calculation (Points to Money) across different instruments?

 

Hi everyone,

I'm working on a custom tool that needs to calculate position sizing based on risk percentage. My tool needs to convert distance (in Points/Pips) into a monetary value (e.g., how much $ I lose/gain if price moves X points).

I've been using MarketInfo(Symbol(), MODE_TICKVALUE) to do this, but I've noticed that the reliability of this data varies significantly depending on the broker and the instrument (Forex vs. Gold vs. Indices). Sometimes the data is accurate, and other times it's completely off, which messes up my lot size calculation.

I want to know how the professionals handle this. What is the most robust/accurate way to calculate the monetary value of a price movement in MQL4, so that it works correctly across all brokers and asset classes without having to manually patch the TickValue for every specific pair?

Is there a mathematical standard that ensures the conversion is always accurate, regardless of the broker's server settings?

Any advice or code snippets on how to approach this "Universal Calculation" would be greatly appreciated. Thanks!

 
DjuharjatiHi everyone, I'm working on a custom tool that needs to calculate position sizing based on risk percentage. My tool needs to convert distance (in Points/Pips) into a monetary value (e.g., how much $ I lose/gain if price moves X points). I've been using MarketInfo(Symbol(), MODE_TICKVALUE) to do this, but I've noticed that the reliability of this data varies significantly depending on the broker and the instrument (Forex vs. Gold vs. Indices). Sometimes the data is accurate, and other times it's completely off, which messes up my lot size calculation. I want to know how the professionals handle this. What is the most robust/accurate way to calculate the monetary value of a price movement in MQL4, so that it works correctly across all brokers and asset classes without having to manually patch the TickValue for every specific pair? Is there a mathematical standard that ensures the conversion is always accurate, regardless of the broker's server settings? Any advice or code snippets on how to approach this "Universal Calculation" would be greatly appreciated. Thanks!
Hi! Great question - and the issue you're hitting is very common. The unreliability usually isn't the broker's data being "wrong"; it's that MODE_TICKVALUE alone is not enough. You also need MODE_TICKSIZE to scale it correctly.
The key insight: MODE_TICKVALUE gives you the value of one tick, but a tick is not always equal to a point. For Forex it often is, but for Gold and Indices the tick size frequently differs - which is exactly why your calculation works for some instruments and breaks for others.

The universal formula is:

moneyValue = tickValue * volume * (priceDistance / tickSize)

where priceDistance = MathAbs(entryPrice - exitPrice).

Here's a robust MQL4 helper I use in my own EAs. It mirrors how MQL5's native OrderCalcProfit() works, combining tick value and tick size:

// Estimates profit/loss in account currency for a given price move.
// Works across Forex, metals, and indices without manual patching.
bool CalcProfit(string symbol, int type, double volume,
                double priceOpen, double priceClose, double &profit)
{
   if(volume <= 0.0 || priceOpen <= 0.0 || priceClose <= 0.0)
      return false;

   double tickValue = MarketInfo(symbol, MODE_TICKVALUE);
   double tickSize  = MarketInfo(symbol, MODE_TICKSIZE);

   if(tickValue == 0.0 || tickSize == 0.0)
      return false;   // invalid specs — never proceed (would oversize the lot)

   int sign = ((type == OP_BUY  && priceClose < priceOpen) ||
               (type == OP_SELL && priceClose > priceOpen)) ? -1 : 1;

   profit = NormalizeDouble(tickValue * volume *
            (MathAbs(priceOpen - priceClose) / tickSize) * sign, 2);
   return true;
}

And then position sizing becomes:

double profit;
if(!CalcProfit(symbol, OP_BUY, 1.0, entryPrice, slPrice, profit))
   return; // abort — invalid data

double lossPerLot = -profit;                       // loss for 1.0 lot
if(lossPerLot < 0.01) return;                       // safety check

double maxLoss = AccountBalance() * riskPercent / 100.0;
double lots    = maxLoss / lossPerLot;

// normalize to broker's lot step
double step = MarketInfo(symbol, MODE_LOTSTEP);
lots = MathFloor(lots / step) * step;

Two critical safety points (learned the hard way):

1) Always validate that tickValue and tickSize are > 0 before dividing. If the broker returns invalid specs and you proceed anyway, you can get a dangerously oversized lot.

2) Reject the trade (return early) rather than falling back to a guessed value when data is invalid - failing safe is better than sizing on bad data.


This is broker-agnostic because you're letting the terminal provide the pre-converted tick value (already in your account currency), rather than computing currency conversions yourself - which is the fragile part that breaks across brokers.

Hope this helps!