Execute orders with bid/ask prices



  • @Nigel said in Execute on bid/ask:

    BidAskCSV

    Hello,

    I am also using Bid/ask data. Wanted to do a test where I buy and sell like @Nigel did.
    But it seems like the orders are not being executed because when I access the order.Exuecuted.price is always 0.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import argparse
    
    import backtrader as bt
    import backtrader.feeds as btfeeds
    #import backtrader.indicators as btind
    import random
    
    
    class BidAskCSV(btfeeds.GenericCSVData):
        linesoverride = True  # discard usual OHLC structure
        # datetime must be present and last
        lines = ('bid', 'ask', 'close', 'open','low', 'high', 'datetime')
        # datetime (always 1st) and then the desired order for
        params = (
            # (datetime, 0), # inherited from parent class
            ('bid', 1),  # default field pos 1
            ('ask', 2),  # default field pos 2
            ('close', 2), ('open', 1), ('low', 1), ('high',2)
        )
        
        def __init__(self):
            super(BidAskCSV, self).__init__()
    

    The strategy:

    class St(bt.Strategy):
    
        def log(self, txt, dt= None):
            """Logging function """
            dt= dt or self.datas[0].datetime[0]
            if isinstance(dt, float):
                dt = bt.num2date(dt)
            print('%s, %s' % (dt.isoformat(), txt))
    
    
        def __init__(self):
            self.order = None
            self.dataclose= self.datas[0].close
            #self.dataclose = self.datas[0].close[0]
                
                
        def notify_order(self, order):
           if order.status in [order.Submitted, order.Accepted]:
               # Buy/Sell order submitted/accepted to/by broker - Nothing to do
               return 
    
           # Check if an order has been completed
           # Attention: broker could reject order if not enougth cash
           if order.status in [order.Completed]:
               if order.isbuy():
                   self.log(
                       'BUY EXECUTED, Price: %.2f, Cost: %.2f' %
                       (order.executed.price,
                        order.executed.value))
    
                   self.buyprice = order.executed.price
                   
               else:  # Sell
                   self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f' %
                            (order.executed.price,
                             order.executed.value))
    
               self.bar_executed = len(self)
           elif order.status in [order.Canceled, order.Margin, order.Rejected]:
               self.log('Order Canceled/Margin/Rejected')
    
           self.order = None
           
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                     (trade.pnl, trade.pnlcomm))
                
    
        def next(self):
            dtstr = self.datas[0].datetime.datetime().isoformat()
            txt = '%4d: %s - Bid %.4f - %.4f Ask, CLOSE %.4f ' % (
                (len(self), dtstr, self.datas[0].bid[0], self.datas[0].ask[0],
                 self.datas[0].close[0]))
    
            print(txt)
            
            position = self.getposition(data=self.datas[0])
            rand = random.random()
            print('-------------')
            print ('Random:', rand)
            print('-------------')
            if rand < 0.2:
                if position:
                    # SELL (with all possible default parameters)
                    self.log('SELL CREATE '.format(self.data.bid[0]))
    
                    # Keep track of the created order to avoid a 2nd order
                    self.order = self.sell(data=self.datas[0])
                    print ('Bid', self.data.bid[0])
            elif rand > 0.8:
                if not position:
                    # BUY (with all possible default parameters)
                    self.log('BUY CREATE {}'.format(self.data.ask[0]))
    
                    # Keep track of the created order to avoid a 2nd order
                    self.order = self.buy(data=self.datas[0])
                    self.log('Executed Price:{}'.format(self.order.executed.price))
                    print ('Executed Price:', self.order.executed.price)
                    print ('ASK', self.data.ask[0])
                    
    

    and finale code:

    def parse_args():
        parser = argparse.ArgumentParser(
            description='Bid/Ask Line Hierarchy',
            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        )
    
        parser.add_argument('--data', '-d', action='store',
                            required=False, default='bidask.csv',
                            help='data to add to the system')
    
        parser.add_argument('--dtformat', '-dt',
                            required=False, default='%m/%d/%Y %H:%M:%S',
                            help='Format of datetime in input')
    
        return parser.parse_args()
    
    
    def runstrategy():
        args = parse_args()
    
        cerebro = bt.Cerebro()  # Create a cerebro
           
        data = BidAskCSV(dataname=args.data, dtformat=args.dtformat)
        cerebro.adddata(data)  # Add the 1st data to cerebro
        # Set our desired cash start
        cerebro.broker.setcash(100000.0)
        
        # Add the strategy to cerebro
        cerebro.addstrategy(St)    
        
            # Add a FixedSize sizer according to the stake
        cerebro.addsizer(bt.sizers.FixedSize, stake=10)
        
        # Print out the starting conditions
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
        # Run over everything
        cerebro.run()
    
        # Print out the final result
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
    
    if __name__ == '__main__':
        runstrategy()
    

    This is what I get as output:

    Starting Portfolio Value: 100000.00
       1: 2010-02-03T23:59:59.999989 - Bid 0.5346 - 0.5347 Ask, CLOSE 0.5347 
    -------------
    Random: 0.329840335116921
    -------------
       2: 2010-02-03T23:59:59.999989 - Bid 0.5343 - 0.5347 Ask, CLOSE 0.5347 
    -------------
    Random: 0.680459956622627
    -------------
       3: 2010-02-03T23:59:59.999989 - Bid 0.5543 - 0.5545 Ask, CLOSE 0.5545 
    -------------
    Random: 0.04838233726017549
    -------------
       4: 2010-02-03T23:59:59.999989 - Bid 0.5342 - 0.5344 Ask, CLOSE 0.5344 
    -------------
    Random: 0.7977225266469058
    -------------
       5: 2010-02-03T23:59:59.999989 - Bid 0.5245 - 0.5464 Ask, CLOSE 0.5464 
    -------------
    Random: 0.8661165246756014
    -------------
    2010-02-03T23:59:59.999989, BUY CREATE 0.5464
    2010-02-03T23:59:59.999989, Executed Price:0.0
    Executed Price: 0.0
    ASK 0.5464
       6: 2010-02-03T23:59:59.999989 - Bid 0.5460 - 0.5470 Ask, CLOSE 0.5470 
    -------------
    Random: 0.7797905933237207
    -------------
       7: 2010-02-03T23:59:59.999989 - Bid 0.5824 - 0.5826 Ask, CLOSE 0.5826 
    -------------
    Random: 0.585687043100518
    -------------
       8: 2010-02-03T23:59:59.999989 - Bid 0.5371 - 0.5374 Ask, CLOSE 0.5374 
    -------------
    Random: 0.2171674683269379
    -------------
       9: 2010-02-03T23:59:59.999989 - Bid 0.5793 - 0.5794 Ask, CLOSE 0.5794 
    -------------
    Random: 0.6576887524911412
    -------------
      10: 2010-02-03T23:59:59.999989 - Bid 0.5684 - 0.5688 Ask, CLOSE 0.5688 
    -------------
    Random: 0.406599019686264
    -------------
    Final Portfolio Value: 100000.00
    

    I don't understand what I am doing wrong, and why the orders are not being executed. Can I get some help here? Thanks!


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.