Close a short position with trailing stop
-
Hi Good Sirs,
I am at wits end after trying this all day. Code as follows, before I explain:import backtrader as bt import math # Create a Stratey class MyStrat(bt.Strategy): # Strategy is a lines object params = (('order_percentage', 0.95), ('ticker', 'ORA'), ('fast', 10), ('slow', 20)) def __init__(self): self.order = None # To keep track of pending orders, init with None self.buyprice = None self.buycomm = None self.bar_executed = None self.size = None self.broker.set_coc(True) self.fast_sma = bt.indicators.SMA(self.data.close, period=self.params.fast, plotname='{}day SMA'.format(self.params.fast)) self.slow_sma = bt.indicators.SMA(self.data.close, period=self.params.slow, plotname='{}day SMA'.format(self.params.slow)) self.crossover = bt.indicators.CrossOver(self.fast_sma, self.slow_sma) # return 1 if fast cross slow upwards, returns -1 if fast cross slow downwards class AutoStopOrStopTrail(MyStrat): # inherit MyStrat params = dict(stop_loss=0.02, # price is 2% less than the entry point trail=0.005, trail_for_short=-0.0005) parent_order = None # default value for a potential order def notify_order(self, order): # called when a buy or sell is requested print('outstanding order: ', order.status) if order.status == order.Cancelled: # status 5 print('CANCEL@price: {:.2f} {}'.format(order.executed.price, 'long' if order.isbuy() else 'short')) return if order.status in [order.Submitted]: # status 1 # Buy/Sell order submitted/accepted to/by broker - Nothing to do print('Order Submitted...') return if order.status in [order.Accepted]: # status 2 # Buy/Sell order submitted/accepted to/by broker - Nothing to do print('Order Accepted...') return if not order.status == order.Completed: print('Order is not completed...') return # discard any other notification if not self.position: # we left the market print('CLOSE@price: {:.2f}'.format(order.executed.price)) return if order.status in [order.Margin, order.Rejected]: print('Order Margin/Rejected') return # Check if an order has been completed, Attention: broker could reject order if not enough cash if order.status in [order.Completed]: # status 4 if order.isbuy(): print('BUY EXECUTED on {}: {:d} shares of {}, Price: {:.2f}, Value: {:.2f}, Comm: {:.2f}'.format(self.datas[0].datetime.date(0), self.size, self.p.ticker, order.executed.price, order.executed.value, order.executed.comm)) elif order.issell(): # if order.issell() print('SEL EXECUTED on {}: {:d} shares of {}, Price: {:.2f}, Value: {:.2f}, Comm: {:.2f}'.format(self.datas[0].datetime.date(0), self.size, self.p.ticker, order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed = len(self) def next(self): print('current close px: ', self.datas[0].datetime.date(0), self.datas[0].datetime.time(0), self.data.close[0]) # Check if we are in the market if (not self.position) and self.crossover != 0: amount_to_invest = (self.params.order_percentage * self.broker.cash) self.size = math.floor(amount_to_invest / self.data.close) px_to_exe = self.data.close[0] * 1.01 if self.parent_order: # something was pending self.cancel(self.parent_order) print('parent cancelled...') # Not yet ... we MIGHT BUY if ... if self.crossover > 0: # go 'long': print('LONG CREATE, CURRENT PX: {:.2f}, LONG AT {}'.format(self.data.close[0], px_to_exe)) self.parent_order = self.buy(price=px_to_exe, size=self.size, exectype=bt.Order.Stop, transmit=False, valid=None) self.sell(exectype=bt.Order.StopTrail, trailpercent=self.p.trail, parent=self.parent_order) elif self.crossover < 0: # short print('SHORT CREATE, CURRENT PX: {:.2f}, SHORT AT {}'.format(self.data.close[0], px_to_exe)) self.parent_order = self.sell(price=px_to_exe, size=self.size, exectype=bt.Order.Stop, transmit=False, valid=None) self.buy(exectype=bt.Order.StopTrail, trailpercent=self.p.trail_for_short, parent=self.parent_order) def start(self): print('Backtesting is about to start...')
I want to go long or short using stop orders. This is so I confirm a trend. So if price is now 1.00,
a. I want to place a long stop order at 1.01. When price rises to 1.01, my order would be executed.
b. Like wise, if I want to go short, I will place the order at 0.99. When price falls to 0.99, my order would be executed.Now along with this, I want to have a trailing stop loss. I have read the guide on using parent order so 2 orders go at once. This is not really working for me.
- I do not know how to close a short position using the child order. I cannot go the below becasue the order will not be executed.
self.close(exectype=bt.Order.StopTrail, trailpercent=self.p.trail_for_short, parent=self.parent_order)
-
When I go with self.buy(...) as per my code above, it seems to be running a different order and not related to the parent order.
-
Going long and then selling seem ok but in my print statement, its odd I got
BUY EXECUTED on 2020-03-27: 372 shares of ORA, Price: 2.56, Value: 952.51, Comm: 0.95
and when sold
SEL EXECUTED on 2020-03-27: 372 shares of ORA, Price: 2.56, Value: 2.56, Comm: 0.00
Both these code use the same code essentially but value and commision is odd? Also no more buying or selling there after, only 1 trade.
I am really hoping you can offer me a lifeline! Thanks in advance, stay safe all.
-
@J-T You might want to try bracket orders