Overall Statistics |
Total Trades 15670 Average Win 0.10% Average Loss -0.11% Compounding Annual Return 10.004% Drawdown 0.700% Expectancy 0.058 Net Profit 61.723% Sharpe Ratio 4.277 Probabilistic Sharpe Ratio 100.000% Loss Rate 46% Win Rate 54% Profit-Loss Ratio 0.96 Alpha 0.081 Beta -0.024 Annual Standard Deviation 0.018 Annual Variance 0 Information Ratio -0.166 Tracking Error 0.125 Treynor Ratio -3.271 Total Fees $82809.27 |
from Execution.ImmediateExecutionModel import ImmediateExecutionModel from collections import deque import numpy as np ll = 3 ul= 3 EmergingMarkets = [ ("EFO","EFU",-1,3,3), #Proshares MSCI EAFE ("UPV","EPV",-1,3,3), #Proshares MSCI Developed EU ("FXP","XPP",-1,3,3), #Proshares MSCI China ("EWV","EZJ",-1,3,3)] #Proshares MSCI Japan] ProsharesSectorETF = [ ("UYM","SMN",-1,3,3), #Proshares Dow Jones U.S. Basic Materials ("UBIO","ZBIO",-1,3,3), #Proshares Nasdaq Biotech 3x ("BIB","BIS",-1,3,3), #Proshares Nasdaq Biotech 2x ("SCOM","UCOM",-1,3,3), #Proshares S&P Communication Services Select Sector 3x ("SKF","UYG",-1,3,3), #Proshares Dow Jones U.S. Financials ("FINU","FINZ",-1,3,3), #Proshares S&P Financial Select Sector ("RXD","RXL",-1,3,3), #Proshares Dow Jones U.S. Health Care ("UXI","SIJ",-1,3,3), #Proshares Dow Jones U.S. Industrials ("DIG","DUG",-1,3,3), #Proshares Dow Jones U.S. Oil & Gas ("SRS","URE",-1,3,3), #Proshares Dow Jones Real Estate ("USD","SSG",-1,3,3), #Proshares Dow Jones U.S. Semiconductors ("ROM","REW",-1,3,3), #Proshares Dow Jones U.S. Technology ("SDP","UPW",-1,3,3)] NotLiquid = [ ("SAA", "SDD"), ("MZZ", "MVV", -1,3,3), ("UMDD", "SMDD", -1,3,3), ("GLL","UGL",-1,3,3),#Proshares Bloomberg Gold Subindex ("AGQ","ZSL",-1,3,3),#Proshares Bloomberg Silver Subindex ("YCS","YCL",-1,3,3), ("DSLV","USLV",-1,3,3), ("UGLD","DGLD",-1,3,3), ("GUSH","DRIP",-1,3,3), #Direxion Oils and Gas Exploration ("RUSL","RUSS",-1,3,3), #Direxion Russia ("GASL","GASX",-1,3,3), #Direxion Natural Gas ("FAZ","FAS",-1,3,3),#Direxion Financials ("ERY","ERX",-1,3,3), #Direxion Energy ("YINN","YANG",-1,3,3) ] + EmergingMarkets + ProsharesSectorETF USTreasury = [ ("TBT","UBT",-1,3,3), #Proshares ICE U.S. Treasury 20+ Year Bond ("PST","UST",-1,3,3), #Proshares ICE U.S. Treasury 7 Year Bond ("TMF","TMV",-1,3,3)] LiquidETFCompetition = [ ("UGAZ","DGAZ",-1,3,3), ("ERY","ERX",-1,3,3), ("NUGT","DUST",-1,3,3), ("UCO","SCO",-1,3,3), ("NUGT","DUST",-1,3,3), ("TECS","TECL",-1,3,3), ("SOXS","SOXL",-1,3,3)] SP500 = [ #Proshares SP Small Cap #Proshares SP Mid Cap 2x #Proshares SP Mid Cap 3x ("SPY", "SH", -1, 3,3), #-1 ("SDS","SSO",-1,3,3),#Proshares SP500 2x ("UPRO","SPXU",-1,3,3), #3x ("SPXL","SPXS",-1,3,3)]# 3x NASDAQ = [ ("TQQQ","SQQQ",-1,ll,ul), #Proshares Nasdaq 3x ("QQQ","PSQ",-1,ll,ul ), #1x ("QLD","QID",-1,ll,ul)] #2x DJIA = [ ("DIA", 'DOG', -1, 3,3), #Proshares Dow 1x ("SDOW","UDOW",-1,3,3),#Proshares Dow 3x ("DDM","DXD",-1,3,3)] #Proshares Dow 2x Russell2000 = [ ("URTY","SRTY",-1,3,3), #Proshares Russel 3x ("RWM","IWM",-1,3,3), #Proshares Russel 1x ("UWM","TWM",-1,3,3)] DirexionETFs = [ ("TECL","TECS",-1,3,3),#Direxion Tech 3x ("TNA","TZA",-1,3,3), #Direxion Small Cap 3x ("LABU","LABD",-1,3,3), #Direxion Biotech ("NUGT","DUST",-1,3,3), #Direxion Gold Miners ("JNUG","JDST",-1,3,3), #Direxion Junior Gold Miners ] Commoditities = [ ("OILU","OILD",-1,2,3), #Proshares Bloomberg WTI Crude Oil Subindex 3x ("UCO","SCO",-1,3,3),#Proshares Bloomberg WTI Crude Oil Subindex 2x ("ERY","ERX",-1,3,3)] AllPairs = Commoditities + DirexionETFs + Russell2000 + DJIA + NASDAQ + SP500 + LiquidETFCompetition def fetch_symbols(Pairs): symbols = [] for info in Pairs: symbols.append(info[0]) symbols.append(info[1]) return symbols Log = False Pairs = DJIA RiskCap= -.0020 LossCap = 3 class LETFArb(QCAlgorithm): def Initialize(self): self.SetStartDate(2015, 1, 1) # Set Start Date self.SetEndDate(2020, 1, 14) self.SetBrokerageModel(BrokerageName.AlphaStreams) self.BettingSize = float(1/len(fetch_symbols(Pairs))) self.SetCash(round(50000/self.BettingSize)) self.Lookback = 6000 self.losscap = LossCap self.riskcap = RiskCap self.PairData= {} for info in Pairs: self.AddEquity(info[0], Resolution.Minute) self.AddEquity(info[1], Resolution.Minute) self.SetExecution(ImmediateExecutionModel()) self.SetBenchmark("SPY") symbols = [] for symbol in fetch_symbols(Pairs): symbols.append(Symbol.Create(symbol, SecurityType.Equity, Market.USA)) self.SetUniverseSelection(ManualUniverseSelectionModel(symbols)) for info in Pairs: index_h= self.History(self.Symbol(info[0]), self.Lookback) letf_h = self.History(self.Symbol(info[1]), self.Lookback) if ("close" in index_h.columns) and ("close" in letf_h.columns): index_prices = index_h["close"] letf_prices = letf_h["close"] letf = letf_prices.pct_change().dropna() index = index_prices.pct_change().dropna() spreads = np.log(1+letf) - np.log(1+info[2]*index) index_prices =[index_prices.iloc[-2], index_prices.iloc[-1]] letf_prices =[letf_prices.iloc[-2], letf_prices.iloc[-1]] self.PairData[info] = { "Spreads":deque(spreads, maxlen= self.Lookback), "IndexPrices": deque(index_prices, maxlen =2), "LETFPrices": deque(letf_prices, maxlen=2), "Loss": 0, } else: self.PairData[info] = { "Spreads":deque([0], maxlen= self.Lookback), "IndexPrices": deque([0], maxlen =2), "LETFPrices": deque([0], maxlen=2), "Loss":0, } self.SetTimeZone("America/New_York") self.SetWarmUp(timedelta(1)) def OnData(self, data): for pairsinfo in self.PairData: IndexTicker = pairsinfo[0] LETFTicker = pairsinfo[1] if (data.Bars.ContainsKey(IndexTicker) and (data.Bars.ContainsKey(LETFTicker))): IndexPrices = self.PairData[pairsinfo]["IndexPrices"] IndexPrices.append(float(data.Bars[IndexTicker].Close)) LETFPrices = self.PairData[pairsinfo]["LETFPrices"] LETFPrices.append(float(data.Bars[LETFTicker].Close)) self.PairData[pairsinfo]["IndexPrices"] = IndexPrices self.PairData[pairsinfo]["LETFPrices"] = LETFPrices if len(IndexPrices) ==2: if IndexPrices[-2] == 0: continue IndexReturn = float( (IndexPrices[-1] - IndexPrices[-2]) / IndexPrices[-2] ) if LETFPrices[-2] == 0: continue LETFReturn = float( (LETFPrices[-1] - LETFPrices[-2]) / LETFPrices[-2] ) Leverage = pairsinfo[2] ExpectedReturn = np.log(1+Leverage*IndexReturn) LETFReturn = np.log(1+ LETFReturn) Spread = float(LETFReturn - ExpectedReturn) Spreads = self.PairData[pairsinfo]["Spreads"] if Spread !=0: Spreads.append(Spread) self.PairData[pairsinfo]["Spreads"] =Spreads if len(Spreads) >= self.Lookback: LowerLimit = pairsinfo[3] UpperLimit = pairsinfo[4] SpreadDeviations = np.std(Spreads) DiscountBand = float(-1* LowerLimit*SpreadDeviations) PremiumBand = float(UpperLimit * SpreadDeviations) Discount = Spread <= DiscountBand Premium = Spread >= PremiumBand OpenPosition = (self.Securities[LETFTicker].Invested) and (self.Securities[IndexTicker].Invested) msg1 = IndexTicker +" " +str(Spread) msg2 = LETFTicker + " "+str(Spread) if (Discount and not OpenPosition): self.EmitInsights(Insight.Price(LETFTicker, timedelta(60), InsightDirection.Up)) self.EmitInsights(Insight.Price(IndexTicker, timedelta(60), InsightDirection.Down)) self.SetHoldings([PortfolioTarget(LETFTicker, self.BettingSize), PortfolioTarget(IndexTicker, self.BettingSize)]) self.Log(msg1) self.Log(msg2) elif(Premium and OpenPosition): pl = (self.Portfolio[IndexTicker].UnrealizedProfit + self.Portfolio[LETFTicker].UnrealizedProfit)/self.Portfolio.TotalPortfolioValue if pl>0: self.EmitInsights(Insight.Price(LETFTicker, timedelta(300), InsightDirection.Flat)) self.EmitInsights(Insight.Price(IndexTicker, timedelta(300), InsightDirection.Flat)) self.Liquidate(LETFTicker) self.Liquidate(IndexTicker) self.PairData[pairsinfo]["Loss"] = 0 if Log: self.Log(msg1) self.Log(msg2) else: self.PairData[pairsinfo]["Loss"] += 1 if (self.PairData[pairsinfo]["Loss"] >=self.losscap) or pl < self.riskcap: self.EmitInsights(Insight.Price(LETFTicker, timedelta(300), InsightDirection.Flat)) self.EmitInsights(Insight.Price(IndexTicker, timedelta(300), InsightDirection.Flat)) self.Liquidate(LETFTicker) self.Liquidate(IndexTicker) self.PairData[pairsinfo]["Loss"] = 0 if Log: self.Log(msg1) self.Log(msg2) elif(OpenPosition) and not(Premium or Discount): pl = (self.Portfolio[IndexTicker].UnrealizedProfit + self.Portfolio[LETFTicker].UnrealizedProfit)/self.Portfolio.TotalPortfolioValue if pl >0 and self.PairData[pairsinfo]["Loss"] > 0: self.EmitInsights(Insight.Price(LETFTicker, timedelta(60), InsightDirection.Flat)) self.EmitInsights(Insight.Price(IndexTicker, timedelta(60), InsightDirection.Flat)) self.Liquidate(LETFTicker) self.Liquidate(IndexTicker) self.PairData[pairsinfo]["Loss"] = 0 if Log: self.Log(msg1) self.Log(msg2) else: pass