| 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