Backtrader Community

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Order executed price mismatch!

    General Code/Help
    3
    5
    272
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • weibudda
      weibudda last edited by

      When I try the sample multidata-strategy.py from the source distribution of backtrader under the samples/multidata-strategy directory, an Order executed price mismatching phenomenon happens.

      As such:
      on 2003-02-11:
      BUY CREATE , 9.14 => yahoo close 9.145000 --- OK
      on 2003-02-12:
      BUY COMPLETE, 10.51 => orcl no data match ?
      2003-02-12,11.820000,11.950000,11.490000,11.500000,10.229136,39650300
      2003-02-12T23:59:59.999989, BUY COMPLETE, 9.10 => yahoo open 9.100000 ---OK

      It seems that, when it goes for Data0-orcl, the Order executed price matching will always go wrong!

      Some details:

      (backtrader37) D:\Python\BackTrader\Test>python ./multidata-strategy.py --plot
      ...
      Self  len: 28
      Data0 len: 28
      Data1 len: 28
      Data0 len == Data1 len: True
      Data0 dt: 2003-02-11 23:59:59.999989
      Data1 dt: 2003-02-11 23:59:59.999989
      2003-02-11T23:59:59.999989, BUY CREATE , 9.14
      2003-02-12T23:59:59.999989, BUY COMPLETE, 10.51
      2003-02-12T23:59:59.999989, BUY COMPLETE, 9.10
      Self  len: 29
      Data0 len: 29
      Data1 len: 29
      Data0 len == Data1 len: True
      Data0 dt: 2003-02-12 23:59:59.999989
      Data1 dt: 2003-02-12 23:59:59.999989
      2003-02-12T23:59:59.999989, SELL CREATE , 9.09
      2003-02-13T23:59:59.999989, SELL COMPLETE, 10.28
      2003-02-13T23:59:59.999989, SELL COMPLETE, 9.35
      ...
      

      And the corresponding data feeds:
      Data0 - orcl-1995-2014.txt,

      Date,Open,High,Low,Close,Adj Close,Volume
      ...
      2003-02-10,11.410000,11.800000,11.380000,11.750000,10.451510,33763500
      2003-02-11,11.840000,12.140000,11.720000,11.910000,10.593827,46126300
      2003-02-12,11.820000,11.950000,11.490000,11.500000,10.229136,39650300
      2003-02-13,11.560000,11.690000,11.350000,11.540000,10.264715,34557500
      2003-02-14,11.560000,11.920000,11.350000,11.700000,10.407034,41473100
      ...
      

      Data1 - yhoo-1996-2014.txt,

      Date,Open,High,Low,Close,Adj Close,Volume
      ...
      2003-02-10,8.785000,8.985000,8.730000,8.960000,8.960000,10486400
      2003-02-11,9.000000,9.245000,8.990000,9.145000,9.145000,14895800
      2003-02-12,9.100000,9.300000,9.000000,9.085000,9.085000,12368000
      2003-02-13,9.345000,9.365000,8.780000,9.025000,9.025000,26697800
      2003-02-14,9.155000,9.455000,9.045000,9.450000,9.450000,15901600
      ...
      

      Appendix:
      multidata-strategy.py

      #!/usr/bin/env python
      # -*- coding: utf-8; py-indent-offset:4 -*-
      ###############################################################################
      #
      # Copyright (C) 2015, 2016 Daniel Rodriguez
      #
      # This program is free software: you can redistribute it and/or modify
      # it under the terms of the GNU General Public License as published by
      # the Free Software Foundation, either version 3 of the License, or
      # (at your option) any later version.
      #
      # This program is distributed in the hope that it will be useful,
      # but WITHOUT ANY WARRANTY; without even the implied warranty of
      # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      # GNU General Public License for more details.
      #
      # You should have received a copy of the GNU General Public License
      # along with this program.  If not, see <http://www.gnu.org/licenses/>.
      #
      ###############################################################################
      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import argparse
      import datetime
      
      # The above could be sent to an independent module
      import backtrader as bt
      import backtrader.feeds as btfeeds
      import backtrader.indicators as btind
      
      
      class MultiDataStrategy(bt.Strategy):
          '''
          This strategy operates on 2 datas. The expectation is that the 2 datas are
          correlated and the 2nd data is used to generate signals on the 1st
      
            - Buy/Sell Operationss will be executed on the 1st data
            - The signals are generated using a Simple Moving Average on the 2nd data
              when the close price crosses upwwards/downwards
      
          The strategy is a long-only strategy
          '''
          params = dict(
              period=15,
              stake=10,
              printout=True,
          )
      
          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))
      
          def notify_order(self, order):
              if order.status in [bt.Order.Submitted, bt.Order.Accepted]:
                  return  # Await further notifications
      
              if order.status == order.Completed:
                  if order.isbuy():
                      buytxt = 'BUY COMPLETE, %.2f' % order.executed.price
                      self.log(buytxt, order.executed.dt)
                  else:
                      selltxt = 'SELL COMPLETE, %.2f' % order.executed.price
                      self.log(selltxt, order.executed.dt)
      
              elif order.status in [order.Expired, order.Canceled, order.Margin]:
                  self.log('%s ,' % order.Status[order.status])
                  pass  # Simply log
      
              # Allow new orders
              self.orderid = None
      
          def __init__(self):
              # To control operation entries
              self.orderid = None
      
              # Create SMA on 2nd data
              sma = btind.MovAv.SMA(self.data1, period=self.p.period)
              # Create a CrossOver Signal from close an moving average
              self.signal = btind.CrossOver(self.data1.close, sma)
      
          def next(self):
              if self.orderid:
                  return  # if an order is active, no new orders are allowed
      
              if self.p.printout:
                  print('Self  len:', len(self))
                  print('Data0 len:', len(self.data0))
                  print('Data1 len:', len(self.data1))
                  print('Data0 len == Data1 len:',
                        len(self.data0) == len(self.data1))
      
                  print('Data0 dt:', self.data0.datetime.datetime())
                  print('Data1 dt:', self.data1.datetime.datetime())
      
              if not self.position:  # not yet in market
                  if self.signal > 0.0:  # cross upwards
                      self.log('BUY CREATE , %.2f' % self.data1.close[0])
                      self.buy(size=self.p.stake)
                      self.buy(data=self.data1, size=self.p.stake)
      
              else:  # in the market
                  if self.signal < 0.0:  # crosss downwards
                      self.log('SELL CREATE , %.2f' % self.data1.close[0])
                      self.sell(size=self.p.stake)
                      self.sell(data=self.data1, size=self.p.stake)
      
          def stop(self):
              print('==================================================')
              print('Starting Value - %.2f' % self.broker.startingcash)
              print('Ending   Value - %.2f' % self.broker.getvalue())
              print('==================================================')
      
      
      def runstrategy():
          args = parse_args()
      
          # Create a cerebro
          cerebro = bt.Cerebro()
      
          # Get the dates from the args
          fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
          todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')
      
          # Create the 1st data
          data0 = btfeeds.YahooFinanceCSVData(
              dataname=args.data0,
              fromdate=fromdate,
              todate=todate)
      
          # Add the 1st data to cerebro
          cerebro.adddata(data0)
      
          # Create the 2nd data
          data1 = btfeeds.YahooFinanceCSVData(
              dataname=args.data1,
              fromdate=fromdate,
              todate=todate)
      
          # Add the 2nd data to cerebro
          cerebro.adddata(data1)
      
          # Add the strategy
          cerebro.addstrategy(MultiDataStrategy,
                              period=args.period,
                              stake=args.stake)
      
          # Add the commission - only stocks like a for each operation
          cerebro.broker.setcash(args.cash)
      
          # Add the commission - only stocks like a for each operation
          cerebro.broker.setcommission(commission=args.commperc)
      
          # And run it
          cerebro.run(runonce=not args.runnext,
                      preload=not args.nopreload,
                      oldsync=args.oldsync)
      
          # Plot if requested
          if args.plot:
              cerebro.plot(numfigs=args.numfigs, volume=False, zdown=False)
      
      
      def parse_args():
          parser = argparse.ArgumentParser(description='MultiData Strategy')
      
          parser.add_argument('--data0', '-d0',
                              default='../../datas/orcl-1995-2014.txt',
                              help='1st data into the system')
      
          parser.add_argument('--data1', '-d1',
                              default='../../datas/yhoo-1996-2014.txt',
                              help='2nd data into the system')
      
          parser.add_argument('--fromdate', '-f',
                              default='2003-01-01',
                              help='Starting date in YYYY-MM-DD format')
      
          parser.add_argument('--todate', '-t',
                              default='2005-12-31',
                              help='Starting date in YYYY-MM-DD format')
      
          parser.add_argument('--period', default=15, type=int,
                              help='Period to apply to the Simple Moving Average')
      
          parser.add_argument('--cash', default=100000, type=int,
                              help='Starting Cash')
      
          parser.add_argument('--runnext', action='store_true',
                              help='Use next by next instead of runonce')
      
          parser.add_argument('--nopreload', action='store_true',
                              help='Do not preload the data')
      
          parser.add_argument('--oldsync', action='store_true',
                              help='Use old data synchronization method')
      
          parser.add_argument('--commperc', default=0.005, type=float,
                              help='Percentage commission (0.005 is 0.5%%')
      
          parser.add_argument('--stake', default=10, type=int,
                              help='Stake to apply in each operation')
      
          parser.add_argument('--plot', '-p', action='store_true',
                              help='Plot the read data')
      
          parser.add_argument('--numfigs', '-n', default=1,
                              help='Plot using numfigs figures')
      
          return parser.parse_args()
      
      
      if __name__ == '__main__':
          runstrategy()
      
      
      1 Reply Last reply Reply Quote 0
      • C
        chewbacca last edited by

        Check the next bar prices, they will match.
        For example you place order on 1st, you see price "x", however, the order will execute on the next daily bar with its prices.

        1 Reply Last reply Reply Quote 0
        • weibudda
          weibudda last edited by

          There are two data feeds, ocrl and yhoo, the 1st day orders are created on both datas, when the 2nd day, the orders are completed. However, the executed price for yhoo, is right, exactly the open price of the next daily bar, but the executed price for ocrl, I can not find out where does it come from... CAN NOT MATCH PRICES FROM ANY DAY!!!

          1 Reply Last reply Reply Quote 0
          • A
            ab_trader last edited by

            YahooFinanceCSVData data feed provides adjusted prices to bt with the default settings. For ORCL on 2/12/2003 it will be the following price:

            10.229 / 11.5 * 11.82 = 10.514
            

            which is what bt logged.

            • If my answer helped, hit reputation up arrow at lower right corner of the post.
            • Python Debugging With Pdb
            • New to python and bt - check this out
            1 Reply Last reply Reply Quote 2
            • weibudda
              weibudda last edited by

              Yes, that's right now~

              1 Reply Last reply Reply Quote 0
              • 1 / 1
              • First post
                Last post
              Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors