Re: Cancel Order
Hello @backtrader. Self.cancel() doesn't seem to work in my strategy class. Can you help me check what I have implemented wrongly.
CODE:
import backtrader as bt
from backtrader import indicators as ind
from collections import deque
from utils.tv_functions import na, nz, ternary
from indicators import StGrab, AtrTrailStop, HullSuite, Halftrend, PPS, HtfEma
import random
class ParthStrategy(bt.Strategy):
lines = ('sl',)
def __init__(self):
self.data_0 = self.datas[0]
self.data_240 = self.datas[1]
# Indicators
self.stgrab = StGrab(self.data_240)
self.htfema = HtfEma(self.data_240)
self.hull_suite = HullSuite(self.data_240)
self.halftrend = Halftrend(self.data_0)
self.pps = PPS(self.data_0)
self.ats = AtrTrailStop(self.data_0)
# Variables
self.window_cond_hull = deque([], maxlen=500)
self.window_cond_touch_line = deque(['False', 'False'], maxlen=2)
self.pend_long = False
self.sl = bt.LineNum(float('nan'))
# Strategy Variables
self.order_entry = None
self.order_close = None
self.order_cancel = None
self.active_trade = None
self.active_trail = None
self.trade_count = 0
def log(self, _text, dt=None):
dt = dt or self.datas[0].datetime.datetime(0)
print(f'{dt.strftime("%Y-%m-%d %H:%M:%S")} : {_text}')
def next(self):
bar = self.data_0
# region ----- CONDITIONS
# St Grab
cond_above_st = bar.close[0] > self.stgrab.lines.ema_high[0]
cond_below_st = bar.close[0] < self.stgrab.lines.ema_low[0]
# HTF EMAs
cond_ema_long = (self.htfema.lines.ema_1[0] > self.htfema.lines.ema_2[0]) and (self.htfema.lines.ema_2[0] > self.htfema.lines.ema_3[0])
# Hull Suite
_hull_long = self.hull_suite.lines.hull[0] > self.hull_suite.lines.shull[0]
self.window_cond_hull.appendleft(_hull_long)
cond_hull_long = any(self.window_cond_hull)
# Halftrend
cond_ht_long = (not na(self.halftrend.lines.arrowUp[0])) and self.halftrend.lines.trend[0] == 0 and self.halftrend.lines.trend[-1] == 1
cond_ht_short = (not na(self.halftrend.lines.arrowDown[0])) and self.halftrend.lines.trend[0] == 1 and self.halftrend.lines.trend[-1] == 0
# ATR Trailing Stop
cond_ats_long = self.ats.lines.cond_ats_long[0]
cond_ats_short = self.ats.lines.cond_ats_short[0]
sl_line = \
ternary((bar.close[0] > self.pps.l.Trailingsl[0]) and (bar.close[0] > self.ats.l.xATRTrailingStop),
ternary((abs(bar.close[0] - self.pps.l.Trailingsl[0]) < abs(bar.close[0] - self.ats.l.xATRTrailingStop)), self.pps.l.Trailingsl[0], self.ats.l.xATRTrailingStop),
ternary((bar.close[0] > self.pps.l.Trailingsl[0]), self.pps.l.Trailingsl[0], self.ats.l.xATRTrailingStop))
cond_touch_line = bar.high[0] >= sl_line and bar.low[0] <= sl_line
self.window_cond_touch_line.append(cond_touch_line)
if self.window_cond_touch_line[0] and not self.window_cond_touch_line[1]:
self.sl[0] = sl_line - ((.45/100) * sl_line)
# endregion
# region ----- ENTRY
if (not self.pend_long) and (cond_ht_long and cond_above_st ) and (self.position.size == 0) and (cond_ats_long): # Halftrend Long Signal, while Price Above Halftrend, and Halftrend above ST_GRaB
self.pend_long = True
self.order_entry = self.buy(bar, price=bar.high, exectype=bt.Order.Stop) # strategy.entry('Buy', strategy.long, stop=high, comment = i_message_enter)
self.log(f'<--- buy order sent ({bar.high[0]})--->')
if self.pend_long and self.order_entry and (self.position.size == 0):
# Cancel Pending Orders
if (cond_ht_short or cond_ats_short or (not cond_hull_long) or (not cond_ema_long)):
# Cancel Buy Sequence If:
# - Short Signal from Halftrend
# - Current Price is below the ATR Line
# - No Buy Signal from Hull Suite in the last 500 bars
# - 4-hour EMA not in the right order, and MAPD is not within 4 and -4
self.pend_long = False
self.broker.cancel(self.order_entry) # strategy.cancel('Buy')
self.log(f'<--- cancel buy order sent --->')
self.sell(exectype=bt.Order.Stop, price=0.1, size=0)
# endregion
# region ----- EXIT
if self.position.size > 0:
self.pend_long = False
# MANUALLY MONITOR TRAILING STOP EXIT :
if (bar.low[0] <= self.sl[0]) and (bar.low[-1] > self.sl[-1]):
self.close()
self.log('<--- exit buy order sent : trailing stop triggered --->')
if cond_ats_short:
self.close()
self.log('<--- close buy signal sent : price below atr line --->')
# endregion
def notify_order(self, order):
bar = self.data_0
if order.status in [order.Accepted]:
self.log(f'<--- order recieved --->')
return
# Check if an order has been completed
# Attention: broker could reject order if not enough cash
if order.status in [order.Completed]:
if order.isbuy():
pass
elif order.issell():
pass
elif order.status == order.Cancelled:
self.log(f'--- Cancel Buy Signal Sent (Confirmed)')
# elif order.issell():
# self.log('--- Stop Loss Updated (Confirmed)')
# elif order.status in [order.Margin, order.Rejected]:
# self.log('ERROR: Order Margin/Rejected')
# self.pend_long = False
# self.order_entry = None
# self.trade_active = None
def notify_trade(self, trade):
if trade.justopened and trade.size > 0:
self.log(f'TRADE EXECUTED at {trade.price: .2f}')
if trade.isclosed:
self.log(f'TRADE CLOSED at {trade.price: .2f}')
self.trade_count += 1
def stop(self):
print('Trades Completed : ', self.trade_count)