I’ve been a zipline developer for my own investing for a year and a half now. Through my use of this engine, I’ve accumulated a list of issues, quirks and grievances that I would like to share here in hopes that perhaps Stefan, or someone else, could fix them in a future release, or at least suggest some practical workaround.
Here’s a shortlist of a few known quirks/issues with Zipline reloaded:
- Order execution: zipline always executes every order at the end of the next trading candle. This is logical, as zipline was developed to be used with minute bars. However, subscribing for minute data is prohibitively expensive for the average user, and most anyone uses just daily data. Which means, for example, that if you use daily historical data, and you submit a market order today, it will be filled tomorrow at a price that’s nearly identical to the market close price (with slippage added).
why it’s problematic:
- buyng/selling on open does not work with zipline
- using stop orders does not work properly with zipline as the stop orders will be filled only if the CLOSE of the next candle has crossed the stop price. It does not matter if there were intraday fluctuations that could have triggered execution in the stop order.
- using limit orders does not work properly for the same reason. Also, limit orders do not execute at their limit price.
how it could be improved:
- add some function for daily data, that permits entering/exiting on open, after applying the relevant slippage.
- add some function for daily data that lets limit prices execute at (or better) their limit as should happen in real life.
- add some function for daily data that lets stop prices execute if intraday OHLC price fluctuations cross the stop point.
- Issues with slippage when setting stop and limit orders: for some reason, when stop/limit orders are executed, the slippage model is applied afterwards such that the entry prices are more favorable. This results in grossly over-optimistic and misleading results. One possible solution is to use the VolumeShareSlippage model with price_impact=0.0, but this is far from perfect.
how it could be improved:
- fix the bug where the slippage model interferes with limit prices
- fix the bug where the slippage model interferes with stop prices, making them more favorable
That’s it off the top of my head for now. If I think of more issues, I’ll add to the list here. However, these are the most annoying ones I’ve encountered so far, and they really put a wrench in Zipline’s flexibility of use.
Meanwhile, feel free to add your own lists of issues as well.
@nikolayt , valid issues…with daily trading in zipline, the minimum rebalance period is 3-days…else you run into order and portfolio hell…sounds like you know that though.
I use zipline-broker, which I manage, and keys on Interactive Brokers support. There is also zipline-trader, which works for Alpaca. Both work by having a live trading module (originally from zipline-live) bolted into zipline, which makes a connection to the broker, and sucks live data, from the broker, needed to trade this-moments-prices. So, in before_trading_starts, you can do all your pipeline/data.history stuff using daily data from yesterday and the past, then use today’s data by getting current price. There are some live trading tricks needed, yet not sure you are that interested. Both repos are not well supported, whereas zipline-reloaded has more support and backtesting features.
I’ve just about finished porting over to zipline-reloaded the special stuff I had in zipline-broker involving bundles and fundamentals support using Sharadar data, and plan to make a break with zipline-broker, moving to zipline-reloaded for all the backtesting I’m doing…I do not have a current solution for how to get to live trading. What I noticed is that many people have separate live trading module, soley for trade execution, that may take info on today’s trades, computed from a tool like zipline-reloaded, and then execute a secondary strategy using this live trading module.
Perhaps your list of requirements above could feed into a sister tool for zipline-reloaded that toolk output .csv files from zipline-reloaded, and then executed the trades indicated with the proper risk, slippage, and portfolio information.
Consider this the start to a conversation, not the end or an answer.
@nikolayt I would suggest adding all your grievances in the github project repository so that they can be better tracked and found.
@ajjcoppola and @nikolayt all your points are valid, but having looked at the zipline code for some time now, I think the code is still in need of a major cleanup to get rid of some old legacy stuff, and moving away from
bcolz storage etc
Following up on my previous post here to add two more issues related to futures continuations and rollovers:
- Suppose we have created a futures continuation for e-mini S&P 500 futures (symbol “ES”), using the following:
continuation = continuous_future(“ES”, offset=0, roll=“volume”, adjustment=“mul”)
this object always maintain a “current” contract that is the most traded by volume of all contracts (the roll=“volume” bit). So, when your algorithm enters new positions, it just asks the continuation which underlying contract it’s using at the moment and uses it for trading. The issue here is that when we’re using very recent data (say, for yesterday), zipline sometimes says the current contract is, say, the March’2023 contract. When you run the backtest again with more recent data several days later, it’s suddenly changed that and says the current contract back then was the April’2023 contract. This creates inconsistencies when backtrading on recent data.
- Related to the above: when rolling over, you typically check if the “current” contract and the contract you’re currently holding a position in are the same. If they are different, you roll to the most current contract. The issue here is quite often the continuation object uses a contract up to and including the expiration date. This means that if the contract expires today, your algorithm won’t roll it over. On the next day the continuation will switch to the new contract, but your algo won’t know this as it will have auto-closed the position. Thus you end up with random positions getting auto-closed, which is not part of your trading algorithm.
Ideally, if you could build a small test example (like for instance in
test_continuous_futures.py), then we would have at least a (failing) test, that would be a great motivation for implementing a fix.