| Overall Statistics |
|
Total Trades 969 Average Win 0.45% Average Loss -0.16% Compounding Annual Return 19.340% Drawdown 13.200% Expectancy 1.341 Net Profit 164.838% Sharpe Ratio 1.497 Probabilistic Sharpe Ratio 79.620% Loss Rate 39% Win Rate 61% Profit-Loss Ratio 2.82 Alpha 0.196 Beta 0.072 Annual Standard Deviation 0.137 Annual Variance 0.019 Information Ratio 0.355 Tracking Error 0.221 Treynor Ratio 2.827 Total Fees $1782.46 |
import numpy as np
import pandas as pd
class TransdimensionalOptimizedAtmosphericScrubbers(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015, 4, 29) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
res = Resolution.Minute
self.STOCK = self.AddEquity('QQQ', res).Symbol
self.BONDS = [self.AddEquity(ticker, res).Symbol for ticker in ['TLT', 'IEF']]
self.XLI, self.XLU, self.UUP = [self.AddEquity(ticker, res).Symbol for ticker in ['XLI', 'XLU', 'UUP'] ]
self.VOLA = 126;
self.BULL = 1;
self.COUNT = 0;
self.OUT_DAY = 0;
self.RET_INITIAL = 80;
self.LEV = 1.00;
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen('QQQ', 140), self.daily_check)
self.mkt_closes = RollingWindow[float](self.VOLA + 1)
history = self.History([self.STOCK], self.VOLA + 1, Resolution.Daily)
if not history.empty and 'close' in history.columns:
for time, close in history.loc[self.STOCK].close.iteritems():
self.mkt_closes.Add(close)
# Setup consolidator
self.consolidator = TradeBarConsolidator(1)
self.consolidator.DataConsolidated += self.DailyHandler
self.SubscriptionManager.AddConsolidator(self.STOCK, self.consolidator)
def DailyHandler(self, sender, consolidated):
self.mkt_closes.Add(consolidated.Close)
def daily_check(self):
if not self.mkt_closes.IsReady:
return
vola = pd.Series(self.mkt_closes).iloc[::-1].pct_change().std() * np.sqrt(252)
WAIT_DAYS = int(vola * self.RET_INITIAL)
RET = int((1.0 - vola) * self.RET_INITIAL)
P = self.History([self.XLI, self.XLU, self.UUP], RET + 2, Resolution.Daily)['close'].unstack(level=0).iloc[:-1].dropna()
if (len(P.columns) < 2):
return
ratio = (P[self.XLI].iloc[-1] / P[self.XLI].iloc[0]) / (P[self.XLU].iloc[-1] / P[self.XLU].iloc[0])
exit = ratio < 1.0
if exit:
self.BULL = 0;
self.OUT_DAY = self.COUNT;
elif (self.COUNT >= self.OUT_DAY + WAIT_DAYS):
self.BULL = 1
self.COUNT += 1
wt_stk = self.LEV if self.BULL else 0;
wt_bnd = 0 if self.BULL else self.LEV;
wt = {}
wt[self.STOCK] = wt_stk
for sec in self.BONDS:
wt[sec] = wt_bnd / len(self.BONDS)
for sec, weight in wt.items():
self.SetHoldings(sec, weight)