Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Multi Series Strategy accessing Unrealized PnL

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

    Multi Series Strategy accessing Unrealized PnL

    Hi -
    I have a multi series Strategy that trades the 5 main equity e-mini equity indexes. Each have their own Data Series. I am trying to code a Risk Management implementation that requires to know the Unrealized PnL of all 5 collectively. I don’t care about the individual PnL of each series, I want to know the collective PnL of all 5.

    I tried to call each Position's GetUnrealizedProfitLoss method in the same BarsInProgress but only one of the series had a valid PnL amount. I need to collectively gather this information to make Risk Management decisions for the Strategy as a whole.

    - I need to access the collective PnL in my historical testing, since it is part of my Risk Management and this needs to be backtested.

    - I need to manage the PnL as a whole during historical and real time in a single BarsInProgress.

    Any best practice how to do this?
    Last edited by szayedoud; 04-03-2020, 12:38 PM.

    #2
    Hello szayedoud,

    Thanks for your question.

    You would need to sum Positions[BarsInProgress Index].GetUnrealizedProfitLoss() and supply the current market price from each instrument to total the unrealized PnL for open positions on those trades. There would not a single object to check that tracks all of the strategies Unrealized PnL for all positions.

    You could use Closes[BarsInProgress Index][0] to references the current close of that that particular instrument. How often Close/Closes updates will depend on the Calculate Mode, and please also note that backtesting does not process OnEachTick or OnPriceChange unless Tick Replay is used. You could add a single tick data series for each instrument and check the Closes series for the single tick data series as an alternative to using Tick Replay and a different calculate mode.

    RealizedPnL from the strategy can be found using SystemPerformance.

    SystemPerformance - https://ninjatrader.com/support/help...erformance.htm

    In case you need further reference for Multi Time Frame scripts, I have linked the documentation here - https://ninjatrader.com/support/help...nstruments.htm

    I look forward to assisting.
    JimNinjaTrader Customer Service

    Comment


      #3
      Hi - thanks for your direction, that worked fairly well, but now I get more occurrences of a problem I would occasionally get during my backtesting. This is the issue:

      Like I said prior, I use the 5 main equity indexes (ES, NQ, YM, EMD and RTY). The EMD is problematic in that it has the lowest volume and occasionally I run into a gap in my 1 minute historical data series where no transaction took place in that minute. When this happens in my backtesting, I just copy/paste the previous minute entry (in the Historical Data window) to where the gap occurred. The actual value is less important - what is more important is that the test has the appropriate timing, and continuity.

      Now that I need to aggregate each Positions[BarsInProgress] Unrealized PnL EACH MINUTE, I run into more gaps in the EMD minute series and that throws off the calculation, and the strategy goes in a bad state.

      - Is there a way I can programmatically recognize when a gap occurs (when that BarsInProgress will not occur that minute) so I can workaround it? If I can tell when this occurs, I can use the previous minute value.

      - Is there a quick and easy way to fill in all gaps in my Historical Data database, with the previous minute? In prior situations, I’d fill in the gap manually, but this occurred every blue moon since I didn’t process EMD info every minute.

      Thanks for your help in advance!

      -Sam

      Comment


        #4
        Hello Sam,

        Thanks for your reply.

        The strategy will fill orders using the data series that the order is submitted to, and we can't really change that.

        You could consider to maintain your approach to inject historical data to fill a gap. I may suggest to use another script to compare data between these data series, and where a gap is found, you could copy previous data as you need. After you compare the data and add any needed historical data, you could run your backtest and the orders will be filled with the data you copied in.

        We look forward to assisting.
        JimNinjaTrader Customer Service

        Comment


          #5
          Ok, that sounds reasonable. Now - is there a way in the NinjaScript API I can easily access the Historical Data? Or, do I have to 1. Manually Export each contract (e.g EMD 06-20, EMD 03-20, etc) from the Historical Data window. 2. Use a script to manipulate the files and fill the gaps . 3. Import those newly modified files back in Historical Data. Is the best way to do it?

          Also - once I import the new data, will it get overwritten if I ever "Reload Historical Data" ?

          Thanks,
          Sam

          Comment


            #6
            Hello Sam,

            There isn't a supported way to manipulate the historical data on the platform through NinjaScript, but you could consider having your "Data Filling" script output a text file complying with our documented formats so you just have to import the data file to fill the gaps.

            Formats - https://ninjatrader.com/support/help...AndDataFormats

            StreamWriter example - https://ninjatrader.com/support/help...o_write_to.htm

            If you selected Reload All Historical data, the data would be replaced, so you would have to run your "Data Filling" script again and import the synthetic data.

            We look forward to assisting.
            JimNinjaTrader Customer Service

            Comment


              #7
              Hi - I have since fixed the gaps in my Historical Data, but I still can't get a cumulative Unrealized PnL that is accurate and consistent with what is displayed in the Control Center Accounts and Positions tab. In historical, I am adding the PnL from Positions, but in Realtime, I am using PositonsAccount. I can't find a good way to add the 5 1 minute series Positions when I can't predict their OnBarUpdate methods. I tried using a counter, but if there is no tick for that minute, that throws off the counter.

              How do I accurately accrue Unrealized PNL in a mutli series strategy each minute - even when there is no tick for that minute for a series? The Control Center - Accounts and Positions tab seems to be accurate. How does it do it?

              Comment


                #8
                Hello Sam,

                The Accounts tab fetches information from your broker. For Sim accounts, this is generated locally.

                OnBarUpdate is event based. If there is no incoming data, OnBarUpdate will not be processed.

                Adding a 1 minute data series for each script will be needed, and then you will need to reference Closes[BarsInProgress Index][0] with PositionsAccount.GetUnRealizedProfitLoss().

                The code below will check UnRealized PnL for each instrument and add them to AcountItem.CashValue. Since the added data series are 1 minute data series, the prices that are used will be the close prices for 1 the most recent 1 minute bar.

                Code:
                    else if (State == State.Configure)
                    {
                        AddDataSeries("ES 06-20", Data.BarsPeriodType.Minute, 1, Data.MarketDataType.Last);
                        AddDataSeries("CL 05-20", Data.BarsPeriodType.Minute, 1, Data.MarketDataType.Last);
                    }
                }
                
                protected override void OnBarUpdate()
                {
                    if (State == State.Historical) return;
                
                    if (BarsInProgress != 0)
                        return;
                
                    if (CurrentBars[0] < 1 || CurrentBars[1] < 1 || CurrentBars[2] < 1)
                        return;
                
                    Print(Account.Get(AccountItem.CashValue, Currency.UsDollar) + PositionsAccount[1].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[1][0]) + PositionsAccount[2].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[2][0]));
                }
                If you would like to have this updated with more recent data so it is inline with the Positions/Strategies tab, I may suggest checking this in OnMarketData which will update with each tick. For example:

                Code:
                private double esTemp, clTemp;
                
                protected override void OnMarketData(MarketDataEventArgs marketDataUpdate)
                {
                    if (BarsInProgress == 1 && marketDataUpdate.MarketDataType == MarketDataType.Last)
                    {
                        esTemp = PositionsAccount[1].GetUnrealizedProfitLoss(PerformanceUnit.Currency, marketDataUpdate.Price);
                        Print(Account.Get(AccountItem.CashValue, Currency.UsDollar) + esTemp + clTemp);
                    }
                
                    if (BarsInProgress == 2 && marketDataUpdate.MarketDataType == MarketDataType.Last)
                    {
                        clTemp = PositionsAccount[2].GetUnrealizedProfitLoss(PerformanceUnit.Currency, marketDataUpdate.Price);
                        Print(Account.Get(AccountItem.CashValue, Currency.UsDollar) + esTemp + clTemp);
                    }
                }
                I look forward to assisting.
                JimNinjaTrader Customer Service

                Comment


                  #9
                  Thanks for your feedback. I have some questions:

                  - You said "Adding a 1 minute data series for each script will be needed, and then you will need to reference Closes[BarsInProgress Index][0] with PositionsAccount.GetUnRealizedProfitLoss()." what do you mean by "adding a 1 minute data series for each script? I have a 1 mutli series script, with 5 1 min series (ES, NQ, YM, EMD, RTY).

                  - You said “Since the added data series are 1 minute data series, the prices that are used will be the close prices for 1 the most recent 1 minute bar.” So anytime you use the [0] index (like on Closes in this case) you’re getting the last OnBarUpdate for that series ? I kinda assumed this, but I want to make sure.

                  - Why are you adding the Unrealized PnL to the Account Cash Value? I am after just the Unrealized PnL. Please explain..

                  Thanks again!

                  Comment


                    #10
                    Hello Sam,


                    - You said "Adding a 1 minute data series for each script will be needed, and then you will need to reference Closes[BarsInProgress Index][0] with PositionsAccount.GetUnRealizedProfitLoss()." what do you mean by "adding a 1 minute data series for each script? I have a 1 mutli series script, with 5 1 min series (ES, NQ, YM, EMD, RTY).
                    You need to add a data series to reference external data. Once the data series is added, it would be referenced with Closes. You should use PositionsAccount[1].GetUnrealizedProfitLoss(PerformanceUnit.Currency, Closes[1][0]) to get the the unrealized PnL for the first added data series. If this is a 1 minute series, the Price Series will be up to date with each minute.

                    Keep in mind, there is no guarantee that data series 1 will close a minute bar before data series 2. This goes into your next question.

                    - You said “Since the added data series are 1 minute data series, the prices that are used will be the close prices for 1 the most recent 1 minute bar.” So anytime you use the [0] index (like on Closes in this case) you’re getting the last OnBarUpdate for that series ? I kinda assumed this, but I want to make sure.
                    Yes.

                    - Why are you adding the Unrealized PnL to the Account Cash Value? I am after just the Unrealized PnL. Please explain..
                    It is just an example to demonstrate getting the unrealized PnL values. You are free to do what you like for your needs.

                    We look forward to assisting.
                    JimNinjaTrader Customer Service

                    Comment


                      #11
                      Thanks for the feedback, I will play around with this tonight.

                      Comment


                        #12
                        Hi again - above you wrote "The Accounts tab fetches information from your broker. For Sim accounts, this is generated locally." is there anyway to access the Control Center Accounts "Unrealized PnL" through the NinaScript API directly? I tried overriding OnMarketData method, and I get varied results - sometimes within an acceptable variance and sometimes not.

                        Comment


                          #13
                          Hello Sam,

                          Information from the Accounts tab of the Control Center can be fetched with Account.Get. This may not be available for all connection technologies, however. Please see the Accounts tab documentation for which columns are supported by each connection technology.

                          Account.Get - https://ninjatrader.com/support/helpGuides/nt8/?get.htm

                          AccountItems - https://ninjatrader.com/support/help...ccountitem.htm

                          Accounts tab (See "Account Values Supported by Provider") - https://ninjatrader.com/support/help...TheAccountsTab

                          As for checking in OnMarketData, I have not had any issue testing with what is provided in post #8. You do not have to include the CashValue or math and simply print clTemp or esTemp to observe UnrealizedPnL update for those added instruments.

                          We look forward to assisting.
                          JimNinjaTrader Customer Service

                          Comment

                          Latest Posts

                          Collapse

                          Topics Statistics Last Post
                          Started by Perr0Grande, Yesterday, 08:16 PM
                          1 response
                          7 views
                          0 likes
                          Last Post NinjaTrader_Jesse  
                          Started by f.saeidi, Yesterday, 08:12 AM
                          3 responses
                          24 views
                          0 likes
                          Last Post NinjaTrader_Jesse  
                          Started by algospoke, Yesterday, 06:40 PM
                          1 response
                          14 views
                          0 likes
                          Last Post NinjaTrader_Jesse  
                          Started by quantismo, Yesterday, 05:13 PM
                          1 response
                          13 views
                          0 likes
                          Last Post NinjaTrader_Gaby  
                          Started by The_Sec, 04-16-2024, 02:29 PM
                          3 responses
                          16 views
                          0 likes
                          Last Post NinjaTrader_ChristopherS  
                          Working...
                          X