SYMBOL_TRADE_TICK_VALUE_LOSS vs SYMBOL_TRADE_TICK_VALUE_PROFIT - page 7

 

Forum on trading, automated trading systems and testing trading strategies

SYMBOL_TRADE_TICK_VALUE_LOSS vs SYMBOL_TRADE_TICK_VALUE_PROFIT

amrali, 2023.02.24 07:49

If your account is in USD, you can calculate the "future" tick values for USDCAD or USDJPY like this:

double TICK_VALUE_LONG  = SYMBOL_TRADE_TICK_VALUE_LOSS;
double TICK_VALUE_SHORT = SYMBOL_TRADE_TICK_VALUE_PROFIT;

// If account currency == base currency, adjust TickValue to future rate (close). Works only for Forex pairs.
if((AccountCurrency == BaseCurrency) && (AccountCurrency != ProfitCurrency))
  {
   TICK_VALUE_LONG  *= SYMBOL_BID / price_close;     // i.e., (1/Bid) * Bid / future_bid   = 1 / future_bid
   TICK_VALUE_SHORT *= SYMBOL_ASK / price_close;     // i.e., (1/Ask) * Ask / future_ask   = 1 / future_ask
  }


Or better use OrderCalcProfit() which already implements the above feature


I think it is enough for this thread. I do not have much to add.

 

I have no idea why Fernando, Alain and Amrali are struggling to get exact values from the code they use to calculate profits for open positions. Of course sometimes you can only know the current profit and the conversion might be different when you close the position, like if I trade EURCAD on a USD account, but for anything else, I don't know why their values don't match. I hope their brokers aren't ripping them off on the backend of their trades!

Maybe some of you only get approximate values from your code because your brokers convert your profits differently than mine, but the methods I use like OrderCalcProfit, POSITION_PROFIT or manual conversion using tick values all give me matching results on live trades.

So if you aren't getting the same results, you may as well give up because it's probably not your fault.

// calculate position profit

input int profit_digits = 2;

ENUM_ORDER_TYPE order_type;
bool use_future_tick_value;
double volume,open_price,close_price,position_profit,price_change,profit_in_points,tick_value;
string symbol,results,comment_string,direction_string,lots_string;
string account_currency,base_currency,quote_currency;

// compare manual calculation with OrderCalcProfit()
double OrderCalcProfit_value;

int OnInit() {

        if (!PositionSelect(_Symbol)) Print("can't select order");
        open_price = PositionGetDouble(POSITION_PRICE_OPEN);
        close_price = PositionGetDouble(POSITION_PRICE_CURRENT);
        volume = PositionGetDouble(POSITION_VOLUME);
        symbol = PositionGetString(POSITION_SYMBOL);
        order_type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE);

        account_currency = AccountInfoString(ACCOUNT_CURRENCY);
        base_currency = SymbolInfoString(NULL,SYMBOL_CURRENCY_BASE);
        quote_currency = SymbolInfoString(NULL,SYMBOL_CURRENCY_PROFIT);
        
        if (account_currency != quote_currency && account_currency == base_currency) {
                use_future_tick_value = true;
        } else { 
                use_future_tick_value = false;
        }
        
        if (volume != 1) lots_string = "lots";
        else lots_string = "lot";
        
        if (order_type == (int)ORDER_TYPE_BUY) {
                direction_string = "buying";
        } else if (order_type == (int)ORDER_TYPE_SELL) {
                direction_string = "selling";
        } else {
                Comment("wrong order type");
        }

        comment_string = "Current profits if " + direction_string + " " + DoubleToString(volume,2) + " " + lots_string;
        comment_string += " with open price " + DoubleToString(open_price,_Digits);
        comment_string += " on " + symbol + ":";
        
        Calc_profit();
        
        return(INIT_SUCCEEDED);

}

void OnDeinit(const int reason) {
        
        if (IsStopped()) Comment("");

} 

