Hammering away at the code, and slowly feeling like things are beginning to make sense. Had a lot of trouble figuring out how I wanted tick data stored (it comes in as a single price or size value at a time from Interactive Brokers; if I store that directly it's a nightmare to play back, but if I store full price/size set at each point there might be inaccurate records).
What I'm really noticing is that as I stop trying to hard complexity from the strategy, The first version had a single "Here's some new data" method that was called, and that then called the strategy runner to buy/sell. The new version has four methods:
- public void backfillTick(final long tickTime, final Double bidPrice, final Double askPrice, final Integer bidSize, final Integer askSize);
- public EntryOrder handleTickWhileFlat(final long tickTIme, final Double bidPrice, final Double askPrice, final Integer bidSize, final Integer askSize);
- public ExitOrders handleTickWhileLong(final long tickTIme, final Double bidPrice, final Double askPrice, final Integer bidSize, final Integer askSize);
- public ExitOrders handleTickWhileShort(final long tickTIme, final Double bidPrice, final Double askPrice, final Integer bidSize, final Integer askSize);
backfillTick() is used during warmup to add data for the strategy, without being tradeable. Previously I passed an "is up to date" parameter in, which was more error prone as the strategy could still try trading if it didn't check that parameter.
The remaining three methods all execute trades by returning them. This IMHO is a lot simpler than the previous version where methods on another object were called, and makes the actual flow clearer. handleTickWhileFlat() returns an object that contains a limit order for entering the market, and a pair of orders (stop and limit) for exiting. The strategy runner then pushes them through to the market as a complete set, with the second two triggered on the first.
The handleTickWhileLong() and handleTickWhileShort() methods return updated values for the stop/limit orders.
The result is that the strategy has a lot less conditionals in it, with much of the logic ending up in the code structure instead. I think it's better anyway...