Execute trade immediatly after a stop is hit
-
After my stop is hit, I want to check a condition and then place an order (which would be executed on the open on the next candle, after the stop is hit). However my understanding is that the stop order is executed after next is called, so it wouldn't execute the order on the candle immediately after the stop is hit, rather it would get executed on the 2nd candle after the stop is hit rather than the first.
Is there a way to solve this problem? -
Interested too!!!
-
Lets figure out what do you want first. Do you want to execute stop (1) at stop price as soon as price hit stop or (2) at the open of the bar next to the bar where price hit stop?
(1) is already introduced in the
bt
with the regular stop orders. Notification about the stop order execution comes at the open of the bar next to the bar where price hit stop. This way I would callimmediately
.(2) is easy to incorporate: just check price vs stop relation in the
next()
and if price crosses/touches stop price, than issue simple market order to close position. It will be executed at the open of the bar next to the bar where price hit stop. -
@ab_trader said in Execute trade immediatly after a stop is hit:
Notification
Is there any way to place stop order instantly after enter order gets filled without waiting next bar?
-
@CooleRnax said in Execute trade immediatly after a stop is hit:
Is there any way to place stop order instantly after enter order gets filled without waiting next bar?
Yes, in the
next()
you issue regular order asmarket
order andstop
order. Then before call of the nextnext()
your market order will be executed (if it will be enough money) and you will have activestop
order. -
What if use limit order to enter the market?
-
@CooleRnax you can try Docs - Brackets.
-
thank you!
-
@student said in Execute trade immediatly after a stop is hit:
After my stop is hit, I want to check a condition and then place an order (which would be executed on the open on the next candle, after the stop is hit). However my understanding is that the stop order is executed after next is called, so it wouldn't execute the order on the candle immediately after the stop is hit, rather it would get executed on the 2nd candle after the stop is hit rather than the first.
Is there a way to solve this problem?Although @ab_trader has probably clarified this with the answers ...
@student said in Execute trade immediatly after a stop is hit:
After my stop is hit, I want to check a condition and then place an order (which would be executed on the open on the next candle, after the stop is hit).
Is that a personal price stop or an already placed
Stop
order?@student said in Execute trade immediatly after a stop is hit:
However my understanding is that the stop order is executed after next is called, so it wouldn't execute the order on the candle immediately after the stop is hit , rather it would get executed on the 2nd candle after the stop is hit rather than the first.
I really fail to understand what your understanding is. If we assume that you have a
Stop
order in place and the trigger price is "hit" the order will be executed. Nothing to do withnext
or candles immediately after it. TheStop
is already there.If no
Stop
order is in place and you place an order, it will of course be first executed with the next candle. Because the current candle is already the past (you see the prices, because the prices have already happened)In both cases nothing to with 2nd candles.
Is there a way to solve this problem?
Specify your problem clearly so that we can understand what your problem is and if there is an actual problem. I really think there isn't any, beyond the usual problem: the resolution of the data is not small enough.
-
@ab_trader @backtrader Let me clarify my problem with a illustration.
This shows what I want to do. If my understanding is correct, the stop order is executed after next(). Therefore I do not have the opportunity to place the long order, which would be executed in the following candle. -
To clarify further, my issue isn't with the execution of the stop as @ab_trader suggested, that works fine. The issue is with placing an order after the stop has been executed and having it execute in the following bar.
-
Believe me when I say that the issue is the presentation of an actual issue which isn't an issue. Let me show why
- Chart presented with manual annotations from some other platform.
@student said in Execute trade immediatly after a stop is hit:
If my understanding is correct, the stop order is executed after next().
- "Understanding" is not an issue. Furthermore nothing happens after
next()
, which happens when everything has happened (as a matter of fact, the next iteration takes ofr course place afternext()
)
@student said in Execute trade immediatly after a stop is hit:
Therefore I do not have the opportunity to place the long order, which would be executed in the following candle.
- It seems from the text, that you haven't actually attempted to place such an order.
You probably want to read this:
And the different methods,
next
,notify_order
,notify_trade
, ...But summarizing:
- If in the current
next
cycle (i.e.: iteration) your X (Stop
apparently) order has been executed and another one is placed - It will be executed in the next cycle (if it can of course be executed, i.e.:
Market
orLimit
in which the limit price is reached, ...)
-
Okay, so I stepped through my code. The stop gets hit and the buy order does get submitted in the right place. The problem is in fact that I'm running into order.margin, which prevents the buy order being taken. I'm logging everything and I can see there is no additional orders are before this. My self.broker.get_cash() value is 9801.0 and I'm trying to submit this order
self.buy(size=3.63)
The close of the candle when this is submitted is 7443.0 and the open of the candle after is also 7443.0. Yes I am using leverage but surely this is still fine?
"Order.Margin: the order execution would imply a margin call and the previously accepted order has been taken off the system"
Why would I be getting margin called with these values?
-
Seems to work when I do
self.buy(size=3.63*0.3)
I can't understand why I'm getting margin called? I have no other positions open, no other orders?
-
You may believe that small drops of information enable the all-mighty backtrader to make a diagnostic, but it is simply not the case.
9801
doesn't obviously fit inside7443
(just like in the joke of the divorcing couple) with a size of3.63
@student said in Execute trade immediatly after a stop is hit:
Yes I am using leverage
Without code ... a statement out of thin air.
@student said in Execute trade immediatly after a stop is hit:
I can't understand why I'm getting margin called?
Neither can anyone.
@student said in Execute trade immediatly after a stop is hit:
I have no other positions open, no other orders?Only you know that.
My recommendation:
- Write a small snippet in which you try to use leverage at the given bar (7401) with the given cash (9801)
A lot easier than trying to debug your, for sure, a lot more complex script which involves
Stop
here and there, and then orders and ... -
I've stripped the code and data down and stuck it in a google colab here https://colab.research.google.com/drive/14Jz3DYBjIejVIcir4BInlw1kUF2hEOJr . You can run it in your browser my pressing the play button next to the code. As you can see, same problem still occurs.
-
I am not in the habit of clicking on links here and there. Maybe someone else is.
-
Okay I will post the code here as well
import backtrader as bt import pandas as pd import datetime # get data data = pd.read_csv('https://pastebin.com/raw/8gah3XhH') # convert timestamp to datetime object data['timestamp'] = pd.to_datetime(data['timestamp'], utc=True) data.set_index('timestamp', inplace=True) class TestStrat(bt.Strategy): params = dict( printout=True ) # Stuff for logging def log(self, txt, dt=None): if self.p.printout: dt = dt or self.data.datetime[0] dt = bt.num2date(dt) print('%s, %s' % (dt.isoformat(), txt)) … self.log('Order Rejected') # Sentinel to None: new orders allowed self.order = None def next(self): if self.data.datetime.time() == datetime.time(8,40): self.buy(size=3.63) # Create a cerebro entity cerebro = bt.Cerebro() # Add strategy cerebro.addstrategy(TestStrat) # Pass it to the backtrader datafeed and add it to the cerebro data = bt.feeds.PandasData(dataname=data) # Resample it to 5 min bars cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=5) cerebro.broker.setcash(10000) cerebro.run()
What prints to the console:
2019-10-24T08:40:00, ORDER ACCEPTED/SUBMITTED 2019-10-24T08:45:00, Order Margin 2019-10-25T08:40:00, ORDER ACCEPTED/SUBMITTED 2019-10-25T08:45:00, Order Margin 2019-10-26T08:40:00, ORDER ACCEPTED/SUBMITTED 2019-10-26T08:45:00, Order Margin
A snippet of the data
2019-10-24 08:38:00+00:00,7440.5,7440.5,7434.0,7436.0 2019-10-24 08:39:00+00:00,7436.0,7441.5,7435.5,7441.0 2019-10-24 08:40:00+00:00,7441.0,7443.0,7441.0,7443.0 2019-10-24 08:41:00+00:00,7443.0,7446.5,7442.5,7444.0 2019-10-24 08:42:00+00:00,7444.0,7444.5,7444.0,7444.5 2019-10-24 08:43:00+00:00,7444.5,7444.5,7444.0,7444.5 2019-10-24 08:44:00+00:00,7444.5,7445.0,7444.0,7444.5 2019-10-24 08:45:00+00:00,7444.5,7444.5,7441.5,7442.0 2019-10-24 08:46:00+00:00,7442.0,7442.0,7441.5,7442.0 2019-10-24 08:47:00+00:00,7442.0,7446.5,7441.5,7446.0 2019-10-24 08:48:00+00:00,7446.0,7446.5,7443.5,7444.0 2019-10-24 08:49:00+00:00,7444.0,7444.0,7443.0,7443.0 2019-10-24 08:50:00+00:00,7443.0,7443.5,7443.0,7443.5
-
Cash is
10000
, asset has a value of7400
ish and you want to buy a size of3.63
.Why shouldn't the order be rejected?
-
I thought you could use leverage/margin in backtrader? I can use it for shorts it seems but not longs?