void Calc_profit() {
        
        if (!PositionSelect(_Symbol)) Print("can't select order");
        close_price = PositionGetDouble(POSITION_PRICE_CURRENT);
        
        if (order_type == (int)ORDER_TYPE_BUY) {
                // buy orders   
                price_change = close_price - open_price;
                tick_value = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
                if (use_future_tick_value) {
                        tick_value *= SymbolInfoDouble(symbol,SYMBOL_BID) / close_price;
                }                       
        } else if (order_type == (int)ORDER_TYPE_SELL) {
                // sell orders  
                price_change = open_price - close_price;
                tick_value = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_PROFIT);
                if (use_future_tick_value) {
                        tick_value *= SymbolInfoDouble(symbol,SYMBOL_ASK) / close_price;
                }
        } else {
                Comment("wrong order type");
        }
        
        // manual calculation
        profit_in_points = price_change * MathPow(10,_Digits);
        position_profit = tick_value * profit_in_points * volume;
        
        results = comment_string;
        results += "\nManual calculation: ";
        results += DoubleToString(position_profit,profit_digits) + " " + account_currency;
        
        // compare with OrderCalcProfit()
        results += "\nOrderCalcProfit():  ";
        if (OrderCalcProfit(order_type,symbol,volume,open_price,close_price,OrderCalcProfit_value)) {
                results += DoubleToString(OrderCalcProfit_value,profit_digits) + " " + account_currency;
        } else {
                results += "error";
        }
        results += "\nTerminal profit:     ";
        results += DoubleToString(PositionGetDouble(POSITION_PROFIT),profit_digits) + " " + account_currency;
        
        Comment(results);

}

void OnTick() {

        Calc_profit();

}
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Position Properties
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Position Properties
  • www.mql5.com
Position Properties - Trade Constants - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Jeepack #: I have no idea why Fernando, Alain and Amrali are struggling to get exact values from the code they use to calculate profits for open positions. Of course sometimes you can only know the current profit and the conversion might be different when you close the position, like if I trade EURCAD on a USD account, but for anything else, I don't know why their values don't match. I hope their brokers aren't ripping them off on the backend of their trades! Maybe some of you only get approximate values from your code because your brokers convert your profits differently than mine, but the methods I use like OrderCalcProfit, POSITION_PROFIT or manual conversion using tick values all give me matching results on live trades. So if you aren't getting the same results, you may as well give up because it's probably not your fault.

Who said I am struggling?

I have no such issue!

Are we even talking about the same thing?

EDIT: I will repeat myself. It is only an approximation, because it is IMPOSSIBLE to know the future tick value at closing time, except when the account currency is the same as the quote currency.

Also, given that the volume has less resolution than the price (volume usually only has 2 digits), the approximation is more than enough to get the exact volume to be correct even if the tick value deviates a bit.

So, I will say again, you are making a mountain out of a molehill.

 
Fernando Carreiro #:

Who said I am struggling?

I have no such issue!

Are we even talking about the same thing? 

EDIT: I will repeat myself. It is only an approximation, because it is IMPOSSIBLE to know the future tick value at closing time, except when the account currency is the same as the quote currency.

Also, given that the volume has less resolution than the price (volume usually only has 2 digits), the approximation is more than enough to get the exact volume to be correct even if the tick value deviates a bit.

So, I will say again, you are making a mountain out of a molehill.

When your account currency is the base currency and the quote currency is different, if you know the closing price, you can calculate the future tick value and get an exact value. If you don't know this and trade multiple lots like me, this will be an issue when calculating your position size. It's been said multiple times in this thread so I don't know why this is still up for debate. While you say that I'm wasting my time, you haven't provided a single example to support your claim when I have made efforts to provide multiple examples to prove this and shared them openly in this thread. You have a lot of experience and I'm sure you have tought me many things since I started coding and posting questions on this forum, but this time, you are wrong.

 
Jeepack #:

When your account currency is the base currency and the quote currency is different, if you know the closing price, you can calculate the future tick value and get an exact value. If you don't know this and trade multiple lots like me, this will be an issue when calculating your position size. It's been said multiple times in this thread so I don't know why this is still up for debate. While you say that I'm wasting my time, you haven't provided a single example to support your claim when I have made efforts to provide multiple examples to prove this and shared them openly in this thread. You have a lot of experience and I'm sure you have tought me many things since I started coding and posting questions in this forum. But this time, you are wrong.

Yes, I was incorrect! I should have written that when the account currency is either the base or the quote currency, you can know the future tick value.

