Overall Statistics |
Total Trades 444 Average Win 3.01% Average Loss -3.05% Compounding Annual Return 41.443% Drawdown 45.800% Expectancy 0.645 Net Profit 5052.541% Sharpe Ratio 1.119 Probabilistic Sharpe Ratio 40.083% Loss Rate 17% Win Rate 83% Profit-Loss Ratio 0.99 Alpha 0 Beta 0 Annual Standard Deviation 0.371 Annual Variance 0.138 Information Ratio 1.119 Tracking Error 0.371 Treynor Ratio 0 Total Fees $7766.06 Estimated Strategy Capacity $490000.00 |
class HABBRStrategy (QCAlgorithm): def Initialize (self): self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2010, 1, 1) self.SetEndDate(2021, 12, 31) self.SetCash(100000) self.symbols = [ # 'EURUSD','AUDCAD','NZDCHF','EURAUD','NZDCAD','AUDJPY','AUDCHF', # 'GBPCAD','EURJPY','EURCAD','CADCHF','GBPCHF','NZDJPY','USDCHF', # 'CHFJPY','AUDNZD' # 'AUDNZD' 'EURUSD','AUDCHF','AUDJPY','AUDNZD','AUDUSD','CADCHF','CADJPY', 'CHFJPY','EURAUD','EURCAD','EURCHF','EURGBP','EURJPY','EURNZD', 'EURUSD','GBPAUD','GBPCAD','GBPCHF','GBPJPY','GBPNZD','GBPUSD', 'NZDCAD','NZDCHF','NZDJPY','NZDUSD','USDCAD','USDCHF','USDJPY' ] haPeriod = 500 haStdev = 2 rsiPeriod = 20 self.SetWarmUp(max(haPeriod, rsiPeriod)) self.ha = {} self.bb = {} self.rsi = {} self.pb = {} self.overSold = {} self.overBought = {} self.orders = {} # % of BB bandwidth entry above/below limit self.longEntry = 0.382 self.longExit = 1.0 self.shortEntry = 0.618 self.shortExit = 0.0 # % loss before position closed self.lossLimit = -25 for symbol in self.symbols: Symbol = self.AddForex(symbol, Resolution.Daily, Market.Oanda).Symbol self.pb[symbol] = RollingWindow[float](2) self.ha[symbol] = self.HeikinAshi(Symbol) self.bb[symbol] = IndicatorExtensions.Of(self.BB(Symbol, haPeriod, haStdev), self.ha[symbol]) self.bb[symbol].Updated += self.bbUpdated self.rsi[symbol] = self.RSI(Symbol, rsiPeriod) self.overSold[symbol] = False self.overBought[symbol] = False def bbUpdated (self, sender, updated): self.Debug(str(sender)) for symbol in self.symbols: bb = self.bb[symbol] self.pb[symbol].Add(bb.PercentB.Current.Value) def OnData (self, data): for symbol in self.symbols: if self.IsWarmingUp or not ( self.ha[symbol].IsReady or self.bb[symbol].IsReady or self.rsi[symbol].IsReady or self.pb[symbol].IsReady ): return ha = self.ha[symbol] bb = self.bb[symbol] open = ha.Open.Current.Value high = ha.High.Current.Value low = ha.Low.Current.Value close = ha.Close.Current.Value percB = bb.PercentB.Current.Value percB1 = self.pb[symbol][1] rsi = self.rsi[symbol].Current.Value if percB1 < self.longEntry / 2: self.overSold[symbol] = True elif percB1 > (1 - self.shortEntry) / 2 + self.shortEntry: self.overBought[symbol] = True bbVal = str(round(percB, 2)) rsiVal = str(round(rsi, 1)) qty = self.CalculateOrderQuantity(symbol, 1) if not self.Portfolio[symbol].Invested: isLongSignal = self.overSold[symbol] and percB > self.longEntry and rsi < 40 isShortSignal = self.overBought[symbol] and percB < self.shortEntry and rsi > 60 if isLongSignal: self.orders[symbol] = self.MarketOrder(symbol, qty, False, f'ENTER long {bbVal} {rsiVal}') self.overSold[symbol] = False elif isShortSignal: self.orders[symbol] = self.MarketOrder(symbol, -qty, False, f'ENTER short {bbVal} {rsiVal}') self.overBought[symbol] = False else: isLong = self.Portfolio[symbol].IsLong isShort = self.Portfolio[symbol].IsShort direction = 'long' if isLong else 'short' entryPrice = self.orders[symbol].AverageFillPrice currentPrice = data[symbol].Close loss = (currentPrice - entryPrice if isLong else entryPrice - currentPrice) / entryPrice * 100 if loss < self.lossLimit: self.Liquidate(symbol, f'EXIT LOSS {direction} {bbVal} {loss}') elif (isLong and percB > self.longExit) or (isShort and percB < self.shortExit): self.Liquidate(symbol, f'EXIT {direction} {bbVal}')
from datetime import timedelta import numpy as np class HABBRStrategy(QCAlgorithm): def Initialize(self): self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2010, 1, 1) self.SetEndDate(2021, 12, 31) self.SetCash(100000) self.symbols = [ # 'AUDCAD' 'AUDCAD','AUDCHF','AUDJPY','AUDNZD','AUDUSD','CADCHF','CADJPY', 'CHFJPY','EURAUD','EURCAD','EURCHF','EURGBP','EURJPY','EURNZD', 'EURUSD','GBPAUD','GBPCAD','GBPCHF','GBPJPY','GBPNZD','GBPUSD', 'NZDCAD','NZDCHF','NZDJPY','NZDUSD','USDCAD','USDCHF','USDJPY' ] n = 500 self.SetWarmUp(n) self.ha = {} self.bb = {} self.rsi = {} self.windowBBPercB = {} self.overSold = {} self.overBought = {} self.orders = {} # % of BB bandwidth entry above/below limit self.longEntry = 0.382 self.longExit = 1.0 self.shortEntry = 0.618 self.shortExit = 0.0 for symbol in self.symbols: self.AddForex(symbol, Resolution.Daily, Market.Oanda) self.ha[symbol] = self.HeikinAshi(symbol) self.bb[symbol] = IndicatorExtensions.Of(self.BB(symbol, n, 2), self.ha[symbol]) self.bb[symbol].Updated += self.bbUpdated self.rsi[symbol] = self.RSI(symbol, 20) self.overSold[symbol] = False self.overBought[symbol] = False self.windowBBPercB[symbol] = RollingWindow[float](2) def bbUpdated (self, sender, updated): for symbol in self.symbols: bb = self.bb[symbol] self.windowBBPercB[symbol].Add(bb.PercentB.Current.Value) def OnData (self, data): if self.IsWarmingUp: return for symbol in self.symbols: ha = self.ha[symbol] bb = self.bb[symbol] open = ha.Open.Current.Value high = ha.High.Current.Value low = ha.Low.Current.Value close = ha.Close.Current.Value percB = bb.PercentB.Current.Value percB1 = self.windowBBPercB[symbol][1] rsi = self.rsi[symbol].Current.Value self.Debug(rsi) if percB1 < self.longEntry / 2: self.overSold[symbol] = True elif percB1 > (1 - self.shortEntry) / 2 + self.shortEntry: self.overBought[symbol] = True bbVal = str(round(percB, 2)) rsiVal = str(round(rsi, 1)) qty = self.CalculateOrderQuantity(symbol, 1) if not self.Portfolio[symbol].Invested: isLongSignal = self.overSold[symbol] and percB > self.longEntry and rsi < 40 isShortSignal = self.overBought[symbol] and percB < self.shortEntry and rsi > 60 if isLongSignal: self.orders[symbol] = self.MarketOrder(symbol, qty, False, f'ENTER long {bbVal} {rsiVal}') self.overSold[symbol] = False elif isShortSignal: self.orders[symbol] = self.MarketOrder(symbol, -qty, False, f'ENTER short {bbVal} {rsiVal}') self.overBought[symbol] = False else: isLong = self.Portfolio[symbol].IsLong isShort = self.Portfolio[symbol].IsShort direction = 'long' if isLong else 'short' entryPrice = self.orders[symbol].AverageFillPrice currentPrice = data[symbol].Close loss = (currentPrice - entryPrice if isLong else entryPrice - currentPrice) / entryPrice * 100 if loss < -25: self.Liquidate(symbol, f'EXIT LOSS {direction} {bbVal}') elif (isLong and percB > self.longExit) or (isShort and percB < self.shortExit): self.Liquidate(symbol, f'EXIT {direction} {bbVal}')
from datetime import datetime import decimal import numpy as np # Heikin Ashi Bollinger Bands Reversion (HABBR) Strategy class HABBR (QCAlgorithm): def Initialize (self): # self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2020, 10, 1) self.SetEndDate(2021, 12, 31) self.SetCash(100000) # available pairs for modelling # AUDCAD, AUDCHF, AUDJPY, AUDNZD, AUDUSD, CADCHF, CADJPY # CHFJPY, EURAUD, EURCAD, EURCHF, EURGBP, EURJPY, EURNZD # EURUSD, GBPAUD, GBPCAD, GBPCHF, GBPJPY, GBPNZD, GBPUSD # NZDCAD, NZDCHF, NZDJPY, NZDUSD, USDCAD, USDCHF, USDJPY fx = self.AddForex('AUDCAD', Resolution.Hour, Market.Oanda) self.syl = fx.Symbol self.Schedule.On(self.DateRules.EveryDay(self.syl), self.TimeRules.BeforeMarketClose(self.syl, 1), Action(self.SetSignal)) self.overBought, self.overSold = False, False self.SetBenchmark(self.syl) self.Bolband = self.BB(self.syl, 20, 2, MovingAverageType.Simple, Resolution.Daily) def OnData (self, data): close = self.History(self.syl, 1, Resolution.Daily)['close'] self.yesterdayclose = close.iloc[-1] # wait for our BollingerBand to fully initialize if not self.Bolband.IsReady: return holdings = self.Portfolio[self.syl].Quantity if self.yesterdayclose > self.Bolband.UpperBand.Current.Value: self.overBought = True self.overSold = False elif self.yesterdayclose < self.Bolband.LowerBand.Current.Value: self.overSold = True self.overBought = False if self.overBought and self.yesterdayclose < self.Bolband.MiddleBand.Current.Value: self.SetHoldings(self.syl, -1) self.overBought = False elif self.overSold and self.yesterdayclose > self.Bolband.MiddleBand.Current.Value: self.SetHoldings(self.syl, 1) self.overSold = False if holdings > 0 and self.yesterdayclose < self.Bolband.MiddleBand.Current.Value: self.Liquidate(self.syl) elif holdings < 0 and self.yesterdayclose > self.Bolband.MiddleBand.Current.Value: self.Liquidate(self.syl)
import decimal as d import numpy as np class heikinAshiExample(QCAlgorithm): def Initialize(self): self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2019, 1, 1) self.SetEndDate(2020, 12, 31) self.SetCash(100000) self.SetWarmUp(20) self.symbols = [ 'AUDCAD','AUDCHF','AUDJPY','AUDNZD','AUDUSD','CADCHF','CADJPY', 'CHFJPY','EURAUD','EURCAD','EURCHF','EURGBP','EURJPY','EURNZD', 'EURUSD','GBPAUD','GBPCAD','GBPCHF','GBPJPY','GBPNZD','GBPUSD', 'NZDCAD','NZDCHF','NZDJPY','NZDUSD','USDCAD','USDCHF','USDJPY' ] self.ha = {} self.bb = {} self.windowHAClose = {} self.windowBBUpper = {} self.windowBBMiddle = {} self.windowBBLower = {} self.overSold = {} self.overBought = {} self.consolidators = {} # % of BB bandwitdh for stop loss/entry above/below limit # self.longStopLoss = -0.20 self.longEntry = 0.4 self.longExit = 1.0 # self.shortStopLoss = 1.20 self.shortEntry = 0.6 self.shortExit = 0.0 for symbol in self.symbols: Symbol = self.AddForex(symbol, Resolution.Hour, Market.Oanda).Symbol self.ha[symbol] = self.HeikinAshi(Symbol, Resolution.Daily) self.bb[symbol] = IndicatorExtensions.Of( self.BB(Symbol, 20, 2, MovingAverageType.Simple, Resolution.Daily), self.ha[symbol] ) self.overSold[symbol] = False self.overBought[symbol] = False self.ha[symbol].Updated += self.haUpdated self.bb[symbol].Updated += self.bbUpdated self.windowHAClose[symbol] = RollingWindow[float](3) self.windowBBUpper[symbol] = RollingWindow[float](3) self.windowBBMiddle[symbol] = RollingWindow[float](3) self.windowBBLower[symbol] = RollingWindow[float](3) ## Oanda Forex opens 17:00 Sunday, closes Friday 17:00 self.Schedule.On(self.DateRules.On(2019, 1, 1), self.TimeRules.At(17, 0), self.DailyConsolidator) # ================================================================================================================== def DailyConsolidator (self): for symbol in self.symbols: self.consolidators[symbol] = QuoteBarConsolidator(24) # 24 hours | 1440 minutes | 86400 seconds self.consolidators[symbol].DataConsolidated += self.OnDailyData self.SubscriptionManager.AddConsolidator(symbol, self.consolidators[symbol]) # ================================================================================================================== def haUpdated (self, sender, updated): for symbol in self.symbols: ha = self.ha[symbol] self.windowHAClose[symbol].Add(ha.Close.Current.Value) # ================================================================================================================== def bbUpdated (self, sender, updated): for symbol in self.symbols: bb = self.bb[symbol] self.windowBBUpper[symbol].Add(bb.UpperBand.Current.Value) self.windowBBMiddle[symbol].Add(bb.MiddleBand.Current.Value) self.windowBBLower[symbol].Add(bb.LowerBand.Current.Value) # ================================================================================================================== def OnDailyData (self, sender, consolidated): if self.IsWarmingUp: return for symbol in self.symbols: open = self.ha[symbol].Open.Current.Value high = self.ha[symbol].High.Current.Value low = self.ha[symbol].Low.Current.Value close = self.ha[symbol].Close.Current.Value close1 = self.windowHAClose[symbol][1] close2 = self.windowHAClose[symbol][2] upper = self.bb[symbol].UpperBand.Current.Value upper1 = self.windowBBUpper[symbol][1] upper2 = self.windowBBUpper[symbol][2] middle = self.bb[symbol].MiddleBand.Current.Value lower = self.bb[symbol].LowerBand.Current.Value lower1 = self.windowBBLower[symbol][1] lower2 = self.windowBBLower[symbol][2] bbPercentBandwidth = (close - lower) / (upper - lower) bbPercentBandwidth1 = (close1 - lower1) / (upper1 - lower1) bbPercentBandwidth2 = (close2 - lower2) / (upper2 - lower2) # two preceding bars close outside BB range if bbPercentBandwidth2 < 0 and bbPercentBandwidth1 < self.longEntry / 2 and bbPercentBandwidth < self.longEntry: self.overSold[symbol] = True elif bbPercentBandwidth2 > 1 and bbPercentBandwidth1 > (1 - self.shortEntry) / 2 + self.shortEntry and bbPercentBandwidth > self.shortEntry: self.overBought[symbol] = True if not self.Portfolio[symbol].Invested: qty = self.Portfolio.TotalPortfolioValue # longStopLoss = round(lower + lower * self.longStopLoss, 3) # shortStopLoss = round(lower + lower * self.shortStopLoss, 3) # LONG entry if self.overSold[symbol] and bbPercentBandwidth > self.longEntry: self.MarketOrder(symbol, qty, False, 'ENTER long') # self.StopMarketOrder(symbol, -qty, longStopLoss, 'EXIT stop loss') self.overSold[symbol] = False # SHORT entry elif self.overBought[symbol] and bbPercentBandwidth < self.shortEntry: self.MarketOrder(symbol, -qty, False, 'ENTER short') # self.StopMarketOrder(symbol, qty, shortStopLoss, 'EXIT stop loss') self.overBought[symbol] = False else: is_long = self.Portfolio[symbol].IsLong is_short = self.Portfolio[symbol].IsShort if is_long and bbPercentBandwidth > self.longExit: self.Liquidate(symbol, 'EXIT long') # self.Transactions.CancelOpenOrders(symbol, 'Cancel limits/stop losses') elif is_short and bbPercentBandwidth < self.shortExit: self.Liquidate(symbol, 'EXIT short') # self.Transactions.CancelOpenOrders(symbol, 'Cancel limits/stop losses') # ================================================================================================================== def OnData (self, data): pass # ================================================================================================================== def OnOrderEvent (self, OrderEvent): order = self.Transactions.GetOrderById(OrderEvent.OrderId) symbol = OrderEvent.Symbol # self.Debug(f'{OrderEvent}') # if OrderEvent.Status == OrderStatus.Filled: # if order.Type == OrderType.Limit: # self.Transactions.CancelOpenOrders(symbol, 'Cancel stop loss') # if order.Type == OrderType.StopMarket: # self.Transactions.CancelOpenOrders(symbol, 'Cancel limit') # ==================================================================================================================
import decimal as d import numpy as np class heikinAshiExample(QCAlgorithm): def Initialize(self): self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2017, 1, 1) self.SetEndDate(2018, 12, 31) self.SetCash(100000) self.SetWarmUp(20) self.symbols = [ 'EURNZD' # 'AUDCAD','AUDCHF','AUDJPY','AUDNZD','AUDUSD','CADCHF','CADJPY' # 'CHFJPY','EURAUD','EURCAD','EURCHF','EURGBP','EURJPY','EURNZD' # 'EURUSD','GBPAUD','GBPCAD','GBPCHF','GBPJPY','GBPNZD','GBPUSD' # 'NZDCAD','NZDCHF','NZDJPY','NZDUSD','USDCAD','USDCHF','USDJPY' ] self.ha = {} self.bb = {} self.windowHAClose = {} self.windowBBUpper = {} self.windowBBMiddle = {} self.windowBBLower = {} self.overSold = {} self.overBought = {} # % of BB bandwidth entry above/below limit self.longEntry = 0.4 self.longExit = 1.0 self.shortEntry = 0.6 self.shortExit = 0.0 for symbol in self.symbols: Symbol = self.AddForex(symbol, Resolution.Daily, Market.Oanda).Symbol self.ha[symbol] = self.HeikinAshi(Symbol, Resolution.Daily) self.bb[symbol] = IndicatorExtensions.Of( self.BB(Symbol, 20, 2, MovingAverageType.Simple, Resolution.Daily), self.ha[symbol] ) self.overSold[symbol] = False self.overBought[symbol] = False self.ha[symbol].Updated += self.haUpdated self.windowHAClose[symbol] = RollingWindow[float](3) self.windowBBUpper[symbol] = RollingWindow[float](3) self.windowBBMiddle[symbol] = RollingWindow[float](3) self.windowBBLower[symbol] = RollingWindow[float](3) def haUpdated (self, sender, updated): for symbol in self.symbols: ha = self.ha[symbol] bb = self.bb[symbol] self.windowHAClose[symbol].Add(ha.Close.Current.Value) self.windowBBUpper[symbol].Add(bb.UpperBand.Current.Value) self.windowBBMiddle[symbol].Add(bb.MiddleBand.Current.Value) self.windowBBLower[symbol].Add(bb.LowerBand.Current.Value) def OnData (self, data): if self.IsWarmingUp: return for symbol in self.symbols: open = self.ha[symbol].Open.Current.Value high = self.ha[symbol].High.Current.Value low = self.ha[symbol].Low.Current.Value close = self.ha[symbol].Close.Current.Value close1 = self.windowHAClose[symbol][1] close2 = self.windowHAClose[symbol][2] upper = self.bb[symbol].UpperBand.Current.Value upper1 = self.windowBBUpper[symbol][1] upper2 = self.windowBBUpper[symbol][2] middle = self.bb[symbol].MiddleBand.Current.Value lower = self.bb[symbol].LowerBand.Current.Value lower1 = self.windowBBLower[symbol][1] lower2 = self.windowBBLower[symbol][2] bbPercentBandwidth = (close - lower) / (upper - lower) bbPercentBandwidth1 = (close1 - lower1) / (upper1 - lower1) bbPercentBandwidth2 = (close2 - lower2) / (upper2 - lower2) if bbPercentBandwidth2 < 0 and bbPercentBandwidth1 < self.longEntry / 2 and bbPercentBandwidth < self.longEntry: self.overSold[symbol] = True elif bbPercentBandwidth2 > 1 and bbPercentBandwidth1 > (1 - self.shortEntry) / 2 + self.shortEntry and bbPercentBandwidth > self.shortEntry: self.overBought[symbol] = True if not self.Portfolio[symbol].Invested: # LONG entry if self.overSold[symbol] and bbPercentBandwidth > self.longEntry: self.SetHoldings(symbol, 1) # self.MarketOrder(symbol, qty, False, 'ENTER long') self.overSold[symbol] = False # SHORT entry elif self.overBought[symbol] and bbPercentBandwidth < self.shortEntry: self.SetHoldings(symbol, -1) # self.MarketOrder(symbol, -qty, False, 'ENTER short') self.overBought[symbol] = False else: if self.Portfolio[symbol].IsLong and (bbPercentBandwidth > self.longExit): self.Liquidate(symbol, 'EXIT long') elif self.Portfolio[symbol].IsShort and (bbPercentBandwidth < self.shortExit): self.Liquidate(symbol, 'EXIT short')
from datetime import timedelta import numpy as np class HABBRStrategy(QCAlgorithm): def Initialize(self): self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2021, 1, 1) self.SetEndDate(2021, 12, 31) self.SetCash(100000) self.SetWarmUp(125) self.symbols = [ # 'CADJPY' 'AUDCAD','AUDCHF','AUDJPY','AUDNZD','AUDUSD','CADCHF','CADJPY', 'CHFJPY','EURAUD','EURCAD','EURCHF','EURGBP','EURJPY','EURNZD', 'EURUSD','GBPAUD','GBPCAD','GBPCHF','GBPJPY','GBPNZD','GBPUSD', 'NZDCAD','NZDCHF','NZDJPY','NZDUSD','USDCAD','USDCHF','USDJPY' ] self.ha = {} self.bb = {} self.windowHAClose = {} self.windowBBUpper = {} self.windowBBLower = {} self.overSold = {} self.overBought = {} self.orders = {} # % of BB bandwidth entry above/below limit self.longEntry = 0.382 self.longExit = 1.0 self.shortEntry = 0.618 self.shortExit = 0.0 for symbol in self.symbols: self.AddForex(symbol, Resolution.Daily, Market.Oanda) self.ha[symbol] = self.HeikinAshi(symbol) self.ha[symbol].Updated += self.haUpdated self.bb[symbol] = IndicatorExtensions.Of(self.BB(symbol, 125, 2), self.ha[symbol]) self.overSold[symbol] = False self.overBought[symbol] = False self.windowHAClose[symbol] = RollingWindow[float](3) self.windowBBUpper[symbol] = RollingWindow[float](3) self.windowBBLower[symbol] = RollingWindow[float](3) def haUpdated (self, sender, updated): for symbol in self.symbols: ha = self.ha[symbol] bb = self.bb[symbol] self.windowHAClose[symbol].Add(ha.Close.Current.Value) self.windowBBUpper[symbol].Add(bb.UpperBand.Current.Value) self.windowBBLower[symbol].Add(bb.LowerBand.Current.Value) def OnData (self, data): if self.IsWarmingUp: return for symbol in self.symbols: ha = self.ha[symbol] bb = self.bb[symbol] open = ha.Open.Current.Value high = ha.High.Current.Value low = ha.Low.Current.Value close = ha.Close.Current.Value upper = bb.UpperBand.Current.Value lower = bb.LowerBand.Current.Value close1 = self.windowHAClose[symbol][1] upper1 = self.windowBBUpper[symbol][1] lower1 = self.windowBBLower[symbol][1] bbPercentBandwidth = (close - lower) / (upper - lower) bbPercentBandwidth1 = (close1 - lower1) / (upper1 - lower1) if bbPercentBandwidth1 < self.longEntry / 2 and bbPercentBandwidth < self.longEntry: self.overSold[symbol] = True elif bbPercentBandwidth1 > (1 - self.shortEntry) / 2 + self.shortEntry and bbPercentBandwidth > self.shortEntry: self.overBought[symbol] = True bbVal = str(round(bbPercentBandwidth, 2)) qty = self.CalculateOrderQuantity(symbol, 0.2) if not self.Portfolio[symbol].Invested: if self.overSold[symbol] and bbPercentBandwidth > self.longEntry: # LONG entry self.orders[symbol] = self.MarketOrder(symbol, qty, False, f'ENTER long {bbVal}') self.overSold[symbol] = False elif self.overBought[symbol] and bbPercentBandwidth < self.shortEntry: # SHORT entry self.orders[symbol] = self.MarketOrder(symbol, -qty, False, f'ENTER short {bbVal}') self.overBought[symbol] = False else: isLong = self.Portfolio[symbol].IsLong isShort = self.Portfolio[symbol].IsShort entryPrice = self.orders[symbol].AverageFillPrice currentPrice = data[symbol].Close if isLong and bbPercentBandwidth > self.longExit: self.Liquidate(symbol, f'EXIT long {bbVal}') elif isShort and bbPercentBandwidth < self.shortExit: self.Liquidate(symbol, f'EXIT short {bbVal}')