Simultaneous bracket order - Cancel one when another has been submitted & accepted
-
I'm trying to enter both a long and a short bracket order with target price, take profit, and stop loss... simultaneously
For long: Limit order +1 pip from current price. Stop loss -1 pip from current price. And take profit of +5 pip of from current price.
For short, exact reverse.
Here's the picture
When one of the two bracket orders get filled (at target price), i'd like to cancel the other one.
Here's the logic for entering the 2 simultaneous orders:
def next(self): current_tick = {} current_tick["close"] = self.datas[0].close[0] current_tick["volume"] = self.datas[0].volume[0] current_tick["date"] = self.datas[0].datetime.date() current_tick["time"] = self.datas[0].datetime.time() if(self.entrysig): order_size =get_size( currency_to_trade=self.p.currency, leverage=self.p.leverage, max_loss_per_trade=0.01, total_cash=self.broker.get_cash(), at_datetime =self.datas[0].datetime.datetime(0), default_value = self.datas[0].close[0] ) long_order = { "direction" : "long", "order_placed_at" : len(self), "order_placed_at_datetime" : current_tick["date"], "target_price" : self.datas[0].close + self.distance_entry, "take_profit" : self.datas[0].close + self.distance_tp, "stop_loss" : self.datas[0].close - self.distance_sl #"valid" : terminate_order } long_bracket = { "limitprice": float('%.4f' % long_order["take_profit"]), "price" : float('%.4f' % long_order["target_price"]), "stopprice" : float('%.4f' % long_order["stop_loss"]), "addinfo" : "long", "size" : order_size, #"exectype" : bt.Order.Market #"valid" : terminate_order } self.order_pairs["long"] = self.buy_bracket(**long_bracket) short_order = { "direction" : "short", "order_placed_at" : len(self), "order_placed_at_datetime" : current_tick["date"], "target_price" : self.datas[0].close - self.distance_entry, "take_profit" : self.datas[0].close - self.distance_tp, "stop_loss" : self.datas[0].close + self.distance_sl #"valid" : terminate_order } short_bracket = { "limitprice": float('%.4f' % short_order["take_profit"]), "price" : float('%.4f' % short_order["target_price"]), "stopprice" : float('%.4f' % short_order["stop_loss"]), "addinfo" : "short", "size" : order_size, #"exectype" : bt.Order.Market #"valid" : terminate_order } self.order_pairs["short"] = self.sell_bracket(**short_bracket)
Here's the logic for cancelling the other
def notify_order(self, order): logging.info('[NOTIFY_ORDER {}] ORDER {} - {}'.format(len(self), order.Status[order.status], order.tradeid)) if order.status in [order.Submitted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do return if order.status in [order.Accepted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do self.total_played+=1 if(order.isbuy()): self.went_long+=1 if(order.issell()): self.went_short+=1 order_addinfo = dict(order.info) if(order_addinfo["addinfo"] == "long"): if(self.order_pairs["short"] is not None): for order in self.order_pairs["short"]: self.cancel(order) self.order_pairs["short"] = None if(order_addinfo["addinfo"] == "short"): if(self.order_pairs["long"] is not None): for order in self.order_pairs["long"]: self.cancel(order) self.order_pairs["long"] = None return if order.status in [order.Expired, order.Cancelled, order.Rejected]: pass if order.status in [order.Completed]: order_type = "buy" if( order.isbuy() ) else "sell" logging.info('[NOTIFY_ORDER {}] {} ORDER EXECUTED [{}], Size: {}, Price: {}, Cost: {}, Comm {}'.format( len(self), order_type.upper(), order.ref, order.executed.size, order.executed.price, order.executed.value, order.executed.comm))
For some reason, all the orders seem to be getting in but also getting out at exact same bar
Where am I going wrong?
-
Your
distance_entry
is unknown. But it would seem if is possibly small enough so that both orders get executed within the range of the same bar.If you activate
quicknotify
inCerebro
you would get a chance to act in between orders, be it the case. -
Oh oops, sorry about that
distance_sl = 0.0003 distance_entry=0.0001 distance_tp=0.0006
I tried widening the values just to see if the volatility was triggering both... even up to:
distance_sl = 0.00010 distance_entry=0.0005 distance_tp=0.0020
But it seems that all the orders are getting bought/sold at exact same time
[INFO] 14:21:32 [NOTIFY_ORDE] BUY ORDER EXECUTED [151], Size: 8814.339166956806, Price: 1.142125, Cost: 10067.077121060544, Comm 0.0 [INFO] 14:21:32 [NOTIFY_ORDE] ORDER Completed - 0 [INFO] 14:21:32 [NOTIFY_ORDER] SELL ORDER EXECUTED [154], Size: -8814.339166956806, Price: 1.142125, Cost: 10067.077121060544, Comm 0.0 [INFO] 14:21:32 [NOTIFY_TRADE] OPERATION PROFIT, GROSS 0.00, NET 0.00 [INFO] 14:21:32 [NOTIFY_TRADE] OPERATION PROFIT, GROSS 0.00, NET 0.00
-
Why cancel? you can totally profit from both of those brackets if something fluctuates up and down intraday =)
-
@Taewoo-Kim said in Simultaneous bracket order - Cancel one when another has been submitted & accepted:
logging.info('[NOTIFY_ORDER {}] ORDER {} - {}'.format(len(self), order.Status[order.status], order.tradeid))
It would seem that you are executing with
Market
and both orders take the closing price the. Since the code posted is not the code executing, it may be that your execution run did so.See for example. Code
logging.info('[NOTIFY_ORDER {}] ORDER {} - {}'.format(len(self), order.Status[order.status], order.tradeid))
Output
[INFO] 14:21:32 [NOTIFY_ORDE] ORDER Completed - 0
The printout doesn't match the
logging.info
statement. It seems the code may have correct to account for the typo and not printing thelen
. With that in mind the following could have also not been commented during execution:#"exectype" : bt.Order.Market
In any case the cancelling is donde at the wrong place. It's been done here
if order.status in [order.Accepted]:
Which only means the broker has accepted the order because there is enough cash to execute it.
Additionally: in the case of a bracket order, there is no need to cancel the 3 orders. Cancelling just the main order will already cancel the bracket.
-
In any case the cancelling is donde at the wrong place. It's been done here
if order.status in [order.Accepted]:
Which only means the broker has accepted the order because there is enough cash to execute it.
So where does this need to go? Which status?
-
You said you want to cancel if the order has been filled.
Accepted
means that the broker has taken it (as opposed for example toMargin
when you don't have enough cash)During backtesting and unless you are playing with volume filling strategies the notification of an order being filled will happen with
Order.Completed
-
im having trouble having BT cancel one of the bracket orders when the other bracket order is converted into a position... here's what i've tried
- putting the order.cancel in order. accepted / submitted
- set exectype as bt.Order.StopLimit / bt.Order.Limit
Still, all the orders are cancelling each other out simultaneously.
Questions:
- When the "main" order of a bracket order is converted into a position, how is BT notified? via notify_order or notify_trade?
- Is there a sample code that achieves what I'm trying to do? I am trying to
- place simultaeous long and short bracket order, both of which are X pips away
- close one set of bracket orders when the other set of bracket orders (i.e. the main order of that other bracket order set) has been filled
-
@Taewoo-Kim said in Simultaneous bracket order - Cancel one when another has been submitted & accepted:
- putting the order.cancel in order. accepted / submitted
As stated in the answer above. The right place is
Completed
. Using any of the ones mentioned above guarantees that you will be cancelling the other bracket immediately, yes or yes (unless there isn't cash enough and you receive aMargin
)@Taewoo-Kim said in Simultaneous bracket order - Cancel one when another has been submitted & accepted:
Still, all the orders are cancelling each other out simultaneously.
Probably due to the fact that you are cancelling them immediately upon receiving
Accepted
orSubmitted
as stated above.@Taewoo-Kim said in Simultaneous bracket order - Cancel one when another has been submitted & accepted:
- When the "main" order of a bracket order is converted into a position, how is BT notified? via notify_order or notify_trade?
A position is your current status in an asset. An order is not converted to a position. The results of the execution are applied to the current position.
Orders are always notified via
notify_order
, hence the name. Docs - Strategy / notify_order@Taewoo-Kim said in Simultaneous bracket order - Cancel one when another has been submitted & accepted:
- Is there a sample code that achieves what I'm trying to do? I am trying to
Not in the samples.