| Overall Statistics |
|
Total Trades 2167 Average Win 0.72% Average Loss -0.73% Compounding Annual Return 10.620% Drawdown 25.500% Expectancy 0.238 Net Profit 550.864% Sharpe Ratio 0.899 Probabilistic Sharpe Ratio 26.258% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 0.99 Alpha 0 Beta 0 Annual Standard Deviation 0.129 Annual Variance 0.017 Information Ratio 0.899 Tracking Error 0.129 Treynor Ratio 0 Total Fees $9614.23 |
# Pick 5 ETFs with strongest 3 month momentum into your portfolio and weight them equally.
# Hold for 1 month and then rebalance at the satrt of a month
# Why invalid orders in backtest
# https://www.quantconnect.com/forum/discussion/10611/why-invalid-orders-in-backtest/p1
import pandas as pd
from datetime import datetime
class AssetClassMomentumAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2002, 7, 28)
self.SetEndDate(datetime.now())
self.InitCash = 100000
self.SetCash(self.InitCash)
self.MKT = self.AddEquity("SPY", Resolution.Hour).Symbol
self.mkt = []
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
# create a dictionary to store momentum indicators for all symbols
self.data = {}
period = int(3*21) # period of the momentum indicator is 3 months, average 21 business day for each month and 6.5 hours trading session
self.symbols = ["SPY", "IWF", "QQQ", "IBB", "XLV", "EEM", "IWD", "TLT", "IEF", "IGOV", "GLD", "IYR", "DBC"]
# warm up the MOM indicator
self.SetWarmUp(period)
for symbol in self.symbols:
self.AddEquity(symbol, Resolution.Minute)
if self.Securities[symbol].IsTradable == True:
self.data[symbol] = self.MOM(symbol, period, Resolution.Daily)
else:
continue
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 30),
self.Rebalance)
def Rebalance(self):
if self.IsWarmingUp: return
for sec in self.data:
if self.Securities[sec].IsTradable == False:
self.data.remove(sec)
top5 = pd.Series(self.data).sort_values(ascending = False)[:5]
for sec in self.Portfolio.Keys:
if sec not in top5.index:
self.Liquidate(sec)
for sec in top5.index:
self.SetHoldings(sec, 1.0 / len(top5))
def OnEndOfDay(self):
mkt_price = self.Securities[self.MKT].Close
self.mkt.append(mkt_price)
mkt_perf = self.InitCash * self.mkt[-1] / self.mkt[0]
self.Plot('Strategy Equity', self.MKT, mkt_perf)
account_leverage = self.Portfolio.TotalHoldingsValue / self.Portfolio.TotalPortfolioValue
self.Plot('Holdings', 'leverage', round(account_leverage, 2))
self.Plot('Holdings', 'Target Leverage', 1)