Overall Statistics |
Total Trades 1330 Average Win 0.76% Average Loss -0.54% Compounding Annual Return 11.806% Drawdown 12.100% Expectancy 0.443 Net Profit 376.303% Sharpe Ratio 1.023 Probabilistic Sharpe Ratio 46.982% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 1.41 Alpha 0.069 Beta 0.171 Annual Standard Deviation 0.082 Annual Variance 0.007 Information Ratio -0.033 Tracking Error 0.159 Treynor Ratio 0.49 Total Fees $0.00 Estimated Strategy Capacity $670000.00 Lowest Capacity Asset VNQ T2FCD04TATET |
import numpy as np import pandas as pd import random import math class CasualRedOrangeJackal(QCAlgorithm): def Initialize(self): self.SetStartDate(2008, 1, 1) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.InitCash = 100000 self.AddEquity("SPY", Resolution.Minute) self.MKT = self.AddEquity("SPY", Resolution.Daily).Symbol self.spy = [] self.basket = ['VTI', 'VXUS', 'VNQ', 'BND', 'GLD', 'EFA', 'TLT', 'IEF', 'QQQ'] for ticker in self.basket: self.AddEquity(ticker, Resolution.Minute) self.Securities[ticker].FeeModel = ConstantFeeModel(0) self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(0, 0), Action(self.ScheduleEndOfMonthRebalance)) self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.BeforeMarketClose('SPY', 5), Action(self.Rebalance)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose('SPY', 0), self.record_vars) def record_vars(self): hist = self.History(self.MKT, 2, Resolution.Daily)['close'].unstack(level= 0).dropna() self.spy.append(hist[self.MKT].iloc[-1]) spy_perf = self.spy[-1] / self.spy[0] * self.InitCash self.Plot('Strategy Equity', 'SPY', spy_perf) def ScheduleEndOfMonthRebalance(self): month_last_day = DateTime(self.Time.year, self.Time.month, DateTime.DaysInMonth(self.Time.year, self.Time.month)) trading_days = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, self.Time, month_last_day) #get the last day in trading_days for x in trading_days: self.month_last_trading_day = x.Date.date() def Rebalance(self): if self.Time.date() == self.month_last_trading_day: dataframe = self.History(self.basket, 180, Resolution.Daily) df = dataframe['close'].unstack(level=0) self.Liquidate() self.Debug(self.Portfolio.Cash) self.adaptive_asset_allocation(df, 4, 20, 180, self.Portfolio.Cash, 1) def adaptive_asset_allocation(self, df, nlargest, volatility_window, return_window, portfolio_value, leverage): window_returns = np.log(df.iloc[-1]) - np.log(df.iloc[0]) nlargest = list(window_returns.nlargest(nlargest).index) returns = df[nlargest].pct_change() returns_cov_normalized = returns[-volatility_window:].apply(lambda x: np.log(1+x)).cov() returns_corr_normalized = returns[-volatility_window:].apply(lambda x: np.log(1+x)).corr() returns_std = returns.apply(lambda x: np.log(1+x)).std() port_returns = [] port_volatility = [] port_weights = [] num_assets = len(returns.columns) num_portfolios = 100 individual_rets = window_returns[nlargest] for port in range(num_portfolios): weights = np.random.random(num_assets) weights = weights/np.sum(weights) port_weights.append(weights) rets = np.dot(weights, individual_rets) port_returns.append(rets) var = returns_cov_normalized.mul(weights, axis=0).mul(weights, axis=1).sum().sum() sd = np.sqrt(var) ann_sd = sd * np.sqrt(256) port_volatility.append(ann_sd) data = {'Returns': port_returns, 'Volatility': port_volatility} hover_data = [] for counter, symbol in enumerate(nlargest): data[symbol] = [w[counter] for w in port_weights] hover_data.append(symbol) portfolios_V1 = pd.DataFrame(data) min_var_portfolio = portfolios_V1.iloc[portfolios_V1['Volatility'].idxmin()] max_sharpe_portfolio = portfolios_V1.iloc[(portfolios_V1['Returns'] / portfolios_V1['Volatility']).idxmax()] proportions = min_var_portfolio[nlargest] index = 0 for proportion in proportions: self.SetHoldings(nlargest[index], proportion * leverage) self.Debug('{}% of portfolio in {}'.format(proportion * leverage, nlargest[index])) index += 1