# Backtesting a portfolio strategy with several assets

I am aware that there exist several libraries and programs that allow to baktest a portfolio strategy by iterating through the OHLC dataframe of the stocks of interest (Backtrader, Backtesting, ...). However, these methods are useful when we are working on one or few stocks: when it comes to backtest a strategy that includes several stocks (thousands), it becomes impossible to iterate though all these datasets.

In these cases, how can we determine the ex-post returns of a portfolio containing such quantity of instruments? For example, if we know the weights for each stock at each trading day to invest in the portfolio, how can we test such strategy?

QuantRocket supports two backtesters, both of which are designed to support universe sizes in the thousands.

1. Moonshot is pandas-based and has the scalability you would expect from a pandas-based library. It's a good choice if you already know and love pandas.
2. Zipline has a design that allows you to dynamically filter thousands of securities each day and execute intraday trading logic on the filtered subset. It also supports end-of-day strategies.

There are examples of strategies targeting large universes in QuantRocket's Code Library.

You're right that many backtesters are geared toward a small number of securities, and trying to adapt them to support thousands of securities is generally an uphill battle.

Disclaimer: I'm affiliated with QuantRocket.

• Thank you for your answer. I'll look at the documentation. Just to be sure, if I have a dataframe containing the stock weights for each stock in each day, can I efficiently build a backtesting strategy with these two backtesters? – Matteo Jan 15 at 8:59

If using R is an option: With package PMwR, which I maintain, you could compute a time-series of returns for such a portfolio in one line of code:

## P -- a matrix of prices: each column holds the prices of one asset
## w -- a matrix of target weights: each row holds a portfolio
## t -- a vector of times (i.e. row numbers) at which to rebalance

library("PMwR")
returns(P, weights = w, rebalance.when = t)