Monday, August 20, 2018

Creating a trading system: list of mistakes

I'll publish further updates in separate posts under the #mistakes label.

I'll add to this list as I remember and/or encounter things:
  • Not using enough data for backtesting -- and using the data wrong. I.e. overfitting. This is probably the nr. 1 mistake -- and it's not a binary thing either; you have to determine "how overfit is my strategy? probably?" and yes assuming it is always somewhat overfit is the correct way to view this.
  • Thinking 1min data would be "good enough". It's not unless you explicitly architecture your strategies and backtester around certain limitations. You really need tick data for many strategies or else you end up with a lot of uncertainties as to what happened first when things are hectic (and important); e.g. fill vs. stop-loss vs. take-profit.
  • Not basing the system around continuous time series data/events.
  • Using Joda time instead of primitive longs for timestamps. If I need to deal with messy time calculations I'll coerce the long to a Joda time object then back again.
  • Thinking this would be a 6 month project. I've been doing this on and off since 2015(!). This is the 3rd variant or iteration of the project.
  • Using mutable state. Yes, I did this even in Clojure for "performance reasons". Of course mutable state in Clojure is fine if you do it in isolated areas -- but I did not do this. Even if I was using something like C++ or Rust I'd be doing functional programming and stick with immutable, persistent data structures at this point.
  • It's important to keep the call stack shallow. If one consider handling of exchange related events:
    • Have your main loop call the core and basic handling Fn first.
    • Then have the same loop (call site) pass the event to your strategy Fn which can further handle the event in more custom ways if needed.
    • By keeping the call stack shallow like this your dispatching will be trivial and faster (important if your main-loop does backtesting in addition to live trading) -- and it'll also be easier to eyeball what and where things went wrong via stack traces.
  • Avoid overuse of core.async. I'd only use this tool as a stream library I think; not for the "green thread" type stuff. I.e. avoid async/go.

I'll publish further updates in separate posts under the #mistakes label.