| Overall Statistics |
|
Total Trades 19626 Average Win 0.01% Average Loss -0.01% Compounding Annual Return -18.158% Drawdown 18.500% Expectancy -0.228 Net Profit -18.323% Sharpe Ratio -9.047 Probabilistic Sharpe Ratio 0% Loss Rate 58% Win Rate 42% Profit-Loss Ratio 0.83 Alpha -0.18 Beta 0.092 Annual Standard Deviation 0.02 Annual Variance 0 Information Ratio -1.011 Tracking Error 0.159 Treynor Ratio -1.981 Total Fees $43259.78 Estimated Strategy Capacity $14000000.00 Lowest Capacity Asset WST R735QTJ8XC9X |
from System import *
from QuantConnect import *
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Data.Consolidators import TradeBarConsolidator
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Orders import OrderStatus
from QuantConnect.Orders.Fees import AlphaStreamsFeeModel
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Securities import Security, SecurityTransactionManager
from QuantConnect.Orders import *
from QuantConnect.Orders import OrderEvent
from QuantConnect.Orders.Fills import FillModel
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Alphas import Insight
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Selection import *
from datetime import datetime, timedelta
import json
from triple_barrier import TripleBarrier
from pm_config import PM_Config
from pattern_match_client_factory import PatternMatchClientFactory
TICKERS = '''DISCK
EA
FB
TWTR
RCL
WYNN
MCD
LB
RL
PVH
AMZN
TSCO
POOL
MGM
MHK
PENN
LKQ
CPB
SJM
CLX
TAP
MNST
TSN
EOG
SLB
VLO
PXD
GS
MTB
CBOE
L
PFG
TROW
CMA
NDAQ
UNM
C
HIG
ICE
VRTX
PRGO
TFX
PKI
PFE
VAR
WST
DHR
ANTM
ABT
TDOC
BAX
ZBH
MCK
CHRW
LUV
NDSN
SWK
FLS
ROP
CMI
NSC
XYL
ALK
TXT
WM
NOC
SNPS
PEGA
FTNT
MSI
XLNX
ADP
GLW
TER
TXN
SHOP
HPE
MPWR
AMD
PTC
XRX
HUBS
FLT
TEAM
CF
SEE
SHW
NUE
MLM
UDR
CCI
DRE
EQIX
VNO
SO
CMS
D
DTE
SRE
TTWO'''.split()
class OAMPatternMatchingAlgorithm(QCAlgorithm):
VERSION = '3.0.3'
def Initialize(self: QCAlgorithm):
qcAlg: QCAlgorithm = self
tickerFileContents = self.Download(PM_Config.TICKER_CSV_URL)
self.Log(tickerFileContents)
self.tickers = TICKERS[0:95] #tickerFileContents.split()
self.Log(self.tickers)
self.SetStartDate(2018,1,1) #Set Start Date
self.SetEndDate(2019,1,5) #Set End Date
self.SetCash(2000 * 1000) # Set Strategy Cash
self.PROFIT_PCT = 0.01
self.LOSS_PCT = 0.01
self.AddEquity("SPY", Resolution.Minute)
self.SetBenchmark("SPY")
## Set Universe Selection
universeSymbols = [Symbol.Create(t, SecurityType.Equity, Market.USA) for t in self.tickers]
self.UniverseSettings.Resolution = Resolution.Minute
self.SetUniverseSelection(ManualUniverseSelectionModel(universeSymbols))
self.pmc = PatternMatchClientFactory.create(qcAlg=self)
for symbol in universeSymbols:
equity = qcAlg.AddEquity(symbol, Resolution.Minute)
## make 15 min bars from minute bars
tbc = TradeBarConsolidator(timedelta(minutes=15))
tbc.DataConsolidated += self.FifteenMinConsolidator
self.SubscriptionManager.AddConsolidator(symbol, tbc)
## hold all pertinent info for each symbol
NUM_PERIODS_FOR_VWAP = 10
TB = TripleBarrier(qcAlg, symbol, 0, qcAlg.PROFIT_PCT, qcAlg.LOSS_PCT)
TB.vwap = self.VWAP(symbol, NUM_PERIODS_FOR_VWAP)
TB.holdingPeriods = 0
TripleBarrier.SYMBOL_DICTIONARY[symbol] = TB
## Does our broker have any exisiting state (order, positions)
future = self.Time + timedelta(minutes=2)
dt = self.DateRules.On(future)
tm = self.TimeRules.At(future.hour, future.minute)
self.Schedule.On(dt, tm, self.BrokerStateInit)
self.Debug("[Initialize] Initialize Done()")
self.Debug("[Initialize] OAMPatternMatchingAlgorithm VERSION: {}".format(OAMPatternMatchingAlgorithm.VERSION))
self.Debug("[Initialize] Triple Barrier VERSION: {}".format(TripleBarrier.VERSION))
self.Debug("[Initialize] PM Server: {}".format(PM_Config.PM_SERVER_URL))
self.Debug("[Initialize] Ticker Urls {}".format(PM_Config.TICKER_CSV_URL))
self.Debug("[Initialize] Tickers: {}".format(self.tickers))
def BrokerStateInit(self):
TripleBarrier.initFromBrokerState(self, self.PROFIT_PCT, self.LOSS_PCT)
def FifteenMinConsolidator(self: QCAlgorithm, sender, bar: TradeBar):
self.Debug("Consolidated bar: [{} <--> {}], bar = {}".format(bar.Time, bar.EndTime, bar))
if not bar.Symbol in TripleBarrier.SYMBOL_DICTIONARY:
self.Log("15-MIN DATA BUT NO TB -- WAS ALGORITHM REDEPLOYED W/ EXISTING HOLDINGS IN PORTFOLIO")
return
security: Security = self.Securities[bar.Symbol]
TB: TripleBarrier = TripleBarrier.SYMBOL_DICTIONARY[bar.Symbol]
headers = {
"TICKER" : str(bar.Symbol),
"OPEN" : str(round(bar.Open, 2)),
"HIGH" : str(round(bar.High,2)),
"LOW" : str(round(bar.Low,2)),
"CLOSE" : str(round(bar.Close,2)),
"VOLUME" : str(round(bar.Volume,2)),
"VOLWAVG" : str(round(TB.vwap.Current.Value,2)),
"ET" : bar.Time.strftime("%Y-%m-%dT%H:%M:%S"),
"ETE" : bar.Time.strftime("%Y-%m-%d %H:%M:%S")
}
insight: Insight = self.pmc.getInsight(headers, self)
self.Log("{} Insight for {} is {}".format(bar.Time, bar.Symbol, insight.Direction))
# Are we last bar before market close? If so, see you in the morning
# 3:30 ............... 3:45 ............... 4:00pm
# |-------- BAR --------||-------- BAR -------|
#
mktClose: datetime = security.Exchange.Hours.GetNextMarketClose(localDateTime=bar.Time, extendedMarket=False)
timeDeltaUntilClose = mktClose - self.Time
if timeDeltaUntilClose <= timedelta(minutes=10):
self.Debug("Market is closed for {}. Close is {}. It is now {}".format(security, mktClose, self.Time))
return
if security.Invested:
TB.holdingPeriods += 1
self.Log("15-MIN HOLDING PERIODS FOR {} = {}".format(bar.Symbol, TB.holdingPeriods))
if TB.holdingPeriods >= 10:
TB.placeTimeBarrierExitOrder()
TB.holdingPeriods = 0
else:
if insight.Direction == InsightDirection.Up:
weight = round(1.0 / len(self.tickers), 3)
quantity = self.CalculateOrderQuantity(str(bar.Symbol), weight)
TB.placeEntryOrder(quantity)
def OnOrderEvent(self: QCAlgorithm, orderEvent: OrderEvent):
orderId = orderEvent.OrderId
order: Order = self.Transactions.GetOrderById(orderId)
self.Debug("OnOrderEvent: {}, alg time: {}, brokerId: {}".format(order, self.Time, order.BrokerId))
if not orderEvent.Symbol in TripleBarrier.SYMBOL_DICTIONARY:
self.Log("ORDER EVENT BUT NO TB -- WAS ALGORITHM REDEPLOYED W/ EXISTING HOLDINGS IN PORTFOLIO: {}".format(order))
return
TB: TripleBarrier = TripleBarrier.SYMBOL_DICTIONARY[orderEvent.Symbol]
TB.update(order, orderEvent)from System import *
from QuantConnect import *
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Algorithm.Framework.Alphas import InsightDirection
from QuantConnect.Algorithm.Framework.Alphas import Insight
from abc import ABC, abstractmethod
class PatternMatchClient:
def __init__(self, qcAlg: QCAlgorithm) -> None:
self.qcAlg = qcAlg
## This is the primary abstract method implemented by derived classes
@abstractmethod
def getInsight(self, headers, qcAlgorithm: QCAlgorithm) -> Insight:
passfrom System import *
from QuantConnect import *
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Algorithm.Framework.Alphas import InsightDirection
from QuantConnect.Algorithm.Framework.Alphas import Insight
from datetime import timedelta
from pm_config import PM_Config
from pattern_match_client import PatternMatchClient
import pandas as pd
from io import StringIO
## Entry File example naming:
## - AMZN_combined_trade_entries_2018_2019_2020.csv
## Data format
## - '2019-01-07 10:15:00'
class PatternMatchClientEntryFile(PatternMatchClient):
VERSION = '0.0.1'
BASE_ENTRY_FILE_URL = "https://oamdatastorageacct.blob.core.windows.net/pm-entry/combined_entries"
ENTRY_LOOKUP_TABLE = {}
def __init__(self, qcAlg: QCAlgorithm) -> None:
super().__init__(qcAlg)
for t in qcAlg.tickers:
print(t)
url = "{}/{}_combined_trade_entries_2018_2019_2020.csv".format(PatternMatchClientEntryFile.BASE_ENTRY_FILE_URL, t)
csv_str = qcAlg.Download(url)
sio = StringIO(csv_str)
df = pd.read_csv(sio)
df.set_index('trade_entry_index', inplace=True)
PatternMatchClientEntryFile.ENTRY_LOOKUP_TABLE[t] = df
qcAlg.Log("READ ENTRY FILE: {}".format(t))
def getInsight(self, headers, qcAlgorithm: QCAlgorithm):
try:
t = headers["TICKER"]
dt = headers["ETE"]
df = PatternMatchClientEntryFile.ENTRY_LOOKUP_TABLE[t]
bullish_consensus = df.loc[dt]['bull_gt05']
insightDirection = InsightDirection.Flat
if bullish_consensus:
insightDirection = InsightDirection.Up
return Insight.Price(headers["TICKER"], timedelta(minutes=15), insightDirection)
except:
return Insight.Price("DUMMY", timedelta(minutes=15), InsightDirection.Flat)
from QuantConnect.Algorithm import QCAlgorithm
from pattern_match_client import PatternMatchClient
from pattern_match_client_pm_server import PatternMatchClientPmServer
from pattern_match_client_entry_file import PatternMatchClientEntryFile
class PatternMatchClientFactory:
USE_ENTRY_FILES = True
## The Factory Create Method
def create(qcAlg: QCAlgorithm) -> PatternMatchClient:
## Entry File Usage (for backtesting)
if PatternMatchClientFactory.USE_ENTRY_FILES:
return PatternMatchClientEntryFile(qcAlg)
## PM Server Usage (for live and paper trading)
return PatternMatchClientPmServer(qcAlg)from System import *
from QuantConnect import *
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Algorithm.Framework.Alphas import InsightDirection
from QuantConnect.Algorithm.Framework.Alphas import Insight
from datetime import timedelta
from pm_config import PM_Config
from pattern_match_client import PatternMatchClient
import json
class PatternMatchClientPmServer(PatternMatchClient):
VERSION = '2.0.1'
def __init__(self, qcAlg: QCAlgorithm) -> None:
super().__init__(qcAlg)
def create_url(self, headers: dict):
## qs ex: = ?TICKER=AAPL&OPEN=109.2&ET=2021-01-05T10:15:00&HIGH=109.7&LOW=108.2&CLOSE=109.23&VOLUME=20000&VOLWAVG=109.51'
base = PM_Config.PM_SERVER_URL
queryString = "TICKER={}".format(headers["TICKER"])
queryString += "&OPEN={}".format(headers["OPEN"])
queryString += "&HIGH={}".format(headers["HIGH"])
queryString += "&LOW={}".format(headers["LOW"])
queryString += "&CLOSE={}".format(headers["CLOSE"])
queryString += "&VOLUME={}".format(headers["VOLUME"])
queryString += "&VOLWAVG={}".format(headers["VOLWAVG"])
queryString += "&ET={}".format(headers["ET"])
url = "{}?{}".format(base, queryString)
return url
def getInsight(self, headers, qcAlgorithm: QCAlgorithm):
url = self.create_url(headers)
pattern_match_server_response = qcAlgorithm.Download(url)
qcAlgorithm.Debug("{} :: Json response from PM Server: {} with url {}".format(qcAlgorithm.Time, pattern_match_server_response, url))
insightDirection = InsightDirection.Flat
if len(pattern_match_server_response) > 0:
decision = json.loads(pattern_match_server_response)["decision"]
if decision == "BULLISH": insightDirection = InsightDirection.Up
if decision == "NEUTRAL": insightDirection = InsightDirection.Flat
if decision == "BEARISH": insightDirection = InsightDirection.Down
return Insight.Price(headers["TICKER"], timedelta(minutes=15), insightDirection)from QuantConnect import *
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Orders import OrderStatus
from QuantConnect.Algorithm import *
from QuantConnect.Securities import Security, SecurityTransactionManager
from QuantConnect.Orders import *
from QuantConnect.Orders import OrderEvent
from QuantConnect.Orders.Fills import FillModel
from datetime import datetime, timedelta
class PM_Config():
## Stock Universe
DEV_TICKER_CSV_URL = "https://oamdatastorageacct.blob.core.windows.net/pattern-matching/tickers_100.csv"
PROD_TICKER_CSV_URL = "https://oamdatastorageacct.blob.core.windows.net/pattern-matching/tickers_sp500.csv"
## Pattern Matching Server
RANDOM_PM_SERVER_URL = 'https://oam-pattern-matching-server-webapp.azurewebsites.net/randomBullishBearishNeutral'
DEV_PM_SERVER_URL = 'https://oam-pattern-matching-server-webapp-staging.azurewebsites.net/patternMatch'
PROD_PM_SERVER_URL = 'https://oam-pattern-matching-server-webapp.azurewebsites.net/patternMatch'
## TODO: Change these when going live to PROD (Production)
TICKER_CSV_URL = DEV_TICKER_CSV_URL
PM_SERVER_URL = RANDOM_PM_SERVER_URL
from QuantConnect import *
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Orders import OrderStatus
from QuantConnect.Algorithm import *
from QuantConnect.Securities import Security, SecurityTransactionManager
from QuantConnect.Orders import *
from QuantConnect.Orders import OrderEvent
from QuantConnect.Orders import Order
from QuantConnect.Orders.Fills import FillModel
from datetime import datetime, timedelta
import math
class TripleBarrier():
VERSION = '3.0.1'
SYMBOL_DICTIONARY = {}
def initFromBrokerState(qcAlg: QCAlgorithm, profitPct: float, stopLossPct: float, noEntryWithinTimeDeltaToClose=None):
qcAlg.Log("[TB BROKER STATE INIT] SETTING UP TRIPLE BARRIER SYMBOL_DICTIONARY FROM BROKER STATE")
for symbol, security in qcAlg.Securities.items():
if symbol not in TripleBarrier.SYMBOL_DICTIONARY:
qcAlg.Log("[TB BROKER STATE INIT] ADDING TB FOR security: {0}".format(security))
holdingQuantity = qcAlg.Portfolio[symbol].Quantity
TB = TripleBarrier(qcAlg, symbol, holdingQuantity, profitPct, stopLossPct, noEntryWithinTimeDeltaToClose)
TB.enterTime = qcAlg.Time
TripleBarrier.SYMBOL_DICTIONARY[symbol] = TB
openOrders = qcAlg.Transactions.GetOpenOrders()
for oo in openOrders:
o: Order = oo
symbol = o.Symbol
if symbol not in TripleBarrier.SYMBOL_DICTIONARY:
qcAlg.Log("[TB BROKER STATE INIT] OpenOrder, but no TB?? : {0}".format(symbol))
continue
TB: TripleBarrier = TripleBarrier.SYMBOL_DICTIONARY[symbol]
ticket: OrderTicket = qcAlg.Transactions.GetOrderTicket(oo.Id)
if ticket.OrderType == OrderType.Limit:
qcAlg.Log("[TB BROKER STATE INIT] FOUND TAKE PROFIT OpenOrderTicket : {0}".format(ticket))
TB.profitTicket = ticket
if ticket.OrderType == OrderType.StopMarket:
qcAlg.Log("[TB BROKER STATE INIT] FOUND STOP LOSS OpenOrderTicket : {0}".format(ticket))
TB.lossTicket = ticket
def __init__(self, qcAlg: QCAlgorithm, tickerSymbol: Symbol, quantity: float, profitPct: float, stopLossPct: float, noEntryWithinTimeDeltaToClose=None) -> None:
self.qcAlg: QCAlgorithm = qcAlg
self.tickerSymbol = tickerSymbol
self.entryPrice = 0.0
self.quantity = round(quantity, 2)
self.shorting = self.quantity < 0
self.profictPct = profitPct
self.profitTicket = None
self.stopLossPct = stopLossPct
self.lossTicket = None
self.enterTime = datetime.min
self.entryTicket = None
self.noEntryWithinTimeDeltaToClose = noEntryWithinTimeDeltaToClose
self.tag = "DOUBLE-BAR" if (self.stopLossPct == 0 or self.profictPct == 0) else "TRIPLE-BAR"
self.tag += "-{}".format(TripleBarrier.VERSION)
self.log("BARRIER INIT")
def log(self, msg):
self.qcAlg.Log("[{}] {}, {}".format(self.tag, msg, self))
def __str__(self) -> str:
holdingQuantity = self.qcAlg.Portfolio[self.tickerSymbol].Quantity
rval = "["
rval += "sym: {}, requested_quant: {}, current_quant: {}, ".format(self.tickerSymbol, self.quantity, holdingQuantity)
rval += "fill_price: {} tp: {}, sl: {}, ".format(self.entryPrice, self.profictPct, self.stopLossPct)
rval += "enterTime: {}".format(self.enterTime)
rval += "]"
return rval
def placeEntryOrder(self, quantity):
self.quantity = math.floor(quantity)
security: Security = self.qcAlg.Securities[self.tickerSymbol]
# is the mkt open
IS_OPEN = security.Exchange.Hours.IsOpen(self.qcAlg.Time, extendedMarket=False)
if not IS_OPEN:
self.log("EXCHANGE NOT OPEN: NOT ENTERING POSITION WITH OPENING MKT ORDER")
return
## Are we too close to close
if self.noEntryWithinTimeDeltaToClose is not None:
mktClose: datetime = security.Exchange.Hours.GetNextMarketClose(localDateTime=self.qcAlg.Time, extendedMarket=False)
timeDeltaTilClosed = mktClose - self.qcAlg.Time
if timeDeltaTilClosed <= self.noEntryWithinTimeDeltaToClose:
self.log("NOT ENTERING POSITION THIS CLOSE TO MKT CLOSE: {}".format(timeDeltaTilClosed))
return
self.enterTime = self.qcAlg.Time
self.entryTicket = self.qcAlg.MarketOrder(self.tickerSymbol, self.quantity, asynchronous=True, tag="MKT ENTRY")
self.log("PLACED ENTRY ORDER: note: FILL COULD TAKE AWHILE")
def placeTimeBarrierExitOrder(self):
self.log("CANCELING OPEN ORDERS AND PLACING TIME BARRIER MKT EXIT ORDER")
self.qcAlg.Transactions.CancelOpenOrders(self.tickerSymbol, "TIME BARRIER CANCELING ALL OTHER ORDERS")
self.qcAlg.Liquidate(self.tickerSymbol, tag="TIME BARRIER EXIT ORDER")
def placeBarriers(self, price, quantity):
if self.quantity != quantity:
self.qcAlg.Error("QUANTITY MISMATCH ERROR")
if self.quantity > 0:
# LONG - the limit price needs to be above the average purchase price
tp_price = round(price + (self.profictPct * price), 2)
sl_price = round(price - (self.stopLossPct * price), 2)
if self.quantity < 0:
# SHORT - the limit price needs to be below the average purchase price
tp_price = round(price - (self.profictPct * price), 2)
sl_price = round(price + (self.stopLossPct * price), 2)
# submit a take profit limit order - as other order (partial) fills, we need to adjust
if self.profictPct != 0:
self.profitTicket = self.qcAlg.LimitOrder(self.tickerSymbol, -self.quantity, tp_price, "TAKE PROFIT {}".format(self.tickerSymbol))
self.log("TAKE PROFIT ORDER (LMT) SET AT {}".format(tp_price))
# submit stop loss order - as other order (partial) fills, we need to adjust
if self.stopLossPct != 0:
self.lossTicket = self.qcAlg.StopMarketOrder(self.tickerSymbol, -self.quantity, sl_price, "STOP LOSS {}".format(self.tickerSymbol))
self.log("STOP LOSS ORDER (STP-MKT) SET AT {}".format(sl_price))
def update(self, order: Order, orderEvent: OrderEvent):
if orderEvent.Status == OrderStatus.PartiallyFilled:
self.updatePartiallyFilled(order, orderEvent)
if orderEvent.Status == OrderStatus.Filled:
self.updateFullyFilled(order, orderEvent)
def updatePartiallyFilled(self, order: Order, orderEvent: OrderEvent):
holdingQuantity = self.qcAlg.Portfolio[self.tickerSymbol].Quantity
if order.Type == OrderType.Market:
self.log("PARTIALLY FILLED ENTRY OR EXIT (TIME BARRIER) MKT TICKET")
## A mkt order is either the entry or the time-barrier exit - we don't care about partial fills
return
if self.lossTicket is None or self.profitTicket is None:
self.log("NO SIBLING PRICE BARRIER ORDER - PARTIAL FILLS DO NOT REQUIRE UPDATES TO OTHER ORDERS")
return
orderResponse = None
updateOrderFields = UpdateOrderFields()
updateOrderFields.Quantity = -holdingQuantity
if self.lossTicket.OrderId == order.Id and self.profitTicket is not None:
self.log("PARTIALLY FILLED LOSS TICKET - UPDATE TAKE PROFIT TICKET {}")
orderResponse = self.profitTicket.Update(updateOrderFields)
if self.profitTicket.OrderId == order.Id and self.lossTicket is not None:
self.log("PARTIALLY FILLED PROFIT TICKET - UPDATE STOP LOSS TICKET {}")
orderResponse = self.lossTicket.Update(updateOrderFields)
return orderResponse
def updateFullyFilled(self, order: Order, orderEvent: OrderEvent):
symbol = orderEvent.Symbol
security = self.qcAlg.Securities[symbol]
MKT_ENTRY_ORDER_FILLED = order.Type == OrderType.Market and security.Invested
MKT_TIME_BARRIER_ORDER_FILLED = order.Type == OrderType.Market and not security.Invested
PRICE_BARRIER_ORDER_FILLED = order.Type != OrderType.Market
if MKT_ENTRY_ORDER_FILLED:
## If market entry order is now filled place the other orders
self.entryPrice = order.Price
quantity = order.Quantity
self.log("ENTRY ORDER (MKT) FILLED: {}".format(orderEvent))
self.placeBarriers(self.entryPrice, quantity)
if MKT_TIME_BARRIER_ORDER_FILLED:
self.qcAlg.Transactions.CancelOpenOrders(self.tickerSymbol, "TIME BARRIER CANCELING ALL OTHER ORDERS")
self.log("EXIT ORDER (MKT) TIME BARRIER FILLED (WE WILL CANCEL THE PRICE BARRIER ORDERS) {}".format(orderEvent))
if PRICE_BARRIER_ORDER_FILLED:
self.qcAlg.Transactions.CancelOpenOrders(self.tickerSymbol, "PRICE BARRIER FILL CANCELING ALL OTHER ORDERS")
self.log("PRICE BARRIER (TP OR SL) ORDER FILLED (WE CANCELED THE OTHER): {}".format(orderEvent))