Backtest Period
Markets Traded
Equities
Maximum Drawdown
Period of Rebalancing
Yearly
Return (Annual)
Sharpe Ratio
Standard Deviation (Annual)
Original paper
SSRN-id329840.pdf470.1KB
Trading rules
- Investment universe: 15 developed countries (Australia, Austria, Belgium, Canada, Denmark, France, Germany, Italy, Japan, Netherlands, Spain, Sweden, Switzerland, UK, US)
- Measure % of adults over 65 in each country
- Calculate average and standard deviation for this measure
- Go long on countries with % of population >65 at least 1 standard deviation below average
- Go short on countries with % of population >65 at least 1 standard deviation above average
- Rebalance portfolio annually
Python code
Backtrader
import backtrader as bt
import pandas as pd
class DemographicStrategy(bt.Strategy):
def __init__(self):
self.country_data = pd.DataFrame({
'country': ['Australia', 'Austria', 'Belgium', 'Canada', 'Denmark', 'France', 'Germany', 'Italy', 'Japan', 'Netherlands', 'Spain', 'Sweden', 'Switzerland', 'UK', 'US'],
'percent_over_65': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # Fill in actual data
})
def next(self):
if self.datetime.date().month != 12:
return
mean_over_65 = self.country_data['percent_over_65'].mean()
std_over_65 = self.country_data['percent_over_65'].std()
long_countries = self.country_data[self.country_data['percent_over_65'] < mean_over_65 - std_over_65]
short_countries = self.country_data[self.country_data['percent_over_65'] > mean_over_65 + std_over_65]
# Allocate equal weights to long and short positions
long_weight = 1.0 / len(long_countries)
short_weight = -1.0 / len(short_countries)
# Adjust positions
for d in self.getdatanames():
country = d.split('.')[0]
if country in long_countries['country'].values:
self.order_target_percent(data=d, target=long_weight)
elif country in short_countries['country'].values:
self.order_target_percent(data=d, target=short_weight)
else:
self.order_target_percent(data=d, target=0.0)
cerebro = bt.Cerebro()
# Add data feeds for each country's ETF
# Data should be in a format that includes the country name in the dataname field
# Example: cerebro.adddata(bt.feeds.YahooFinanceData(dataname='Australia.ETF', ...))
# ...
cerebro.addstrategy(DemographicStrategy)
cerebro.run()
Please note that you will need to replace the ‘percent_over_65’ values in the ‘country_data’ DataFrame with the actual data. Also, make sure to add the data feeds for each country’s ETF to the ‘cerebro’ object before running the strategy.