Backtest Period
1980-2005
Markets Traded
Equities
Maximum Drawdown
Period of Rebalancing
Yearly
Return (Annual)
32%
Sharpe Ratio
Standard Deviation (Annual)
Original paper
SSRN-id1928694.pdf127.9KB
Trading rules
- Investment universe: All stocks on London Exchange (excluding multiple-class ordinary shares, foreign companies, lightly regulated markets, and financial sector stocks)
- Portfolio formation: Annually in July
- Inclusion criteria: NCAV/MV ratio higher than 1.5
- Portfolio type: Buy-and-hold
- Holding period: One year
- Stock weighting: Equally weighted
Python code
Backtrader
import backtrader as bt
import datetime
class NCAVStrategy(bt.Strategy):
def __init__(self):
self.ncav_ratio_threshold = 1.5
def next(self):
if self.datetime.month[0] == 7 and self.datetime.day[0] == 1:
self.rebalance_portfolio()
def rebalance_portfolio(self):
self.sell_all_stocks()
selected_stocks = self.select_stocks()
if not selected_stocks:
return
weight = 1.0 / len(selected_stocks)
for stock in selected_stocks:
self.buy(stock, target=weight)
def sell_all_stocks(self):
for position in self.positions:
if position.is_long:
self.sell(position.data)
def select_stocks(self):
ncav_stocks = []
for stock in self.getdatanames():
data = self.getdatabyname(stock)
ncav = data.ncav[0]
mv = data.close[0]
if mv == 0:
continue
ncav_mv_ratio = ncav / mv
if ncav_mv_ratio > self.ncav_ratio_threshold:
ncav_stocks.append(data)
return ncav_stocks
if __name__ == '__main__':
cerebro = bt.Cerebro()
cerebro.addstrategy(NCAVStrategy)
# Load data and add to cerebro
# ...
cerebro.run()
Note that this code assumes that the NCAV data is available for each stock in the dataset. You’ll need to load the stock data and NCAV data for each stock on the London Exchange and add them to the Cerebro instance.