How is the new EntryPrice (& thus Pips etc) of a modified or partially closed Position calculated?

Created at 14 Nov 2024, 00:07
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
MA

martins

Joined 22.10.2019

How is the new EntryPrice (& thus Pips etc) of a modified or partially closed Position calculated?
14 Nov 2024, 00:07


How does cTrader decide the new EntryPrice (and thus Pips & net/gross profit etc) of a Position after part of it has been closed (either by close-with-new-volume or modify-with smaller-volume, they both seem to do the same)? 
A simplistic calculation would be to leave Entry unchanged, as if you'd had 2 same-price positions open and just closed one, but it seems to be more involved. Also how is the calculation done when a position is increased? Thanks Martin.

 

For example reducing the volume to approx 1/10 from 585000 to 55000 in this log resulted in a new Entry price 1.37171 near (but not at) the middle of the original Entry 1.36734 & the price of 1.37818 when the change was made (therefore the Pips roughly halved):

closePartPosition: volume=530000 Id=11 Buy
before: id=11  symbol=GBPUSD  type=BUY   vol=585000  entry=1.36734  pips 108.4  netprofit=4593.89  grossprofit=4778.68  swap -149.69  commissions=-17.55
after: id=11  symbol=GBPUSD  type=BUY   vol=55000  entry=1.37171  pips 64.7  netprofit=250.7265812  grossprofit=268.1  swap -14.0734188  commissions=-1.65
closePartPosition: lastCloseBuyPrice=1.37818 lastCloseSellPrice=1.37821 (up -136.9665811 new Equity=1459.3834189   up 4343.1634189 new Balance=1498.2334189)

I've seen https://ctrader.com/forum/ctrader-algo/38685/ which seems to imply the EntryPrice didn't used to change in 2017, which may have been right for reducing volume, but it seems to adjust after volume modification up and down now.
 


@martins
Replies

PanagiotisCharalampous
14 Nov 2024, 06:48

Hi there,

The entry price of the position is the average entry price of the deals composing the position. If the position has only one opening deal, then the opening price should not change. If more opening deals are involved e.g. you have increased the size of the position after entering it, the entry price might change as partial volume is closed and deals removed from the position.

Best regards,

Panagiotis


@PanagiotisCharalampous

martins
14 Nov 2024, 17:28 ( Updated at: 15 Nov 2024, 00:28 )

RE: How is the new EntryPrice (& thus Pips etc) of a modified or partially closed Position calculated?

PanagiotisCharalampous said: 

Hi there,

The entry price of the position is the average entry price of the deals composing the position. If the position has only one opening deal, then the opening price should not change. If more opening deals are involved e.g. you have increased the size of the position after entering it, the entry price might change as partial volume is closed and deals removed from the position.

Best regards,

Panagiotis

Ok, thanks, that's helpful. I can see from logging that when the volume of a position is INCREASED the calculation of its new Position.Pips value is exactly:
 (oldPips * oldVol - spreadAsPips * increaseInVol) / newVol
which is correctly distributing the pips on the old portion plus the immediate pip loss of the new portion (due to spread) across the new larger volume (and so the EntryPrice will be that many pips from the current price and represent the weighted average). Rounding of the calculation seems usually to the nearest 0.1 pip but sometimes goes the other way, possibly to correct for accumulated rounding error. That's all fine.

HOWEVER, I'm seeing the remaining portion of a position after a REDUCTION in volume ALSO has its Position.Pips altered. Why is that?
Possibly the position was not combined really (in the live server or backtest memory) but rather kept as a collection of parts from each modification that increased volume, so that when it is later reduced some specific part is closed, in a LIFO or FIFO order or some other rule? Is this broker driven? 

So maybe ModifyPosition does not really modify a position in the sense of ending up with one homogeneous position with a single EntryPrice & Pips profit? Can't brokers running cTrader handle merging modification deals into one net holding?

If not, please could the doc say so, and how do we know what the separate parts are so we can predict partial closing results (without laboriously keeping track of all modifications)? Is there any information in a Position that can tell a cBot the position's stats will not react in a predictable way if later PARTIALLY closed ('predictable' meaning Entry & Pips stay unchanged, profit prorata etc)? 

I'm coming to the conclusion it's not good to mix increasing and decreasing volume via ModifyPosition; one or the other yes, predictable, but not both in the same cBot if it's basing decisions on Position.Pips or Account.UnrealizedProfit, or on almost anything other than Equity.

Thanks.

 

Update re "laboriously keeping track": not that hard, but involves keeping ‘account state’ data outside the cTrader account, like in a local file or cloud, not self-contained in the positions - unless perhaps cTrader could add a large Account.Comment field that could store arbitrary data, or make the Positions.Comment modifyable & bigger?? :) 


