Passing *kwargs to a broker
-
Hello,
I see in the documentation there is a note in the documentation stating order*kwargs
will be passed to the broker and create aLIMIT IF TOUCHED
order.Lets say I pass the optional "stopLoss" parameter to Oanda through a
kwarg
will backtrader be aware of the existence of this order opposing order? I.e if it is triggered, will backtrader still thinkself.position == True
?stopLoss kwarg is documented here
https://developer.oanda.com/rest-live/orders/#createNewOrderI would like to pass the stopLoss
kwarg
to ensure that the stop loss is only created when the order is accepted/completed. Currently I am handling this by creating a stop loss order when I receive anorder.Completed
notification when the entry order has completed.Thanks!
-
Actually that was written when only Interactive Brokers was in place. The extra
**kwargs
in orders with Oanda are stored as additional information in the order, but not used. The Docs - Oanda shows the actual supported orders. Passing the**kwargs
wouldn't be an issued.The
stopLoss
field is watched in the implementation of bracket orders and a similar approach could be used. But it cannot be automatically used. Those are orders running internally in Oanda -
Ok thanks...
So using a bracket approach, I suppose I could do the following to set a stop loss without a take profit.
self.b1 = self.buy(size=size, transmit=False) self.s1 = self.sell(exectype=bt.Order.Stop, price=stop_price, size=stop_size, parent=self.b1, transmit=True)
Then when closing manually with
self.close()
I would need to also manually cancel the stop loss too. (assuming the SL is not hit first)self.close() self.cancel(self.s1)
Note I tried to do the following which I thought would be a nice way to close a position so I don't have to track the open stop loss order and cancel it myself.
self.close(parent=self.b1)
I thought it might trigger the cancellation of the stop loss but it appears to create an order that is not executed / completed so I guess it is an invalid use case. (It appears as an open order)
-
If you
close
your position, thestoploss
pseudo-order will be cancelled automatically. If you do it manually, you are actually cancelling the real order, because inOanda
, the 3 different orders are actually 1 for the end-user, even if they are clearly 3 on the server side. -
[Original Reply Removed]
Ok - Not sure what I was doing yesterday :p . Using a bracket to create a market order without a take profit on Oanda is as simple as:
self.buy_bracket(exectype=bt.Order.Market, stopprice=stop_price, size=10)
This works very well.
One note: If I try to do the same by manually making the orders, like this:
buy = self.buy(size=size, transmit=False) self.sell(exectype=bt.Order.Stop, price=stop_price, size=stop_size, parent=buy, transmit=True)
Oanda throws an exception:
File "/home/dave/.local/lib/python3.5/site-packages/backtrader/brokers/oandabroker.py", line 291, in _transmit parent, stopside = self.opending.pop(pref) ValueError: not enough values to unpack (expected 2, got 1)
Not sure if it is expected or not but I am happy using the bracket method anyway.
Also for me issuing a
buy_bracket
with only a stoploss specified during backtesting (i.e using cerebro broker) results in an additional order being created and they are not removed when issuingself.close()
.In the example below I used a simple script with basic ouput to test. Note:
- When a
buy
is executed, sell order is created at thestoploss level
and a second sell order is created at thedata close
level - 2 bars later when the SELL is executed, the orders placed above are still open.
2016-03-01, Close, 1.39856 Orders open: 0 SMA Long Signal Received Price: 1.39856 vs SMA: 1.3950407142857144 Stop Price = 1.38856 2016-03-01, BUY EXECUTED, 1.39856 2016-03-01, Close, 1.39763 Orders open: 2 Order Ref: 2 Order size: -100 Order Price: 1.38856 Order Ref: 3 Order size: -100 Order Price: 1.39856 2016-03-01, Close, 1.39360 Orders open: 2 Order Ref: 2 Order size: -100 Order Price: 1.38856 Order Ref: 3 Order size: -100 Order Price: 1.39856 IN A POSITION - Closing Orders 2016-03-01, SELL EXECUTED, 1.39360 2016-03-01, Close, 1.39186 Orders open: 2 Order Ref: 2 Order size: -100 Order Price: 1.38856 Order Ref: 3 Order size: -100 Order Price: 1.39856
Is the method a valid use case or do I have to alter my approach between
Oanda
broker andCerebro
broker? I try to keep one script for both back testing and live to avoid maintaining two for each strategy.This is the next() method of the simple script if interested.
def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.5f' % self.dataclose[0]) open_order = self.broker.get_orders_open() print('Orders open: {}'.format(len(open_order))) for order in open_order: print('Order Ref: {}'.format(order.ref)) print('Order size: {}'.format(order.size)) print('Order Price: {}'.format(order.created.price)) #print(open_order) if self.dataclose[0] > self.sma: if not self.position: print('SMA Long Signal Received') print('Price: {} vs SMA: {}'.format(self.dataclose[0], self.sma[0])) size = 100 stop_size = 100 stop_price = self.dataclose - 0.01 print('Stop Price = {}'.format(stop_price)) self.buy_bracket(exectype=bt.Order.Market, stopprice=stop_price, size=size) elif self.dataclose[0] < self.sma: if self.position: print('IN A POSITION - Closing Orders') self.close()
- When a
-
The problem is that simulating a bracket order ends up creating a 3rd simulated order with
buy_bracket
, even if you have not given a price, which is then understood as the current price (theclose
)And the manual creation runs into the problem that the 3rd simulated and expected has not been created by you and the code breaks.
You only need one broker in the system.
-
Yes I only have one broker in the system at a time. I just wanted to check whether the same code could be used to switch between on or the other depending on whether I want to backtest or go live.
It looks as though I need to handle setting creating a new position with a stop but without a take profit slightly differently depending on whether I run the script in backtest mode or live through Oanda.
Thanks again for all the pointers on this topic.
-
Upon further examination, the reason not to pass
**kwargs
with Oanda, unlike with Interactive Brokers, is:-
With Interactive Brokers the order object gives a hint as to where the key in
**kwargs
is actually present in the order and can therefore be applied -
With Oanda the order is simply a dictionary of values to be filled. The end user could actually be sending anything and this would be in the JSON sent to Oanda (whether that's simply digested with no complain by Oanda is something untested)
-