Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

OnMarketData vs. OnBarUpdate Price Level Question

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

    OnMarketData vs. OnBarUpdate Price Level Question

    Hi,

    I have been studying the price level changes between the various NT methods and I am hitting something that is not clear to me.

    I have a sample strategy enclosed along with an output in excel to illustrate my concerns / questions. What I am looking at is just the sequence of price level changes captured on the two event handlers OnBarUpdate, and OnMarketData. I am running this one a 1 tick time series at the most granular level possible. The sample was ran on the ES on April 16th during the first part of the US cash open. Considering that the data series is 1 tick, it doesn't matter if the OnBarUpdate calculates on every tick, or on bar close, as these two will be the same.

    I have studied the documentation and understand that OnBarUpdate front runs OnMarketData and will be 1 tick ahead in most cases. That's okay and I can work with this.

    What I am looking for is a single consistent method to use to capture the following:

    1. The fastest possible method to capture a price level change event: (Bid or Ask price moves up or down 1 tick)
    2. This method will capture EVERY price level change, and omit nothing.

    While I can tell that when the OnBarUpdate does run an update it will always front run the other methods, the issue is that it does not seem to capture every price level change.

    In the enclosed excel output consider the following:

    1. On Row 176 we can see that the OnBarUpdate method front runs the OnMarketData method and captures the price level change first. This is expected and makes sense.
    2. On row 605 the OnBarUpdate prices (Bid / Ask) do not change, yet the OnMarketData prices (Bid /Ask) hit a new price level. How is this possible considering that the OnBarUpdate event is suppose to run first?
    3. On row 992 the OnBarUpdate prices (Bid / Ask) do not change, yet the OnMarketData prices (Bid /Ask) hit a new price level. How is this possible considering that the OnBarUpdate event is suppose to run first?
    4. On row 1097 the OnBarUpdate prices (Bid / Ask) do not change, yet the OnMarketData prices (Bid /Ask) hit a new price level. How is this possible considering that the OnBarUpdate event is suppose to run first?

    So what is going on here? There are only 1 of 2 possibilities.

    1. The OnMarketData updates are capturing events that really occurred and the OnBarUpdate method is not able to see these price level change events. If this is the case, then this is a serious design flaw. How is this possible?

    2. The OnMarketData price level changes are not real, there is an error in the code somehow. Only the OnBarUpdate price level changes are real.


    Please investigate this and let me know what is going on here.

    Thanks,

    Ian
    Attached Files

    #2
    Hello iantg,

    Ticks are only produced for last events.

    May I confirm you are comparing last events in OnMarketData?

    Using an example script that prints the Time & Sales information, I am not able to find inconsistencies when comparing with last ticks appearing on a chart.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Hi Chelsea,

      Thanks for helping me with this.

      All I am trying to do is capture the most granular and fastest method possible to determine what the current price level is. My requirement is to be able to see EVERY price level change in real time. As you know, you can't submit limit orders below or above market prices depending on if you are buying the bid or selling the ask, so I need to know at all times what the current price level is.

      I understand that running:

      if( marketDataUpdate.MarketDataType == MarketDataType.Ask) will differ from
      if( marketDataUpdate.MarketDataType == MarketDataType.Last) for example in the mechanics of what information it is pulling. And that is okay, pulling from Last captures transacted volume from the past where as pulling Ask or Bid captures the resting volume at the current best bid / best ask price.

      I am comfortable with these differences and aware of this. The issue I have is that when I try to find a single source of truth to capture every price level change and get this information through the fastest method NT provides, I seem to have two choices.

      1. Use OnBarUpdate: This method will front run the other NT methods and typically be the fastest to see price level change events. However it appears that this method misses price level changes. (For example in the enclosed spreadsheet rows 605,992,1097 all had price level changes that occurred from OnMarketData but did not occur on OnBarUpdate.

      2. Use OnMarketData; This method seems to capture more price level changes (I am not sure if these are all real, or if there is a flaw in the data feed running
      if( marketDataUpdate.MarketDataType == MarketDataType.Ask) for example. But these update do often lag behind OnBarUpdate by as much as a few seconds which makes using this method not viable.

      Assuming that both of these feeds are accurate in their own way, I have to pick my poison between OnBarUpdate which is fastest (when it actually updates), and OnMarketData which captures more price level change events but can often times lag behind OnBarUpdate.

      So do you see the issue? I just want to validate that this:
      if( marketDataUpdate.MarketDataType == MarketDataType.Ask)
      is meant to capture the best ask price and applicable volume for example. If this assumption is correct, then how does this capture price level change events that the OnBarUpdate never seem to notice. (rows 605,992,1097 for example). The root of my question is really, what is going on here? Are the price levels picked up by OnMarketData real and OnBarUpdate is somehow missing them, or is this just a bug?

      Thanks,

      Ian

      Comment


        #4
        Hello iantg,

        Changes to the ask or bid may not cause a tick to be sent..

        So in this respect, its possible that OnBarUpdate will not match the ask and bid market updates. It should, however, match the last updates.

        MarketDataType.Ask will be the last change to the first row of ask data. (Meaning someone has placed an order that is working at that price but not filled (resting), an order was changed to this price but not filled (resting), or an order was filled at this price)

        MarketDataType.Last will be the last transaction (meaning an actual trade) that occurred at either the ask or the bid.

        It would be expected there would be more updates to the ask and bid than there are ticks at the last.

        I'm not able to reproduce any behavior where OnMarketData lags behind OnBarUpdate. These are run in the same thread and are not asynchronous. If something causes OnMarketData to stop updating, this would also cause OnBarUpdate to stop updating.

        May I confirm you have tested the script I have linked and you are finding the last ticks are not matching the prints from the indicator?
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          Hi Chelsea,

          Thank you for following up with me on this.

          I have reviewed the links you have provided and am familiar with these. They differ in what they are trying to do compared to my use case.

          Let's start with this point: "'I'm not able to reproduce any behavior where OnMarketData lags behind OnBarUpdate."

          I have built a test script you can run where you will see what I am referring to. I have enclosed it, along with the output this produces. To test this yourself, you just need to print this to the output window, copy and paste it into excel, then use / as the delimiter to split the data into multiple columns. The attached excel spreadsheet has the header column definitions.

          But here is what the code is doing. (It is very simple)
          In order to test this correctly you need to run this on a 1 tick data series.

          1. From the OnBarUpdate: It just prints 1 row on every tick. So every time a trade occurs it prints a row. The key fields here are the bid and ask prices

          2. From the OnMarketData: I am printing on the if (marketDataUpdate.MarketDataType == MarketDataType.Last ) definition and I have split this into logic for ask and bid. This is nothing more than the same code blocks provided by NinjaTrader on the documenation website with just a little bit of work to capture the variables in a readable format for excel.

          The issue I have is that every time the price level changes from the OnBarUpdate method, it takes the OnMarketData method several more updates to catch up and match the price level change. And for clarification I am not referring to GetCurrentBid() from OnMarketData to GetCurrentBid() from OnBarUpdate... I am referring to marketDataUpdate.Price (inside of logic pointing this to the Bid) from OnMarketData vs. GetCurrentBid() from OnBarUpdate for example. When one changes, I expect the other to change to the same value. These do not update in sync, and this is the key issue.

          You can see it clearly on rows 43, 175, and 433 where I highlighted this behavior. It technically happens almost every time, but I only highlighted the first few.

          So if these price level change events are suppose to occur at the same point in time between these 2 events they are not doing that.

          We can start with just this one item and go from here. But this is the starting point for my entire issue. I can't get a single version of the truth from NT that provides every update to the bid / ask price at the first possible moment available. It seems that OnMarketData using if (marketDataUpdate.MarketDataType == MarketDataType.Bid ) or if (marketDataUpdate.MarketDataType == MarketDataType.Ask ) captures price level changes that the OnBarUpdates don't even see..... But I can't just use OnMarketData only because when OnBarUpdate does update, it front runs the OnMarketData events by 1 to 5 seconds often times.... Which in my use case, makes it not possible to use because it is too slow.

          Start by reviewing the examples I have enclosed and let me know if this explains the first part of the issue.

          Thanks,

          Ian
          Attached Files
          Last edited by iantg; 05-14-2018, 12:53 PM.

          Comment


            #6
            Hello iantg,

            I'm still not quite understanding..

            Do you mean that OnBarUpdate will update multiple times before OnMarketData will update that price?

            Say OnBarUpdate updates the tick as 1000 and then 1000.25 and then 1000.50 and then 1000.75, before OnMarketData will update to 1000.25?

            What should I be looking at in the file you have provided?


            OnBarUpdate 4 16 2018 9:25:02 AM 9 25 2 769 2676 2676.25 147 69 1
            Bid Trans Update 4 16 2018 9:25:02 AM 9 25 2 769 2676 2676.25 147 69 1 2676.25 1 2676.5 0

            These appear to match.. As do all other places you have highlighted..

            What prices are different?
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Chelsea,

              If you look at the excel file I enclosed you can see the issue on the 3 highlighted rows I mentioned. Rows (43, 175, and 433).

              In each of these cases the OnBarUpdate methods: GetCurrentBid() and GetCurrentAsk() reach a new price level. But the OnMarketData bid and ask price from Column N and Column P respectively are still lagging and on the old price level.

              Take for example the first case, Row 43. On row 42 the GetCurrent Bid / Ask price level is at 2676.25 / 2676.5 and the OnMarketData prices (Columns N and P) are on the same price level 2676.25 / 2676.5. Then on Row 43 the OnBarUpdate methods GetCurrentBid() and GetCurrentAsk() reach a new price level 2676 / 2776.25 (Down 1 tick) at the same time this price level change occurs the OnMarketData method is still lagging at the old price level of 2676.25 / 2676.5. The OnMarketData method does not catch up and get on this price level until row 140. This comes at a time difference of nearly 2 seconds!

              Do you see what I am referring to now?

              Thanks,

              Ian

              Comment


                #8
                Again, ultimately what I am looking for is just one source of the truth in the data. For scalpers, HF traders, and most algo traders we have one overarching requirement from the data feed and that is to get the correct price level. This feed should have the following characteristics.

                1. If there are multiple feeds, we need the feed that identifies the price level change the fastest. In NT there are 3 feeds. (OnBarUpdate, OnMarketData and OnMarketDepth). Whichever of these feeds is the fastest to note a price level change is the one we need.
                2. This feed needs to capture every single price level change. It can't skip or miss price levels. This would be a disaster for algo's.

                So based on these 2 requirements I am trying figure out how best to use Ninjatrader. It seems that we have the following:

                1. Fastest to Update price levels: OnBarUpdate typically updates first. This can often update a few seconds ahead of OnMarketDepth and OnMarketData. Specifically I am comparing the bar methods of GetCurrentAsk() and GetCurrentBid() to the OnMarketDepth and OnMarketData methods of marketDepthUpdate.Price and marketDataUpdate.Price respectively.

                2. Feed that captures every price level change: It appears that OnMarketData captures more price level changes. If you run the OnMarketData feed like this:

                if( marketDataUpdate.MarketDataType == MarketDataType.Ask)

                and then print every update here: marketDataUpdate.Price
                you will find that compared to GetCurrentAsk(), this approach will capture 25% to 50% more price level events. I am not 100% sure if these are all real price levels or if there are bugs in how this feed is compiled. I need some clarification on this point. But if this feed does capture every real price level change and the GetCurrentAsk() method does not then we have an issue.

                From my research and the two sample strategies I have enclosed, it appears that the OnBarUpdate has to be used to capture price level changes the fastest but also OnMarketData has to be used to capture price level changes that are missed by OnBarUpdate. So there is no real solution for my requirement (The requirement for all scalpers, and algo traders) to capture every price level change event through the fastest possible method.

                It looks like I am going to have to hack together some custom logic to solve for this design flaw.... And I hope I am wrong, and I completely missed something.

                Please let me know if you are able to follow the issue I am describing.

                Thanks,

                Ian

                Comment


                  #9
                  Any Updates?

                  Does anyone from NT have any updates or thoughts on this?

                  I know these issues are not that straight forward, so if you need any clarification on anything let me know.

                  Ian

                  Comment


                    #10
                    Hello Ian,

                    I'm trying to reduce the information in your posts into a simple inquiry.

                    Are you reporting that the marketDataUpdate.Ask (from the OnMarketData argument) is not matching GetCurrentAsk() when also called from OnMarketData?

                    (This is without using OnBarUpdate at all)

                    I was able to reproduce this behavior and I am currently looking further into this.
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Hi Chelsea,

                      I can understand the fact that I am bringing up lots of different topics, and the NT team may need to research and solve for these one by one. So if you are already seeing the differences I found between marketDataUpdate.Ask and GetCurrentAsk() then I think this would be a great place to start.

                      I would expect that the price level should be in sync between bar events, market data events and market depth events. But from my research this is not the case. So this makes it hard to tell what price level we are on. Further, it makes it impossible to build strategies that take advantage of all 3 feeds... when they are all reporting differences in the price level, this makes using the 3 feeds together in any combination virtually worthless.

                      So as a starting point, if you could solve for just what causes the differences between the price level of the best bid / best ask between the OnMarketData feed between marketDataUpdate.Ask and GetCurrentAsk(). I know that the GetCurrent methods use the bar from the bar event even if it is not called from OnBarUpdate. But going with a 1 tick data series I would expect this to sync up since the MarketData feed is granular to each tick.

                      Thanks,

                      Ian
                      Last edited by iantg; 05-16-2018, 01:10 PM.

                      Comment


                        #12
                        Hello iantg,

                        Thank you for your response.

                        Our QA team put together the attached example script that shows that GetCurrentAsk() and thus GetCurrentBid() is pulled from the bars object where as marketDataUpdate.Ask and marketDataUpdate.Bid are ahead of the bars object.

                        Please let me know if you have any questions.
                        Attached Files

                        Comment


                          #13
                          Hi Patrick,

                          I appreciate the team at NT taking the time to look into this for me.

                          I ran the code that QA built as a strategy and printed the output. My settings are as follows:

                          Instrument = ES
                          Time Series = 1 Tick


                          Here are are my observations:

                          1. The print and sequence of the print statement from the OnBarUpdate front runs the OnMarketData price in all cases: For example this print will show like this:
                          | OBU | GetCurrentAsk: 2647 At the time this occurs, the last known print from OnMarketData will be still at the old price of 2676.75 and then at some point in the future it will catch up and then show | OMD | GetCurrentAsk: 2647. But in both of these cases we are comparing the same GetCurrentAsk call, with one coming inside of the OnBarUpdate subroutine and the other coming from the OnMarketData subroutine.
                          I don't think this really matters as much as this is behavior that we can expect. The price will change first from inside the OnBarUpdate sub since this is the sub that is related to the GetCurrent methods in the first place. No real issues here, but I just thought I would point out that OnBarUpdate does run this first not second.

                          2. The real issue that we haven't addressed yet, is why the Ask price that comes from the OnMarketData via | OMD | marketUpdateAsk: is often lagging the GetCurrentAsk price. In virtually every case (Each Price level) the following events play out. First the Price level changes and the GetCurrentAsk moves up or down by one tick, when the price changes, we do not see any change to the price from the OnMarketData via | OMD | marketUpdateAsk: instead this is stuck lagging at the old price. It takes around 25% to 50% of the lifecycle of the price level before this | OMD | marketUpdateAsk: finally catches up and moves to the same price. So consider this issue # 1 that we need to solve for and understand.

                          3. There are times where all 3 of these can be out of sync: For example on the ES using a 1 tick time series I sampled the code and found this print that illustrates the issues:

                          5/26/2018 12:12:43 AM | OMD | GetCurrentAsk: 2646.25
                          5/26/2018 12:12:43 AM | OMD | marketUpdateAsk: 2646.75
                          --------------------------------------------------------------------------------
                          Updating bid to 2646.25
                          Updating ask to 2646.5

                          Here we have a .25, 5. and .75 Price point for the Ask. So which one is right in this case? Why do we have 3 versions of the truth? Run the code enclosed on this date in the ES and you will see the issue right here.

                          4. There are price levels from the OnMarketData call OMD | marketUpdateAsk: that just oscillate between 2 prices: Like thisL

                          2646.25
                          2646.5
                          2646.25
                          2646.5
                          2646.25

                          All the while the GetCurrentAsk price shows an unabridged price of 2646.25. So which of these are real and which one is a bug? Either the price level is changing and the GetCurrentAsk is not seeing all the changes, or the data feed from marketUpdateAsk has a bug and is just throwing some sort of error. I believe after testing, the error is with the OnMarketData method and the GetCurrentAsk method is correct.


                          Take a look at these points and let me know if you can see what I am referring to or not. I will be glad to share some more details / examples, but this is a real issue.

                          Thanks,

                          Ian
                          Attached Files

                          Comment


                            #14
                            In Addition to the OnMarketData Last feed being out of sync with the GetCurrentBid() and GetCurrentAsk() methods from OnBarUpdate, the OnMarketData Ask and Bid feeds are off further.

                            So for clarification: (These values for the variables transbid and transask that represent the transaction prices, do not sync up to the GetCurrentBid() and GetCurrentAsk() prices at all.


                            if (marketDataUpdate.MarketDataType == MarketDataType.Last )

                            {

                            if (marketDataUpdate.Price <= marketDataUpdate.Bid)
                            {
                            transbid = marketDataUpdate.Price;

                            }

                            if (marketDataUpdate.Price >= marketDataUpdate.Ask)
                            {
                            transask = marketDataUpdate.Price;

                            }

                            }

                            Now further to my next query regarding data being out of sync. When I run the OnMarketData feed for the Bid and Ask like this:

                            if( marketDataUpdate.MarketDataType == MarketDataType.Ask)
                            if( marketDataUpdate.MarketDataType == MarketDataType.Bid)

                            .......And assign variables to hold marketDataUpdate.Price under these conditions, these prices are out of sync further still. To give you an idea. I ran all of these feeds wide open over 300 price levels then de-duped to get unique prices just so you can see how out of sync these three feeds are. Enclosed is the output in excel. I will be glad to share the code to produce this.

                            But the questions is still the same. Which version of these three feeds is the truth and which ones are lagging, or off due to bugs. I suspect that some of the transaction data feed from MarketDataType.Last can be lagging due to the nature of transactions being reported after the price level has changed. So this explains some of it. But there are cases where this feed hits prices that never existed from the GetCurrent methods. And if some of this is strictly due to just lag / latency, then this still doesn't explain how it would oscillate between two prices like this.

                            2000
                            2000.25
                            2000
                            2000.25

                            Once the price level changes, we should not see any updates from prior price levels still showing up. So the obvious explanation of lag due to prices still updated from the former price level doesn't fully explain this.

                            For the MarketDataType.Bid and MarketDataType.Ask prices, these should be the level 1 best bid and best ask prices and applicable resting volumes. These often hit price levels that never exist in the GetCurrentBid / GetCurrentAsk methods. So it almost looks like in some cases these are actually front running the GetCurrentBid / GetCurrentAsk methods. But in other cases it seems obvious that these are lagging. So I am not sure what the data structure relationship is here. But I would like some clarification on this.

                            I think there are some bugs here for sure, but I would also just like to understand what the sequential order, and purpose of each of these 3 feeds is suppose to be from a design perspective.

                            I hate to beat you guys up on this, but you can see the obvious issues here hopefully.

                            Thanks!

                            Ian
                            Attached Files
                            Last edited by iantg; 05-30-2018, 01:31 PM.

                            Comment


                              #15
                              Hello iantg,

                              Thank you for your update.

                              I have brought this item back up with our QA team. I will follow up here when I have any additional details.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by warreng86, 11-10-2020, 02:04 PM
                              7 responses
                              1,360 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Started by Perr0Grande, Today, 08:16 PM
                              0 responses
                              5 views
                              0 likes
                              Last Post Perr0Grande  
                              Started by elderan, Today, 08:03 PM
                              0 responses
                              9 views
                              0 likes
                              Last Post elderan
                              by elderan
                               
                              Started by algospoke, Today, 06:40 PM
                              0 responses
                              10 views
                              0 likes
                              Last Post algospoke  
                              Started by maybeimnotrader, Today, 05:46 PM
                              0 responses
                              14 views
                              0 likes
                              Last Post maybeimnotrader  
                              Working...
                              X