I have not provided any examples, because I am not claiming anything at all. For me the current known methods are enough. All I have stated is that ...

  1. The two tick values (profit/loss) are for me misnamed (and all three of you have already come to that conclusion, so there is nothing more for me to say).
  2. The future tick value is unknown (with the above exception), so the current method of using the current tick value is for me sufficient of an approximation and I have no need for further refinement.
  3. The main goal for using the tick size and its value is to calculate a volume for one's desired risk, and given that the volume (lots) is of lower precision than the calculation yields, the resulting volume has enough tolerance, allowing the final tick value to deviate quite a bit and still not affect the calculated volume. In other words the final loss (risk) is within the tolerance allowed by the lower precision of the volume (lots).

That said, I find that there is no need to delve deeper down the rabbit hole (except for academic purposes), because the current method is more than good enough to guarantee that a strategy's success is not in any way negatively affected by the approximation.

So, unless you are studying this for academic purposes, I would urge you to focus on the other aspects of your EA and strategy and not get hung up on this. Just use the OrderCalcProfit and OrderCalcMargin and move on.

As a well know trader's saying goes ... Do you want to be right or do you want to make money?

That is in essence what I have been trying to convey, that your energy and focus should be on other aspects of EAs and strategies, instead of this one. That is all.

 
Fernando Carreiro #:

Yes, I was incorrect! I should have written that when the account currency is either the base or the quote currency, you can know the future tick value.

I have not provided any examples, because I am not claiming anything at all. For me the current known methods are enough. All I have stated is ...

  1. The the two tick values (profit/loss) are for me misnamed (and all three of you have already come to that conclusion, so there is nothing more for me to say).
  2. The future tick value is unknown (with the above exception), so the current method of using the current tick value is for me sufficient of an approximation and I have no need for further refinement.
  3. The main goal for using the tick size and its value is to calculate a volume for one's desired risk, and given that the volume (lots) is of lower precision than the calculation yields, the resulting volume has enough tolerance, allowing the final tick value to deviate quite a bit and still not affect the calculated volume. In other words the final loss (risk) is within the tolerance allowed by the lower precision of the volume (lots).

That said, I find that there is no need to delve deeper down the rabbit hole (except for academic purposes), because the current method is more than good enough to guarantee that a strategy's success is not in any way negatively affected by the approximation.

So, unless you are studding this for academic purposes, I would urge you to focus on the other aspects of your EA and strategy and not get hung up on this. Just use the OrderCalcProfit and OrderCalcMargin and move on.

As a well know trader's saying goes ... Do you want to be right or do you want to make money?

That is in essence what I have been trying to convey, that your energy and focus should be on other aspects of EAs and strategies, instead of this one. That is all.

Ok, as long as the information you provide is correct, everything is good. Thank you for making the correction. I agree with you that the impact of this change will be minimal, you are 100% correct, but this correction could be important for someone who wants to remove imperfections from their position size calculation when they trade multiple lots. For example, with a typical FX position, for me, this change can mean a difference of 0.01 in my lot size and if I double the account size, it can now easily change my lot size by 0.03 lots. This isn't going to make a significant difference on one single trade, but if I compound this difference over hundreds of trades, it starts to have a real impact that I would prefer avoiding. I'm glad we understand each other a bit better now because I have great respect for your knowledge and experience. Thank you for your input.

 
Jeepack #: For example, with a typical FX position, for me, this change can mean a difference of 0.01 in my lot size and if I double the account size, it can now easily change my lot size by 0.03 lots. This isn't going to make a significant difference on one single trade, but if I compound this difference over hundreds of trades, it starts to have a real impact that I would prefer avoiding.

I don't agree with that statement based mostly on empirical deduction and not so much on mathematical analysis, so I could be wrong.

My reasoning is as follows—volume (lots) usually has lower precision than price. This is not always the case but it is for many of the symbols.

So as an example. let use assume a volume step of 0.01 lots and a tick size of 0.00001 (there is a 3 digit difference in precision). With 0.01 lots and a stop-loss of 1000 ticks, the risk is 10 tick-lot.

So, for a rounding tolerance of +0.005/-0.005 lots, this means that the tick-value can deviate between -33% and 100% of its current value and still yield the exact some volume for the risk calculation (these are just quick off the head calculations, assuming a tick value close to the tick size).

Obviously for a 3 digit symbol like USDJPY, then the tolerated deviation is much tighter, but the example above just serves as a quick example to show that the tolerance is quite high.

Again, I am not going to go down this rabbit hole, so feel free to dig in and fully analyse the math for yourself of these tolerances if you wish.

 
Fernando Carreiro #:

