For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

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.

    1. 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)
    
    1. 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.

    2. 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


Log in to reply
 

});