| Overall Statistics |
|
Total Trades 2 Average Win 0.39% Average Loss 0% Compounding Annual Return 0.393% Drawdown 0.200% Expectancy 0 Net Profit 0.393% Sharpe Ratio 0.624 Probabilistic Sharpe Ratio 27.875% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.003 Beta 0.001 Annual Standard Deviation 0.005 Annual Variance 0 Information Ratio 0.188 Tracking Error 0.153 Treynor Ratio 2.801 Total Fees $22.17 |
'''
NOTES re CT III from FUTs
#FUCK need to add HIGHS and LOWS to ma -- so need 2 MAs
#ha12 and la12
#R1 = Average(High?! of data2-O of data2,12);
#S1 = Average(O of data2-L of data2,12);
#Cent = (OpenD(0)+CloseD(1))/2;
#R2 = Cent + PercentRange*R1; 0 + .5 * R1
#S2 = Cent - PercentRange*S1;
#if lower > upper3 #Done
#and Close < S2 #DONE
#and opend(0) > close //(15M Close) #Do in OnData with TradeBar
#Buy
Simpler way -- FUCK ult osc and this bullshit trade bar fucking joke. Jesus.
for c in sortedByVol:
symbol = c.Symbol
if symbol not in self.UOs:
history = self.History(symbol, 51, Resolution.Daily)
self.UOs[symbol] = Ultimate(symbol, history)
self.UOs[symbol].Update(c.EndTime, c.AdjustedPrice)
#sortedByUO = sorted(self.UOs.items(), key = lambda kv: v.uo_value, reverse=True)
if self.UOs[symbol].uo_val > 100:
self.longs += [symbol]
elif self.UOs[symbol].uo_val < -100:
self.shorts += [symbol]
self.selected = self.longs + self.shorts
FUCK UO
In OnData
#U3 Version...
for symbol in self.selected:
if data.Bars.ContainsKey(symbol):
if symbol not in self.U3s:
hist = self.History(symbol, 25, Resolution.Daily)
self.U3s[symbol] = U3(hist, symbol)
self.U3s[symbol].Update(data[symbol].EndTime,data[symbol]) #data[symbol].EndTime,
#End U3 Version...
tradeBars = data.Bars
ibmTradeBar = tradeBars['IBM']
class U3():
def __init__(self,history, symbol=None):
if symbol:
self.symbol = symbol
self.uo = UltimateOscillator(9,15,25)
for time, price in history.items(): #Manual update...
self.Update(time, price)
#I think issue is -- ^^ is using history
#whereas BELOW is using data['symbol']
def Update(self,time, bar):
#Accepts data[sym] as bar
#Update in OnData w data['SPY'] AS BAR -> data["SPY"].EndTime , data["SPY"].Close, High, Low etc
#Dont kno if I need this line ? Think I already have tradebar.
#bar.EndTime
#IF not work try with bar! BELOW
bar = TradeBar(time, self.symbol, bar.open, bar.high, bar.low, bar.close, bar.Volume)
self.uo.Update(bar) #Builtin UO Update method...
'''
class DailyBars():
def __init__(self, algorithm, history):
self.dailyWindow = RollingWindow[TradeBar](10) #GENIUS
#REPLACES UPDATE...
self.dailyCons = TradeBarConsolidator(timedelta(days=1))
algorithm.SubscriptionManager.AddConsolidator(symbol, self.dailyCons)
for bar in history.itertuples():
tb = TradeBar(bar.Index[1], symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
self.dailyWindow.Add(tb)
@property
def IsReady(self):
return self.dailyWindow.IsReady#from Selection.EmaCrossUniverseSelectionModel import EmaCrossUniverseSelectionModel
from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Securities import *
from QuantConnect import Market
from datetime import datetime
import pandas as pd
class CalibratedOptimizedInterceptor(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2018, 1, 1) # Set Start Date
self.SetEndDate(2019, 1, 1)
self.SetCash(100000) # Set Strategy Cash
# self.AddEquity("SPY", Resolution.Minute)
fastPeriod = 10
slowPeriod = 30
count = 10
self.UOs = {}
self.BB15s = {}
self.U3s = {}
self.L3s = {}
self.DOs = {}
#self.SetUniverseSelection(self.SelectCoarse)
self.AddUniverse(self.SelectCoarse)
self.UniverseSettings.Resolution = Resolution.Daily
def OnEndOfDay(self):
'''Where on earth is this called?'''
self.Debug(f'{self.Time.date()} -- {len(self.ActiveSecurities)}')
#for security in self.ActiveSecurities.Values:
# self.Debug(f"{self.Time.date()} -- {security.Symbol.Value}")
def SelectCoarse(self, coarse):
sortedByVol = sorted([c for c in coarse if c.AdjustedPrice > 10],
key = lambda x: x.DollarVolume, reverse=True)[:100]
self.selected = []
self.longs = []
self.shorts = []
#Alt method...
new = [s.Symbol for s in sortedByVol if s.Symbol not in self.UOs]
if new:
history = self.History(new, 51, Resolution.Daily)
if history.empty: return Universe.Unchanged
history = history.close.unstack(0)
for sym in new:
if sym in history: #Added?
self.UOs[sym] = DBB(history[sym].dropna())
openD, lower, upper, ma12 = 0,0,0,0
for c in sortedByVol:
symbol = c.Symbol
if symbol not in new and symbol in self.UOs:
self.UOs[symbol].Update(c.EndTime, c.AdjustedPrice)
#New for U2
if symbol not in self.BB15s:
history = self.History(symbol, 25, Resolution.Daily)
self.BB15s[symbol] = BB(symbol, self, history)
lower = self.BB15s[symbol].lb.Current.Value
upper = self.BB15s[symbol].ub.Current.Value
ma12 = self.BB15s[symbol].MA.Current.Value
#self.Debug(f'{symbol} -- U:{upper} L:{lower} MA:{ma12}')
'''
This needs to be ha12 and la12 -- 2 MAs... --
can just average the highs / lows in vecs?
'''
openD = history.open.iloc[-1] #-1 or 0?
#closeYD = history.close.iloc[-2] Maybe should do windows?
#self.Debug(f'{self.U2s[symbol].uo.Current.Value}')
if self.UOs[symbol].IsReady and self.BB15s[symbol]:
upper3 = self.UOs[symbol].ub3 #Uses Current.Value already!
lower3 = self.UOs[symbol].lb3
closeY = self.UOs[symbol].closeDs[1]
self.Debug(f'{symbol} -- U3:{upper3} L3:{lower3} CloseY:{closeY}')
self.Debug(f'{symbol} -- U:{upper} L:{lower} MA:{ma12}')
cent = (openD + closeY) / 2
R2 = cent + .5 * ma12
S2 = cent - .5 * ma12
if lower > upper3 and c.AdjustedPrice > (ma12): #Added in .5 here, to make R2 S2
self.longs += [symbol]
if upper < lower3 and c.AdjustedPrice < (ma12):
self.shorts += [symbol]
self.selected = self.longs + self.shorts
self.Debug(f'{self.selected}')
return self.selected
def SelectFine(self, fine):
pass
def OnSecuritiesChanged(self, changes):
self.Log(f"Added Securities: {[security.Symbol.Value for security in changes.AddedSecurities]}")
insights = []
for security in changes.RemovedSecurities:
self.Liquidate(security.Symbol)
#insights += [Insight.Price(security.Symbol, timedelta(weeks=99), InsightDirection.Flat)]
#algorithm.SubscriptionManager.RemoveConsolidator(symbol, self.symbols[symbol].monthlyConsolidator)
#algorithm.SubscriptionManager.RemoveConsolidator(symbol, self.symbols[symbol].dailyConsolidator)
#self.EmitInsights(insights)
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
if len(self.selected) == 0: return
qty = .99 / len(self.selected)
self.selected = [sym for sym in self.selected if data.ContainsKey(sym)]
bar = data.Bars
#Get daily open... For Timing the entries of longs / shorts.
for symbol in self.selected:
if not data.ContainsKey(symbol): continue
sbar = bar[symbol]
if symbol not in self.DOs:
hist = self.History(symbol, 5, Resolution.Daily)
self.DOs[symbol] = DailyOpen(hist)
self.DOs[symbol].Update(sbar.Open) #Think this is right?
todaysOpen = self.DOs[symbol].todaysOpen
#and opend(0) > close //(15M Close) -- NEED to save OPEN of day!
#Long Entries
self.longs = [sym for sym in self.longs if sym in self.selected ]
for symbol in self.longs:
if self.Portfolio[symbol].IsLong: continue
if not data.ContainsKey(symbol): continue
sbar = bar[symbol]
#self.Debug(f'open > close ? -- {todaysOpen} > {sbar.Close}')
if todaysOpen > sbar.Close:
self.SetHoldings(symbol, qty)
''' LONG ONLY
#Short Entries -- really just daily timing of them.
self.shorts = [sym for sym in self.shorts if sym in self.selected]
for symbol in self.shorts:
if self.Portfolio[symbol].IsShort: continue
if not data.ContainsKey(symbol): continue
sbar = bar[symbol]
#self.Debug(f'open < close ? -- {todaysOpen} < {sbar.Close}')
if todaysOpen < sbar.Close:
self.SetHoldings(symbol, -qty)
#MAY need to increment entries today?
'''
class DBB():
#Need rolling window -- to ADD past DAILY bbs to this...
def __init__(self,history): #symbol,
#self.window = RollingWindow[float](50)
self.closeDs = RollingWindow[float](2) #This is DAILY close
#self.opens = RollingWindow[float](2) #Cannot add this, bc only closes passed.
self.uppers = RollingWindow[float](5) #New Addit!
self.lowers = RollingWindow[float](5)
self.ub3 = None
self.lb3 = None
#self.uo = UltimateOscillator(9, 15, 24) #self.symbol,
self.bb = BollingerBands(20,2, MovingAverageType.Simple)
self.ub = self.bb.UpperBand
self.lb = self.bb.LowerBand
#Unstacked one...
for time, price in history.items():
self.Update(time, price)
def Update(self,time, price): #time,
self.bb.Update(time,price)
self.uppers.Add(self.ub.Current.Value) #Addits...
self.lowers.Add(self.ub.Current.Value)
self.closeDs.Add(price)
if self.IsReady:
self.ub3 = self.uppers[3]
self.lb3 = self.lowers[3]
@property
def IsReady(self): #Addits...
return self.bb.IsReady and self.uppers.IsReady and self.lowers.IsReady #self.uo.IsReady #and
class BB():
'''15M BBs'''
def __init__(self,symbol, algorithm, history):
self.BB = BollingerBands(symbol,20,2, MovingAverageType.Simple)
# ADDED SYMBOL ^^^^ TO BB
self.symbol = symbol
algorithm.AddEquity(self.symbol) #?? Need to add I guess.. OKAY!
self.consolidator = TradeBarConsolidator(timedelta(minutes=15))
algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator) #NEW
algorithm.RegisterIndicator(symbol, self.BB, self.consolidator)
self.ub = self.BB.UpperBand
self.lb = self.BB.LowerBand
#MA Cons (NEW)
self.MA = SimpleMovingAverage(12)
self.ma_cons = TradeBarConsolidator(timedelta(days=1))
algorithm.RegisterIndicator(symbol, self.MA, self.ma_cons)
#self.ma = self.MA #.Current.Value
#ZO ADDITS ************************
for bar in history.itertuples(): #Manual update...
tbar = TradeBar(bar.Index[1], symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
self.consolidator.Update(tbar)
self.ma_cons.Update(tbar)
self.MA.Update(tbar.EndTime,tbar.Close) #JUST tbar input?
self.BB.Update(tbar.EndTime,tbar.Close)
# *********************************
#Register / Subscribe to event Don't think this is needed? ^^ that is register
#self.consolidator.DataConsolidated += self.OnDataConsolidated
@property
def IsReady(self):
return self.MA.IsReady and self.BB.IsReady
'''
#Dont think I need this?
def OnDataConsolidated(self, sender, bar):
#self.window.Add(bar.Close)
self.BB.Update(bar.EndTime, bar.Close) #Might JUST need to be index and bar -- if it's JUST closes?
self.MA.Update(bar.EndTime, bar.Close)
self.ub = self.BB.UpperBand
self.lb = self.BB.LowerBand
self.ma = self.MA
'''
class DailyOpen():
'''CAN just add TRADEBAR to window, then call w keys -- self.pastBars[0].Open, for ex'''
def __init__(self, history):
self.opens = RollingWindow[float](5)
self.todaysOpen = 0
for bar in history.itertuples():
#for time, price in history.items(): symbol, WAS in tradeBar
#tbar = TradeBar(bar.Index[1], bar.open, bar.high, bar.low, bar.close, bar.volume)
#self.Update(tbar.Open) #Could simply do self.opens.Add(price.Open)
self.opens.Add(bar.open)
def Update(self, price):
self.opens.Add(price)
if self.opens.IsReady:
self.todaysOpen = self.opens[0]
'''Better Version of ^^^^'''
class DailyBars():
'''More efficient version of DailyOpens'''
def __init__(self, history):
self.daily_opens = RollingWindow[float](5)
self.daily_closes = RollingWindow[float](5)
self.daily_highs = RollingWindow[float](5)
self.daily_lows = RollingWindow[float](5)
for time, bar in history.items():
self.Update(bar)
def Update(self, bar):
self.daily_opens.Add(bar.Open)
self.daily_closes.Add(bar.Close)
self.daily_highs.Add(bar.High)
self.daily_lows.Add(bar.Low)
class Momentum():
def __init__(self, history):
self.window = RollingWindow[float](275)
self.mom_yr = 0
self.mom_mo = 0
for row in history.itertuples():
self.Update(row.close)
def Update(self, price):
self.window.Add(price)
if self.window.IsReady:
self.mom_yr = (self.window[25] - self.window[275]) / self.window[275] #Was [-252] and [-25]
self.mom_mo = (self.window[0] - self.window[25]) / self.window[25]
class SymbolData:
def __init__(self, algorithm, symbol):
self.algorithm = algorithm
self.symbol = symbol
# Define daily and monthly rolling windows
self.monthlyWindow = RollingWindow[TradeBar](13)
self.dailyWindow = RollingWindow[TradeBar](280)
# Define daily and monthly consolidators
self.monthlyConsolidator = algorithm.Consolidate(symbol, Calendar.Monthly, self.OnMonthlyData)
self.dailyConsolidator = TradeBarConsolidator(timedelta(days = 1))
# Register daily consolistor to algorithm
algorithm.SubscriptionManager.AddConsolidator(symbol, self.dailyConsolidator)
# Define and register ADX indicator
self.adxThreshold = 25
self.adx = AverageDirectionalIndex(20)
algorithm.RegisterIndicator(symbol, self.adx, self.dailyConsolidator)
# Use historical data to warmup rolling windows, consolidators, and indicators
history = algorithm.History(symbol, 280, Resolution.Daily)
for bar in history.itertuples():
tbar = TradeBar(bar.Index[1], symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
self.dailyWindow.Add(tbar)
self.monthlyConsolidator.Update(tbar)
self.adx.Update(tbar)