Again, I am not going to go down this rabbit hole, so feel free to dig in and fully analyse the math for yourself of these tolerances if you wish.

I think the math checks out, as long as you're trading multiple lots. For example, if you start with a quote of 1.30000 and your stop loss is at -0.5% (-0,00650), then the tick value for the loss would be multiplied by 1.005 (1.30000 / 1.29350). So if you trade 2 lots, 2 / 1.005 = 1.99 lots. You are right, this is a very small difference. But I prefer making the adjustment.

 
Jeepack #: I think the math checks out, as long as you're trading multiple lots. For example, if you start with a quote of 1.30000 and your stop loss is at -0.5% (-0,00650), then the tick value for the loss would be multiplied by 1.005 (1.30000 / 1.29350). So if you trade 2 lots, 2 / 1.005 = 1.99 lots. You are right, this is a very small difference. But I prefer making the adjustment.

Here is a more concrete calculation with exact calculations instead of my "off the head" ones:

Balance: €1000
Risk (1%): €10
Stop-loss: 1000 ticks
Symbol: EURUSD
Current price: 1.05451

Current tick value: $1 = €0.948307744829352
Risk for 1 Lot = 1000 ticks x tick-value = €948.307744829352
Volume = €10 / €948.307744829352 = 0.0105451 ≈ 0.01 (rounded)

Question: What values of tick-value would result in the same volume being calculated? What tolerance is allowed?

In other words, a volume of 0.0149999999999 maximum and 0.005 minimum would result in the same volume of 0.01 (when rounded).

So for a volume of 0.005, the tick value can be a maximum of 2.0, and for a volume of 0.014999999999, the tick value can be a minimum of  0.66666666.

Converting this back into a price, this means that the EURUSD price can vary between 0.50000 and 1.50000 . This is a total range of 100000 ticks, which is way beyond our stop loss of only 1000 ticks.

So, as you can see by the above example, the tolerance is so huge that any amount of reasonable deviation in your calculations based solely on the current tick value instead of future value, has no impact on the calculation of your volume due to the limited precision of said volume.

EDIT: This is why I believed the discussion was fruitless, because wanting to get so much precision, just to have it slashed by rounding it to the volume precision, seemed to me only valuable academically, but not in practice.

However, what may be fruitless to me, may be of great importance to others, so maybe I should have explained this early on instead of now.

 
Jeepack #:

I have no idea why Fernando, Alain and Amrali are struggling to get exact values from the code they use to calculate profits for open positions. Of course sometimes you can only know the current profit and the conversion might be different when you close the position, like if I trade EURCAD on a USD account, but for anything else, I don't know why their values don't match. I hope their brokers aren't ripping them off on the backend of their trades!

Maybe some of you only get approximate values from your code because your brokers convert your profits differently than mine, but the methods I use like OrderCalcProfit, POSITION_PROFIT or manual conversion using tick values all give me matching results on live trades.

So if you aren't getting the same results, you may as well give up because it's probably not your fault.

Did you try it on a live market, a symbols which are not using the account currency ? It's very hard to have exact values because MT5 is by nature asynchronous, it can happens and it effectively happens that the needed quote (or tickvalue) is changed between the time your get POSITION_PROFIT and the time you calculate the profit. Anyway, it doesn't really matter.

Your correction doesn't make sense on an open position.

close_price = PositionGetDouble(POSITION_PRICE_CURRENT);Print(close_price);
        
        if (order_type == (int)ORDER_TYPE_BUY) {
                // buy orders   
                price_change = close_price - open_price;
                tick_value = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
                if (use_future_tick_value) {
                        tick_value *= SymbolInfoDouble(symbol,SYMBOL_BID) / close_price;
                }                       
        } else if (order_type == (int)ORDER_TYPE_SELL) {
                // sell orders  
                price_change = open_price - close_price;
                tick_value = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_PROFIT);
                if (use_future_tick_value) {
                        tick_value *= SymbolInfoDouble(symbol,SYMBOL_ASK) / close_price;
                }

For a BUY, Bid = current price (close_price). For a SELL, Ask = current price (close_price). Your correction do nothing. It only makes sense when the close price is the future closure price.

Additionally you need to use POSITION_TYPE_BUY and POSITION_TYPE_SELL, and not ORDER_TYPE_BUY/ORDER_TYPE_SELL. By chance these enum values are the same, so it has no impact, but it's a logical bug nonetheless.

Reason: