Good news — I finally got my custom plugin that I’ve been working on for a while to run almost flawlessly. However, I’ve run into one last issue that I can’t seem to figure out.
I have a built-in monitoring and alert system that relies on Time & Sales data. The problem is that when I activate it and set a threshold, it keeps triggering orders repeatedly — far more often than it should.
To troubleshoot, I created a custom debugger that writes all the Time & Sales events to a local text file. After reviewing the output and comparing it to NinjaTrader’s own Time & Sales window, I noticed multiple duplicates being reported. It looks like the same prints are being processed more than once.
My suspicion is that it has something to do with the OnMarketData() function — maybe NinjaTrader is sending data twice, or my script is picking up both bid/ask updates and trades simultaneously. I’ve been trying to fix this for days without luck, so any guidance would be greatly appreciated.
Thanks in advance for your help!
My custom Chart Trader — built it from scratch and finally running smooth (well, almost ).
By any chance do you have a secondary data series in your script? That could be the reason for the duplication. I recall dealing with a similar issue quite a while ago but don’t recall all the details unfortunately.
OnMarketData() documentation says the following:
The OnMarketData() method is expected to be called after OnBarUpdate()
If you create a secondary data series using AddDataSeries, I believe each time OnBarUpdate is called, OnMarketData will get called, therefore, once for BarsInProgress=0 and once for BIP=1.
So the simple fix is to only process OnMarketData once when BarsInProgress is 0. I checked through my various scripts that use OnMarketData and I have the following in all of them.
Thanks. I’ll check it out. I’m pretty sure I don’t have two subscriptions, that thought crossed my mind, but I’ll look into what you’re saying. I actually fixed the issue, but it was really a workaround because it was sending me double trades and double the volume. I just made a script that, once the data came in, divided it by two, and when I did that, I got the answer I was looking for. Unfortunately, this is a workaround and not how it’s supposed to work. So, even though it worked, if I build on this, it could potentially mess things up even more later. So, I’ll definitely look into this, and I really appreciate your response. Thanks.
The BarsInProgress concept applies to Strategies and Indicators, not Add-Ons. My code uses the Add-On pattern:
instrument.MarketData.Update += OnMarketDataUpdate;
MarketDataEventArgs has no equivalent to BarsInProgress - it only has:
Time, Price, Volume, MarketDataType, Bid, Ask, Instrument, IsReset
No sequence number, no thread ID, no BarsInProgress equivalent.
Most likely it’s a coding error, and without seeing the code it’s hard to guess the exact cause. Here are several points to pay attention to:
Inside OnMarketData, make sure you’re only processing updates for the Last price.
As @fc77 already mentioned, make sure you don’t have additional DataSeries, even if they’re for the same instrument — OnMarketData will be triggered for each one.
If you’re using the OnOrderUpdate event (or a similar one) to confirm the order submission, it’s possible that more OnMarketData events will arrive before the OnOrderUpdate confirmation, which could cause multiple submissions.
When you close the Add-On, make sure to properly dispose of all resources — especially to unsubscribe from OnMarketData.
Thank you for the reply, but I kind of figured out what it was. It has something to do with NinjaTrader, and add-ons. Market data doesn’t properly send information to add-ons. I had to create an indicator and then use “bar on close” or “close on bar” information, and that fixed the issue. It’s a little bit of extra work, but it worked, and now I’m properly getting information to report. Although I did want the add-on to do all of the work, which would have been amazing, add-ons can’t write to NinjaTrader’s chart; only indicators can. So I had to pretty much create an indicator anyway.