Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Problems with Position.AveragePrice

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Problems with Position.AveragePrice

    I'd like to raise something regarding a potential problem with the position average prices as calculated by NT8.

    This problem seems to occur when you have a strategy which has multiple partial entries and exits (i.e. rebalancing).

    The strategy I have runs on two instruments (same problem with single instrument though), and rebalances every week or every other week (leading to a large amount of partial entries and exits). The strategy calculates the desired position sizes by using the current net capital of the strategy by summing the realized P&L and the open P&L for all instruments with an open position. Profits or losses in a short leg then require a rebalance in both positions.

    Unfortunately, I'm not able to provide a sample strategy as there is far too much use of custom methods/framework and I don't have the time to strip stuff out. I've already spent way too much time helping report/debug/resolve problems with NT8. However, if you'd like me to help print any outputs to help resolve this issue, I'd be happy to do so as it's considerably less effort.

    Here is a code snippet though which will help explain the output further below:

    Code:
    double RealizedPL		= SystemPerformance.AllTrades.TradesPerformance.Currency.CumProfit;
    double OpenPL 			= 0;
    
    foreach (InstrumentClass o in TradedList)
    {
    	if (o.HasPosition)
    	{
    		OpenPL = OpenPL + Positions[o.Index].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[o.Index][0]);
    		Print("[" + o.Index + "] Unrealized P/L = " + Positions[o.Index].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[o.Index][0]).ToString("C"));
    	}
    }
    
    Print(RealizedPL.ToString("C") + " + " + OpenPL.ToString("C") + " = " + (RealizedPL + OpenPL).ToString("C"));
    
    Print("[Stats] Total P&L = " + Metrics.TotalProfitLoss.ToString("C") + " / " + (Metrics.TotalProfitLoss / Metrics.InitialCapital).ToString("P"));
    
    if (States.HasPositions &&
    	Times[0][0] >= new DateTime(2015, 1, 30))
    {
    	Print("Closing Positions");
    	DoFlatten();
    }
    As you can see from my output below, the unrealized P&L components are inflated or calculated incorrectly, causing the total P&L to be revised sharply downward (look at the difference between Jan 30 and Feb 2) when the code above forces the strategy to close existing positions. The correct P&L as shown in the Strategy Analyzer and by summing the P&L for all trades is the lesser amount.

    Code:
    -------------------- [1398] Session Open: January 29, 2015 @ 09:30:00 --------------------
    [Capital Management] Current Capital = $1,779,056.46
    [2] Unrealized P/L = $579,751.77
    [1] Unrealized P/L = $501,303.60
    $617,822.32 + $1,081,055.37 = $1,698,877.69
    [Stats] Total P&L = $1,698,877.69 / 1,698.88 %
    
    -------------------- [1399] Session Open: January 30, 2015 @ 09:30:00 --------------------
    [Capital Management] Current Capital = $1,798,877.69 | Previous Capital = $1,779,056.46
    [2] Unrealized P/L = $610,763.38
    [1] Unrealized P/L = $452,764.71
    $617,822.32 + $1,063,528.09 = $1,681,350.42
    [Stats] Total P&L = $1,681,350.42 / 1,681.35 %
    Closing Positions
    
    -------------------- [1400] Session Open: February 2, 2015 @ 09:30:00 --------------------
    [Capital Management] Current Capital = $1,131,536.93 | Previous Capital = $1,798,877.69
    [2] Unrealized P/L = ($335.01)
    [1] Unrealized P/L = ($252.96)
    $1,031,412.14 + ($587.97) = $1,030,824.17
    [Stats] Total P&L = $1,030,824.17 / 1,030.82 %
    Fortunately, the easy solution to this problem is going into Tools > Options > Trading > Calculations > Use FIFO for position average price. Assuming that the weighted average cost method is used when FIFO is not ticked, I'd prefer this (so perhaps this issue is worth looking into, but not a huge dealbreaker).

    #2
    Hello wuileng,

    Thanks for reporting there may be incorrect behavior with the Position.AveragePrice.

    As no simplified test script was supplied, I will create a test script on your behalf when resources are available. A test script is required for us to report an issue to our development.

    I'd like to clarify what we are comparing.

    You are comparing the realized pnl of this strategy only
    Code:
    SystemPerformance.AllTrades.TradesPerformance.Currency.CumProfit;
    With accumulated unrealized pnl of a list of strategies
    Code:
    foreach (InstrumentClass o in TradedList)
    {
    	if (o.HasPosition)
    	{
    		OpenPL = OpenPL + Positions[o.Index].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[o.Index][0]);
    		Print("[" + o.Index + "] Unrealized P/L = " + Positions[o.Index].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[o.Index][0]).ToString("C"));
    	}
    }
    And finding these are not the same. Is this correct?
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Hi,

      What I'm doing is comparing the realized PnL for this strategy as you mentioned, with the unrealized PnL of all instruments this strategy trades (TradedList), for which open positions are recorded (o.HasPosition which is updated on every bar by another method).

      What I'm trying to illustrate in my example, is this:

      $617,822.32 + $1,081,055.37 = $1,698,877.69
      $617,822.32 + $1,063,528.09 = $1,681,350.42
      Closing Positions
      $1,031,412.14 + ($587.97) = $1,030,824.17
      Unrealized PnL is calculated to be 1m across those two instruments for which positions are available. Upon forcing a closing of positions, the unrealized PnL of 1m does not collapse into a realized PnL of 1.6m as expected, instead, the unrealized PnL really should have been only 0.4m (this is correct according to strategy analyzer and summing the PnL of across all trades).

      To give you a good example of a sample strategy you could write that records this behaviour:
      - go short UNG and go long SPY shares of notional value equal to our starting capital
      - have something calculate total capital on every bar (daily) = realized + unrealized across both instruments
      - when the position size of either differs by 5% from our total capital, buy or sell shares to bring the position size back to total capital

      Comment


        #4
        Hello wuileng,

        I would not expect the realized pnl for a single strategy to match or even be similar to the accumulated unrealized pnl for all instruments on an account.

        Can you further detail why the pnl of closed trades made by one instance of a strategy would be a comparable value with the accumulated unrealized pnl of open trades for other instruments?
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          Of course it wouldn't, but that's not what we're comparing. We are merely making comparisons and adding up realized and unrealized PnL for instruments within the context of one strategy.

          Let me clarify further:
          Total PnL (within a strategy) = Realized PnL (for that strategy) + Unrealized PnL (for that strategy)

          Unrealized PnL (for a strategy trading two instruments) = Unrealized PnL for Instrument 1 (within that strategy) + Unrealized PnL for Instrument 2 (within that strategy)

          Therefore,
          Total PnL (within a strategy) = Realized PnL (for that strategy) + Unrealized PnL for Instrument 1 (within that strategy) + Unrealized PnL for Instrument 2 (within that strategy)

          So, you would expect that when you close all positions, that the sum of unrealized PnL gets added to the realized PnL right? Well this is not what is happening (see the differences between lines 2 and 3 below).

          Comment


            #6
            Hi wuileng,

            Thank you for clarifying this.

            Its possible that a snapshot of the unrealized pnl might be equal to the final realized pnl if the snapshot is taken close to the fill of the exit.
            In historical data, if this is being checked when the bar closes, the close of the previous bar would likely be used for getting the unrealized pnl snapshot, while the first tick of the new bar would be used for the order fill.

            Attached is an example simple script to demonstrate. This simply places two orders. The unrealized is checked as the bar closes. After the unrealized is checked the exit is called and the orders fill with a slightly different price:

            The output appears:
            3/2/2017 4:09:00 PM | ES 03-17 | BIP: 0 | Unrealized: -12.5 | Close: 2379.75
            3/2/2017 4:09:00 PM | NQ 03-17 | BIP: 1 | Unrealized: -25 | Close: 5359.25
            3/2/2017 4:10:00 PM | instrument='ES 03-17' entryPrice=2380 exitPrice=2379.5 quantity=1 marketPosition=Long entryTime='3/2/2017 4:03:00 PM' entryTime='3/2/2017 4:10:00 PM' profitCurrency=-25
            3/2/2017 4:10:00 PM | instrument='NQ 03-17' entryPrice=5360.5 exitPrice=5359.25 quantity=1 marketPosition=Long entryTime='3/2/2017 4:03:00 PM' entryTime='3/2/2017 4:10:00 PM' profitCurrency=-25
            SystemPerformance.AllTrades.TradesPerformance.Curr ency.CumProfit: -50
            The close of the bar that triggered the exit of the NQ matches the actual fill price of the exit order. (Meaning the close of the 4:09 bar matches the open of the 4:10 bar)

            The close of the bar that triggered the exit of the ES does not match the fill price of the exit. (Meaning the last tick of the 4:09 bar at 2379.75 does not match the open price of the 4:10 bar at 2379.5. The price dropped one tick between the time the unrealized was checked as the exit was submitted and when the order filled.)

            Accumulating the unrealized pnl would result in -37.5 While the final result would be -50.

            In realtime, this would be a matter of order of operations. The unrealized must be checked before the position is closed. In the time between the unrealized being checked and the exit fill there could be a change in price.
            3/8/2017 2:46:20 PM | ES 03-17 | BIP: 0 | Unrealized: 0 | Close: 2363.25
            3/8/2017 2:46:40 PM | GC 04-17 | BIP: 1 | Unrealized: -20.0000000000045 | Close: 1207.1
            3/8/2017 2:46:20 PM | instrument='ES 03-17' entryPrice=2363.25 exitPrice=2363 quantity=1 marketPosition=Long entryTime='3/8/2017 2:45:34 PM' entryTime='3/8/2017 2:46:20 PM' profitCurrency=-12.5
            3/8/2017 2:46:42 PM | instrument='GC 04-17' entryPrice=1207.3 exitPrice=1207 quantity=1 marketPosition=Long entryTime='3/8/2017 2:45:34 PM' entryTime='3/8/2017 2:46:42 PM' profitCurrency=-29.9999999999955
            SystemPerformance.AllTrades.TradesPerformance.Curr ency.CumProfit: -42.4999999999955
            Here, the both the ES and GC changed price in real-time in between the time the unrealized was checked and the exit triggered and the actual fill of the exit.

            Can you demonstrate that after the unrealized pnl is checked while the position is still open that close price supplied to the .GetUnrealizedProfitLoss() method matches the execution price of the exit order? (Meaning after the unrealized was checked the price never changed before the order filled?)
            If the supplied price to .GetUnrealizedProfitLoss() matches the exit price of the trade, I would expect any accumulated unrealized pnl to match the SystemPerformance CumProfit.
            Attached Files
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              From my understanding there would be a minor difference between the price given (Closes[i][0]) and the actual realized price at which the position closes.

              However I'd expect that to be roughly a bar's difference. As you can see from the magnitudes in my example though, it seems like this is way too big a difference which is why I think it is a bug.

              Comment


                #8
                Hello wuileng,

                "Under the hood" in NinjaTrader, we use data given to us by your data feed provider whenever possible. Due to this, we will need a little more information from you. Could you let us know who your data feed provider is? Could you also let us know if you are using a risk template, which risk template you are using, and if you are using a risk template, what its specifications are, possibly with a screen shot?

                Please note that there were also some intentional decisions regarding unrealized profit and loss with regard to commissions, which could cause some differences between NT7 and NT8. Based on the answers to your questions I may be able to provide more information on this front.

                I look forward to assisting further.
                Jessica P.NinjaTrader Customer Service

                Comment


                  #9
                  Hi,

                  I have encountered these problems while trading equities, for which I am using Barchart as my data provider (split + dividend adjusted). Since the data from Barchart is already adjusted, the adjust for splits/dividends settings are turned off.

                  When I modify the time of forced position flattening, the error remains, which suggests to me that it's not a problem with the data, but rather the calculation process behind the scenes.

                  I am not using a risk template, or at least the equities I am trading do not have a profile (see attached screenshot). If you look at the magnitude of the P&L and errors, it also seems like it's not something to do with commissions.
                  Attached Files

                  Comment


                    #10
                    Thanks for this information. It looks like just one more piece of information would give us a complete picture as far as what is happening. Can you right-click your account and select "edit account", and send a picture similar to what I am sending your way with your account settings?

                    Since this may contain personally identifying information, please send to platformsupport[at]ninjatrader[dot]com referencing 1671081 and Attn:NinjaTrader_JessicaP in the subject line
                    Attached Files
                    Jessica P.NinjaTrader Customer Service

                    Comment


                      #11
                      Hello again wuileng,

                      I appreciate your patience. I have been creating a tool which will allow us to test our core calculations, and will enable us to better answer your question.
                      Jessica P.NinjaTrader Customer Service

                      Comment


                        #12
                        Hello again wuileng,

                        I was unable, after extensively reviewing how both strategy and account data are calculated, to discover any discrepancies between Position.AveragePrice for a given strategy, and its impact on your account.

                        I would like to recommend, therefore, both checking your AccountItem object associated with your account, and subscribing to AccountItemUpdate and AccountStatusUpdate. This will let you see exactly how your orders have been filled, using information provided to you from the trade desk. You will then be able to check your strategy's logic against this information.

                        You can use this code to get a reference to your account object. Replace "sim101" by your account's name.

                        Code:
                        [FONT=Courier New]
                                /// <summary>
                                /// http://ninjatrader.com/support/helpGuides/nt8/en-us/account_class.htm
                                /// </summary>
                                /// <returns>the Sim101 account or null on error</returns>
                                private static Account Sim101()
                                {
                                    if (null == _Sim101)
                                    {
                                        lock(Account.All);
                                        {
                                            _Sim101 = Account.All.FirstOrDefault(a => a.Name == "Sim101");
                                        }
                                    }
                                    return _Sim101;
                                }
                                private static Account _Sim101;[/FONT]
                        Please let us know if there are any other ways we can help.
                        Jessica P.NinjaTrader Customer Service

                        Comment


                          #13
                          Hi,

                          Could you please send me the strategy that you used and perhaps I can modify it into something else which might reproduce this problem?

                          Btw, these errors I have encountered were all in backtesting.

                          Comment


                            #14
                            I will be happy to and I appreciate your offer. I am reviewing this strategy and removing any proprietary information. I will return shortly with a stripped down copy.
                            Jessica P.NinjaTrader Customer Service

                            Comment


                              #15
                              All proprietary self-checks to make sure the event handlers used by this script are returning data consistent with other core calculations have been removed from the returned test script. Information from all three event handlers was tested against realized PnL every time any trade in any strategy was realized. Thank you again for your report and continued assistance. This help guide page will give the best overview as to what information this script exposes.



                              To clarify the purpose of this add-on, whenever a realized trade is made, in any strategy, it will be made immediately available via the account's Executions member (which should be locked before reading), and its ExecutionUpdate handler. In your strategy, all you will then need to do to detect a discrepancy that can not be accounted for due to slippage is to implement an OnOrderUpdate method in your strategy which prints time and price information, set up your OnBarUpdate to print up time and price information for trades away from the current price, and then use the tool I provided to give you a clear view from the account side of all the activity going into and out of the trade desk.
                              Attached Files
                              Last edited by NinjaTrader_JessicaP; 03-30-2017, 10:16 AM.
                              Jessica P.NinjaTrader Customer Service

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by DJ888, 04-16-2024, 06:09 PM
                              4 responses
                              12 views
                              0 likes
                              Last Post DJ888
                              by DJ888
                               
                              Started by terofs, Today, 04:18 PM
                              0 responses
                              7 views
                              0 likes
                              Last Post terofs
                              by terofs
                               
                              Started by nandhumca, Today, 03:41 PM
                              0 responses
                              6 views
                              0 likes
                              Last Post nandhumca  
                              Started by The_Sec, Today, 03:37 PM
                              0 responses
                              3 views
                              0 likes
                              Last Post The_Sec
                              by The_Sec
                               
                              Started by GwFutures1988, Today, 02:48 PM
                              1 response
                              9 views
                              0 likes
                              Last Post NinjaTrader_Clayton  
                              Working...
                              X