modifyDeals.Count=95 i=58 modifyDeals[i].Id=6 modifyDeals[i].Vol=19000 modifyDeals[i].Bid=1.36653 modifyDeals[i].Ask=1.36656
modifyDeals.Count=95 i=59 modifyDeals[i].Id=6 modifyDeals[i].Vol=13000 modifyDeals[i].Bid=1.36404 modifyDeals[i].Ask=1.36407
modifyDeals.Count=95 i=60 modifyDeals[i].Id=5 modifyDeals[i].Vol=4000 modifyDeals[i].Bid=1.36399 modifyDeals[i].Ask=1.36402
modifyDeals.Count=95 i=61 modifyDeals[i].Id=6 modifyDeals[i].Vol=-230000 modifyDeals[i].Bid=1.3605 modifyDeals[i].Ask=1.36053
modifyDeals.Count=95 i=62 modifyDeals[i].Id=5 modifyDeals[i].Vol=-230000 modifyDeals[i].Bid=1.3605 modifyDeals[i].Ask=1.36053
modifyDeals.Count=95 i=63 modifyDeals[i].Id=6 modifyDeals[i].Vol=-77000 modifyDeals[i].Bid=1.36007 modifyDeals[i].Ask=1.3601
modifyDeals.Count=95 i=64 modifyDeals[i].Id=5 modifyDeals[i].Vol=-77000 modifyDeals[i].Bid=1.36007 modifyDeals[i].Ask=1.3601
modifyDeals.Count=95 i=65 modifyDeals[i].Id=6 modifyDeals[i].Vol=10000 modifyDeals[i].Bid=1.35909 modifyDeals[i].Ask=1.35912
modifyDeals.Count=95 i=66 modifyDeals[i].Id=5 modifyDeals[i].Vol=19000 modifyDeals[i].Bid=1.36651 modifyDeals[i].Ask=1.36654
modifyDeals.Count=95 i=67 modifyDeals[i].Id=5 modifyDeals[i].Vol=10000 modifyDeals[i].Bid=1.36892 modifyDeals[i].Ask=1.36895
modifyDeals.Count=95 i=68 modifyDeals[i].Id=5 modifyDeals[i].Vol=13000 modifyDeals[i].Bid=1.37044 modifyDeals[i].Ask=1.37047

  struct modifyDeal {     // https://stackoverflow.com/questions/33809867/c-sharp-struct-in-a-list
  public int Id { get; set; }
  public double Vol { get; set; }
  public double Bid { get; set; }
  public double Ask { get; set; }
  public modifyDeal(int id, double vol, double bid, double ask)
  { Id = id; Vol = vol; Bid = bid; Ask = ask; }
 }

 List<modifyDeal> modifyDeals = new List<modifyDeal>(); // 14nov24

    var deal = new modifyDeal(position.Id, newVolume - position.VolumeInUnits, Symbol.Bid, Symbol.Ask);
   //or deal.Id = position.Id; etc
   modifyDeals.Add(deal); 

Might be able to extract same info using the History interface possibly (how far back does it go?), but haven't found all the doc about it, for instance where is History.OrderByDescending() other than in the example https://help.ctrader.com/ctrader-algo/references/Trading/History/History/#examples 

Later: Actually only one adjustment number per position might need remembering in order to emulate proportional netting when partially closing a position that has been increased earlier - the difference between ‘the proportional Pips or Entry expected before the partial close is done’ and ‘the actual new Pips or new Entry that appears in the Position afterwards’ - so the Bot can apply that offset to later Pips & profit (with opposite adjustment to Balance).
Is there any way of storing a small amount of data per position on the server, for instance a modifyable Comment? 
 


@martins

PanagiotisCharalampous
15 Nov 2024, 06:51

RE: RE: How is the new EntryPrice (& thus Pips etc) of a modified or partially closed Position calculated?

martins said: 

PanagiotisCharalampous said: 

Hi there,

The entry price of the position is the average entry price of the deals composing the position. If the position has only one opening deal, then the opening price should not change. If more opening deals are involved e.g. you have increased the size of the position after entering it, the entry price might change as partial volume is closed and deals removed from the position.

Best regards,

Panagiotis

Ok, thanks, that's helpful. I can see from logging that when the volume of a position is INCREASED the calculation of its new Position.Pips value is exactly:
 (oldPips * oldVol - spreadAsPips * increaseInVol) / newVol
which is correctly distributing the pips on the old portion plus the immediate pip loss of the new portion (due to spread) across the new larger volume (and so the EntryPrice will be that many pips from the current price and represent the weighted average). Rounding of the calculation seems usually to the nearest 0.1 pip but sometimes goes the other way, possibly to correct for accumulated rounding error. That's all fine.

HOWEVER, I'm seeing the remaining portion of a position after a REDUCTION in volume ALSO has its Position.Pips altered. Why is that?
Possibly the position was not combined really (in the live server or backtest memory) but rather kept as a collection of parts from each modification that increased volume, so that when it is later reduced some specific part is closed, in a LIFO or FIFO order or some other rule? Is this broker driven? 

So maybe ModifyPosition does not really modify a position in the sense of ending up with one homogeneous position with a single EntryPrice & Pips profit? Can't brokers running cTrader handle merging modification deals into one net holding?

If not, please could the doc say so, and how do we know what the separate parts are so we can predict partial closing results (without laboriously keeping track of all modifications)? Is there any information in a Position that can tell a cBot the position's stats will not react in a predictable way if later PARTIALLY closed ('predictable' meaning Entry & Pips stay unchanged, profit prorata etc)? 

