Overall Statistics |
Total Trades 125 Average Win 0.04% Average Loss 0.00% Compounding Annual Return 14.531% Drawdown 5.600% Expectancy 12.182 Net Profit 31.124% Sharpe Ratio 1.944 Loss Rate 9% Win Rate 91% Profit-Loss Ratio 13.47 Alpha -0.021 Beta 7.987 Annual Standard Deviation 0.07 Annual Variance 0.005 Information Ratio 1.665 Tracking Error 0.07 Treynor Ratio 0.017 Total Fees $126.82 |
from math import ceil,floor,isnan from datetime import datetime import pandas as pd import numpy as np import cvxpy as cv class AssetAllocationAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2016, 1, 1) #Set Start Date self.SetEndDate(2018, 1, 1) #Set End Date self.SetCash(100000) #Set Strategy Cash tickers = ["IEF", "TLT", "SPY", "EFA", "EEM", "JPXN", "XLK"] self.symbols = [] for i in tickers: self.symbols.append(self.AddEquity(i, Resolution.Daily).Symbol) for syl in self.symbols: syl.window = RollingWindow[TradeBar](252) self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), Action(self.Rebalancing)) def OnData(self, data): if data.ContainsKey("SPY"): for syl in self.symbols: syl.window.Add(data[syl]) def Rebalancing(self): data = {} for syl in self.symbols: data[syl] = [float(i.Close) for i in syl.window] df_price = pd.DataFrame(data,columns=data.keys()) # To order prices from oldest to latest # df_price = df_price.sort_values(by = 0, ascending = False) df_price = df_price.iloc[::-1] # Calculating returns # daily_return = df_price.pct_change().dropna().values daily_return = df_price.pct_change().dropna() if daily_return.size != 0: a = PortfolioOptimization(daily_return, 0, len(data)) opt_weight = a.opt_portfolio() if isnan(sum(opt_weight)): return self.Log(str(opt_weight)) for i in range(len(data)): self.SetHoldings(df_price.columns[i], opt_weight[i]) # equally weighted # self.SetHoldings(self.symbols[i], 1.0/len(data)) class PortfolioOptimization(object): import numpy as np import pandas as pd import cvxpy as cv def __init__(self, df_return, risk_free_rate, num_assets): self.daily_return = df_return self.risk_free_rate = risk_free_rate self.n = num_assets # numbers of risk assets in portfolio self.mu = np.matrix(df_return.mean(axis = 0).values) self.sigma = df_return.cov().values def opt_portfolio(self): w = cv.Variable((self.mu.shape[1],1)) """ MV model Variables """ risk = cv.quad_form(w, self.sigma) constraints = [cv.sum(w) == 1] constraints.append(w >= 0) constraints.append(w <= 0.25) prob = cv.Problem(cv.Minimize(risk), constraints) prob.solve() weights = np.matrix(w.value).T weights = weights/np.sum(weights) weights = np.squeeze(np.array(weights)) return weights