1

I am trying to do a backtest on a Markowitz portfolio. So far I've tried zipline, backtrader and QSTrader (although QSTrader may work, but there is no documentation so its very hard). I haven't had any luck with creating the backtest as I've wanted.

My data structure is a csv consisting of the adjusted closing prices for 200 different stocks. I want to do a portfolio rebalance every quarter or year. I already have the code for the actual portfolio optimization and the weights it returns. I just need an actual framework to plug those weights into and then redo the calculation every quarter yearly. I've been at it for around 5 hours so far and I just simply cant get any backtest to work. Zipline is very confusing in how it handles data and even more so when it comes to importing a local csv with the structure i described. Backtrader suffers bit of the same problem. QSTrader seems to just not work for me and it throws the following error after loading the data:

Traceback (most recent call last):
  File "d:\Finansiering. Modern Portfolio Theory Projekt\Finansiering_Backtrader.py", line 53, in <module>
    strategy_backtest.run()
  File "D:\Anaconda\envs\zipline\lib\site-packages\qstrader\trading\backtest.py", line 398, in run
    self.qts(dt, stats=stats)
  File "D:\Anaconda\envs\zipline\lib\site-packages\qstrader\system\qts.py", line 172, in __call__
    rebalance_orders = self.portfolio_construction_model(dt, stats=stats)
  File "D:\Anaconda\envs\zipline\lib\site-packages\qstrader\portcon\pcm.py", line 289, in __call__
    target_portfolio = self._generate_target_portfolio(dt, full_weights)
  File "D:\Anaconda\envs\zipline\lib\site-packages\qstrader\portcon\pcm.py", line 139, in _generate_target_portfolio
    return self.order_sizer(dt, weights)
  File "D:\Anaconda\envs\zipline\lib\site-packages\qstrader\portcon\order_sizer\dollar_weighted.py", line 168, in __call__
    'modifying the backtest start date and re-running.' % (asset, dt)
ValueError: Asset price for "A" at timestamp "2006-01-31 21:00:00+00:00" is Not-a-Number (NaN). This can occur if the chosen backtest start date is earlier than the first available price for a particular asset. Try modifying the backtest start date and re-running.

The start date of the backtest is correct, basically at the end of the month when it needs to rebalance it just gets a stroke. I haven't been able to fix this either.

I hope someone has a semi plug and play solution to this.

sword134
  • 91
  • 1
  • 11

2 Answers2

0

I'm not that experienced with zipline either, but it seems that zipline handles data with a data_bundle class. The documentation is not very clear indeed. Here's what you'll probably need to do:

  1. Formatize your data in the csv files - better build a function for that. The strict format of data bundles is included in the documentation under the section of custom csv bundle. Keep in mind that they need to have the exact same start and end dates, be aligned with your trading calendar, and have the EXACT same format as the csv provided in the documentation.

  2. You should have a ".zipline" folder, create/edit extension.py in it with the following contents: 1) register a trading calendar; 2) register the custom csv bundle - both of which can be found in the documentation.

  3. Type $zipline ingest -b [bundle_name] in your prompt - this should ingest the data.

  4. Call the data of each asset with "symbol" and specify the bundle name when running a backtest.

Hope this could help you.

Tony Zhang
  • 11
  • 2
0

I think bt - flexible backtesting for Python is more suited to what you want to do. The library is designed to periodically rebalance financial portfolio.

Florent
  • 1,791
  • 22
  • 40