I'm coming to the conclusion it's not good to mix increasing and decreasing volume via ModifyPosition; one or the other yes, predictable, but not both in the same cBot if it's basing decisions on Position.Pips or Account.UnrealizedProfit, or on almost anything other than Equity.

Thanks.

 

Update re "laboriously keeping track": not that hard, but involves keeping ‘account state’ data outside the cTrader account, like in a local file or cloud, not self-contained in the positions - unless perhaps cTrader could add a large Account.Comment field that could store arbitrary data, or make the Positions.Comment modifyable & bigger?? :) 


modifyDeals.Count=95 i=58 modifyDeals[i].Id=6 modifyDeals[i].Vol=19000 modifyDeals[i].Bid=1.36653 modifyDeals[i].Ask=1.36656
modifyDeals.Count=95 i=59 modifyDeals[i].Id=6 modifyDeals[i].Vol=13000 modifyDeals[i].Bid=1.36404 modifyDeals[i].Ask=1.36407
modifyDeals.Count=95 i=60 modifyDeals[i].Id=5 modifyDeals[i].Vol=4000 modifyDeals[i].Bid=1.36399 modifyDeals[i].Ask=1.36402
modifyDeals.Count=95 i=61 modifyDeals[i].Id=6 modifyDeals[i].Vol=-230000 modifyDeals[i].Bid=1.3605 modifyDeals[i].Ask=1.36053
modifyDeals.Count=95 i=62 modifyDeals[i].Id=5 modifyDeals[i].Vol=-230000 modifyDeals[i].Bid=1.3605 modifyDeals[i].Ask=1.36053
modifyDeals.Count=95 i=63 modifyDeals[i].Id=6 modifyDeals[i].Vol=-77000 modifyDeals[i].Bid=1.36007 modifyDeals[i].Ask=1.3601
modifyDeals.Count=95 i=64 modifyDeals[i].Id=5 modifyDeals[i].Vol=-77000 modifyDeals[i].Bid=1.36007 modifyDeals[i].Ask=1.3601
modifyDeals.Count=95 i=65 modifyDeals[i].Id=6 modifyDeals[i].Vol=10000 modifyDeals[i].Bid=1.35909 modifyDeals[i].Ask=1.35912
modifyDeals.Count=95 i=66 modifyDeals[i].Id=5 modifyDeals[i].Vol=19000 modifyDeals[i].Bid=1.36651 modifyDeals[i].Ask=1.36654
modifyDeals.Count=95 i=67 modifyDeals[i].Id=5 modifyDeals[i].Vol=10000 modifyDeals[i].Bid=1.36892 modifyDeals[i].Ask=1.36895
modifyDeals.Count=95 i=68 modifyDeals[i].Id=5 modifyDeals[i].Vol=13000 modifyDeals[i].Bid=1.37044 modifyDeals[i].Ask=1.37047

  struct modifyDeal {     // https://stackoverflow.com/questions/33809867/c-sharp-struct-in-a-list
  public int Id { get; set; }
  public double Vol { get; set; }
  public double Bid { get; set; }
  public double Ask { get; set; }
  public modifyDeal(int id, double vol, double bid, double ask)
  { Id = id; Vol = vol; Bid = bid; Ask = ask; }
 }

 List<modifyDeal> modifyDeals = new List<modifyDeal>(); // 14nov24

    var deal = new modifyDeal(position.Id, newVolume - position.VolumeInUnits, Symbol.Bid, Symbol.Ask);
   //or deal.Id = position.Id; etc
   modifyDeals.Add(deal); 

Might be able to extract same info using the History interface possibly (how far back does it go?), but haven't found all the doc about it, for instance where is History.OrderByDescending() other than in the example https://help.ctrader.com/ctrader-algo/references/Trading/History/History/#examples 

Later: Actually only one adjustment number per position might need remembering in order to emulate proportional netting when partially closing a position that has been increased earlier - the difference between ‘the proportional Pips or Entry expected before the partial close is done’ and ‘the actual new Pips or new Entry that appears in the Position afterwards’ - so the Bot can apply that offset to later Pips & profit (with opposite adjustment to Balance).
Is there any way of storing a small amount of data per position on the server, for instance a modifyable Comment? 
 

Hi there,

HOWEVER, I'm seeing the remaining portion of a position after a REDUCTION in volume ALSO has its Position.Pips altered. Why is that?
Possibly the position was not combined really (in the live server or backtest memory) but rather kept as a collection of parts from each modification that increased volume, so that when it is later reduced some specific part is closed, in a LIFO or FIFO order or some other rule? Is this broker driven? 

This is what I explained in my previous post. Positions are just collections of deals traded in a FIFO manner.

Is there any information in a Position that can tell a cBot the position's stats will not react in a predictable way if later PARTIALLY closed ('predictable' meaning Entry & Pips stay unchanged, profit prorata etc)? 

There isn't. As you correctly pointed out, if you need this information, you need to track it your self. 

Best regards,

Panagiotis


@PanagiotisCharalampous