If you are using any of these coding queries in your indicators, your indicators are displaying bad data!!!
Here are a few examples of what is going wrong:
When several ticks arrive at the same time, NT tends to assign all of those trades the same volume even though the trades all had different volumes.
Also, When the market trends strongly in one direction, the bid and ask prices offered fall behind the live market. This
results in last trades for both the bid and the ask, to be tallied, either, all for the bid, or all for the ask.
This really screws up stuff like volume delta calculations!!!!
This problem is persistent in both NT 6.5 and NT7.
The workaround for this problem is to create your own temporary store values from e.Volume and e.Price.
Below are the lines of code that I now use in my indicators.
Favorite Futures: Gameplay KlownbineŽ Trading of Globex
Posts: 1,276 since Jul 2009
Thanks: 1,227 given,
OnMarketData Method and Gom Volume Ladder
The Gom Volume Ladder depends on bid ask data from the GomRecorderIndicator, which is in turn processed by and passed through the GomDeltaIndicator.
I believe that the code in the OnMarketData method of the GomRecorderIndicator is correct. It agrees with sample code that was posted a couple of years ago in the Ninjatrader forums.
If the e.MarketDataType is is e.MarketDataType.Bid, it stores the price associated with that event as the most recent bid price.
If the e.MarketDataType is MarketDataType.Ask, it stores the price associated with that event as the most recent ask price.
If the e.MarketDataType is MarketDataType.Last, that event means an actual trade has occurred. The price and volume associated with that event are the price and volume of the trade. The price of the trade is compared to the most recent bid and ask prices from the MarketDataType.Bid and MarketDataType.Ask events, to see whether the trade occurred AtAsk, AboveAsk, AtBid, BelowBid, or BetweenBidAsk (these are the strings values associated with the tickType Enum.)
Please let me know if anyone can see any problems with this. It looks fine to me.
The following 4 users say Thank You to Zondor for this post:
However, The ladder does use FirstTickOf Bar in its code. This means it suffers from the FirstTickOf Bar bug in NT7.When the volume ladder is building live on the chart, it is dropping the first tick of every bar.
When you refresh the chart, it will refresh with the correct data from all the ticks.
NT6.5 should be working just fine.
The following 4 users say Thank You to RJay for this post:
1. What exactly is the FirstTickOfBar bug which you are referring to? Is it perhaps the issue that the OnMarketData() call back occurs before the OnBarUpdate() (with FirstTickOfBar == true) occurs if the tick results in the end of the current bar?
If that is indeed the case, I prefer this approach since your code gets the tick prior to all the processing associated with OnBarUpdate for the tick which results in a new bar. When an old bar ends and new bar starts, NT has to do book-keeping for closing the previous bar and creating the new bar. I would prefer if my strategy gets that tick sooner than later.
Ideally, NT could first do a quick check to see if the tick results in a new bar and then set the field accordingly. That brings up a new question:
If you have multiple bars for the same instrument in your indicator, does the OnMarketData() trigger multiple times for each Bar or does it trigger only once for each instrument.
2. Regarding the bad values in the OnMarketData:
I think they use a single structure to store values for all the different tick types but only update the one corresponding to the current tick type. This makes sense from an performance point of view. All they do is set the type and the respective fields and reuse the same-structure instead of resetting it or setting it for the latest value for the other fields. Think if it as getting data tick by tick. When you get a Last Tick (trade), you should not be looking at the fields associated with the Bid/Ask.
The following 2 users say Thank You to aviat72 for this post:
I think the conversation confirms what I wrote in the previous post. The FirstTickOfBar is only valid in the context of OnBarUpdate().
It is not valid on the OnMarketData event. Making it valid would require NT to pre-process the tick and then establish a new bar is being formed prior to sending the OnMarketData event. This requires more computation and would delay the OnMarketData event.
NT is prioritizing the OnMarketData event over OnBarUpdate. They could split the processing of OnBarUpdate into parts; a pre-processing step which checks whether a new bar is being formed which is called prior to OnMarketData() and then the rest of the stuff which is done OnBarUpdate().
The point I was trying to make was that the fields which are valid is based on the context of the event type. If the event is of type last, then looking at bid info for that event is not valid. NT could return an exception saying that the field does not even exist; but that will add more code and will slowdown the system.
That is why GOM stores the price stores the last bid/ask locally based on the type of tick. Your expectation of the last bid/ask price and volume data being set correctly on a Last event is not consistent with the type of event OnMarketData() is designed for.
Think of it in terms of a tick stream. If you have a series which says: B,A,A,L,B,A then to check for the Bid fields on event 4 (L) is not valid. You need to check for the value passed on the last Bid event (event 1) which you should store locally.
Last edited by aviat72; October 17th, 2010 at 08:55 PM.