I’ve been working on a high frequency trading system for NinjaTrader on behalf of a long term client. My live account is with MB Trading. Rather than placing market orders and paying a commission, I changed the order types to limit orders. We want to receive a small commission for the market making strategy rather than paying a commission to accept the displayed prices.
MetaTrader suffers two major disadvantages that make NinjaTrader a superior option for high-frequency trading. MT4 does not offer charts lower than the M1 time frame and the trade context is busy error prevents multiple charts from running simultaneously. NinjaTrader is complex enough to where I can control most details, but simple enough that I don’t need to invest hundreds of hours to test an idea. After extensively testing the strategy on M1 charts as a price taker, I feel very confident that the strategy is sound. The only issue now is determining whether or not whether taking a passive (i.e., market making) approach will result in enough fills to make the strategy worthwhile.
The first issue that I came across wasn’t with NinjaTrader; it was with MB Trading’s API. The strategy worked fine on the simulation account, which only routes orders to NinjaTrader (NT). NT then makes guesses when fills would occur. The goal of that phase was not to test the strategy. I only wanted to test the programming to make sure that it worked properly.
100 trades went off without a hitch in the Sim account. The strategy only made it through 2-3 microlot trades on the live account before the pending orders hung. NinjaTrader pending orders pass through 3 states before they actually hit the market. For the programmers out there, these are the OrderState properties of IOrder objects.
- Pending submit – the strategy sent the order to the broker and is waiting to hear back
- Accepted – the broker acknowledges receipt of the order, but is still placing the order into the market
- Working – the order is available for others to trade
The strategy updated orders on every tick. What often happened was that the pace would go far too quickly, creating a major communications backlog during fast markets. NinjaTrader never threw an exception. The only evidence of a problem was that I would see a hanging order with the PendingChange property. The inconvenient solution was to exit NinjaTrader and reload everything.
I figured that perhaps that the managed order state caused the issue. I changed my approach to unmanaged orders, but that did not make a difference. I eventually came to the realization that the MB Trading API cannot handle more than one order every few seconds.
The strategy found the sweet spot after changing from tick to second charts. Updates of 6 seconds or longer seem to give the MB Trading API enough time to update wihle still preserving something of a high frequency approach. Any trades that need to run faster than that threshold at MB Trading need to use the FIX protocol.
The other element that drove me crazy is that NinjaTrader limit orders automatically delete themselves once per bar. I nearly tore my hair out, and I don’t have all that much hair, for several hours trying to figure out why orders deleted themselves automatically. Many people identify with the school of hard knocks approach to learning. I’m as thick headed as most. I figured out the cause when I revisitied NinjaTrader’s online documentation and discovered a limit entry method that allows good till cancelled (GTC) orders.
The speed problem also manifested with overfills. An overfill is when a strategy requests to cancel a pending order, but the broker fills the order before the cancellation takes effect. The biggest concern with overfills is that NinjaTrader automatically disables a strategy and exits positions at market when an overfill occurs. The only way to programmatically prevent this is to change the entry methods to an unmanaged approach.
The easiest way to develop for a high frequency strategy in NinjaTrader (but not ultra-high frequency) is to use managed orders. Whenever an exit is needed, place the limit entry in the opposite direction. NinjaTrader takes care of placing the exit order for the open market positoin. Limit the updates to every handful of seconds. It allows the broker API to catch up and helps avoid the problem of overfills.
Hi, thank u for sharing this experience. However, i am not a coder but an ATS developer and i am planning to use open source tradelink which also uses c# to link it with Oanda API. My ATS will also utilize sub minute time frame and will play fast ” medium FT”. I have found your post is very useful.
However, i am not familiar with NT. Could NT connect to Oanda API as well?
Shaun Overton says
I’m glad that you found the post informative. NinjaTrader only hooks up to supported brokers. It will not work with Oanda.
My plan is to use OpenQuant not NT. I have just started leaning coding so i am using NT rich educational resources too learn programming with C#. Then i will migrate to OQ. With OQ , i could have a custom broker connector. I do plan to connect it with LMAX.
However, my ATS speed could reach 10k orders per day ( around 1 order per 8 seconds) and mostly it is using pending orders ( 95% of times).
Please update your post with any relevant info regarding designing a higher than usual frequency trading automated system. Tips and tricks would be highly appreciated.
Shaun Overton says
Thank you for your post. We will keep this suggestion in mind for future blog posts.
I appreciate your write-up on overfills. It is the most sensible I have come across for the issue in NinjaTrader. What type of limit order is this in Ninja (referring to your post):
I figured out the cause when I revisitied NinjaTrader’s online documentation and discovered a limit entry method that allows good till cancelled (GTC) orders.
Shaun Overton says
It’s been several years since I wrote that post, but there was nothing special about the order types. They were generic limit orders.
Saludos desde España,
Estaría interesado en hablar contigo sobre este tipo de estrategias.
Podemos mandarnos un email por privado?