Navigation

    Backtrader Community

    • Register
    • 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/

    Oandatest no attribute 'contractdetails'

    General Discussion
    3
    13
    5279
    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.
    • C
      cortex last edited by backtrader

      Hello Dro,
      I' m trying to use the code Oandatest.py but that doesn't work I have the following error:

        File "C:/samples/oandatest/oandatest.py", line 168, in start
          if self.data0.contractdetails is not None:
        File "C:\backtrader\lineseries.py", line 429, in __getattr__
          return getattr(self.lines, name)
      AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'contractdetails'
      

      I have install Oanda.py it works indepandently from BT and entered the parameters : acount , practice and token.
      Do you have an idea how to solve this issue ?

      1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        Without some code it is really difficult to understand why things may go wrong.

        There are two random guesses that can be made by looking at the actual reported error:

        1. The actual error code seems to indicate that data0 is not an actual OandaData

        or

        1. The requested timeframe/compression pair is not supported and the data feed is bailing out from creating a contractdetails attribute. This is reported in as a NOTSUPPORTED_TF data notification.

        The sample is not coded with full robustness, because it is a sample.

        1 Reply Last reply Reply Quote 0
        • C
          cortex last edited by backtrader

          re: Oandatest no attribute 'contractdetails'
          Hello thanks for the answer. Do you know how I can select the right dataframe supported ?
          I'm sorry for the code it is below. here this the paramaters I used

          --token mytoken --account myaccount --data0 EUR_USD

          Thank you very much for your help.

          # 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 oandapy
          import argparse
          import datetime
          # The above could be sent to an independent module
          
          import backtrader as bt
          from backtrader.utils import flushfile # win32 quick stdout flushing
          
          StoreCls = bt.stores.OandaStore
          DataCls = bt.feeds.OandaData
          BrokerCls = bt.brokers.OandaBroker
          
          class TestStrategy(bt.Strategy):
          params = dict(
          smaperiod=5,
          trade=False,
          stake=10,
          exectype=bt.Order.Market,
          stopafter=0,
          valid=None,
          cancel=0,
          donotcounter=False,
          sell=False,
          )
          
          def __init__(self):
              # To control operation entries
              self.orderid = list()
              self.order = None
          
              self.counttostop = 0
              self.datastatus = 0
          
              # Create SMA on 2nd data
              self.sma = bt.indicators.MovAv.SMA(self.data, period=self.p.smaperiod)
          
              print('--------------------------------------------------')
              print('Strategy Created')
              print('--------------------------------------------------')
          
          def notify_data(self, data, status, *args, **kwargs):
              print('*' * 5, 'DATA NOTIF:', data._getstatusname(status), *args)
              if status == data.LIVE:
                  self.counttostop = self.p.stopafter
                  self.datastatus = 1
          
          def notify_store(self, msg, *args, **kwargs):
              print('*' * 5, 'STORE NOTIF:', msg)
          
          def notify_order(self, order):
              if order.status in [order.Completed, order.Cancelled, order.Rejected]:
                  self.order = None
          
              print('-' * 50, 'ORDER BEGIN', datetime.datetime.now())
              print(order)
              print('-' * 50, 'ORDER END')
          
          def notify_trade(self, trade):
              print('-' * 50, 'TRADE BEGIN', datetime.datetime.now())
              print(trade)
              print('-' * 50, 'TRADE END')
          
          def prenext(self):
              self.next(frompre=True)
          
          def next(self, frompre=False):
              txt = list()
              txt.append('Data0')
              txt.append('%04d' % len(self.data0))
              dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
              txt.append('{:f}'.format(self.data.datetime[0]))
              txt.append('%s' % self.data.datetime.datetime(0).strftime(dtfmt))
              txt.append('{:f}'.format(self.data.open[0]))
              txt.append('{:f}'.format(self.data.high[0]))
              txt.append('{:f}'.format(self.data.low[0]))
              txt.append('{:f}'.format(self.data.close[0]))
              txt.append('{:6d}'.format(int(self.data.volume[0])))
              txt.append('{:d}'.format(int(self.data.openinterest[0])))
              txt.append('{:f}'.format(self.sma[0]))
              print(', '.join(txt))
          
              if len(self.datas) > 1 and len(self.data1):
                  txt = list()
                  txt.append('Data1')
                  txt.append('%04d' % len(self.data1))
                  dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
                  txt.append('{}'.format(self.data1.datetime[0]))
                  txt.append('%s' % self.data1.datetime.datetime(0).strftime(dtfmt))
                  txt.append('{}'.format(self.data1.open[0]))
                  txt.append('{}'.format(self.data1.high[0]))
                  txt.append('{}'.format(self.data1.low[0]))
                  txt.append('{}'.format(self.data1.close[0]))
                  txt.append('{}'.format(self.data1.volume[0]))
                  txt.append('{}'.format(self.data1.openinterest[0]))
                  txt.append('{}'.format(float('NaN')))
                  print(', '.join(txt))
          
              if self.counttostop:  # stop after x live lines
                  self.counttostop -= 1
                  if not self.counttostop:
                      self.env.runstop()
                      return
          
              if not self.p.trade:
                  return
          
              if self.datastatus and not self.position and len(self.orderid) < 1:
                  if not self.p.sell:
                      # price = round(self.data0.close[0] * 0.90, 2)
                      price = self.data0.close[0] - 0.005
                      self.order = self.buy(size=self.p.stake,
                                            exectype=self.p.exectype,
                                            price=price,
                                            valid=self.p.valid)
                  else:
                      # price = round(self.data0.close[0] * 1.10, 4)
                      price = self.data0.close[0] - 0.05
                      self.order = self.sell(size=self.p.stake,
                                             exectype=self.p.exectype,
                                             price=price,
                                             valid=self.p.valid)
          
                  self.orderid.append(self.order)
              elif self.position and not self.p.donotcounter:
                  if self.order is None:
                      if not self.p.sell:
                          self.order = self.sell(size=self.p.stake // 2,
                                                 exectype=bt.Order.Market,
                                                 price=self.data0.close[0])
                      else:
                          self.order = self.buy(size=self.p.stake // 2,
                                                exectype=bt.Order.Market,
                                                price=self.data0.close[0])
          
                  self.orderid.append(self.order)
          
              elif self.order is not None and self.p.cancel:
                  if self.datastatus > self.p.cancel:
                      self.cancel(self.order)
          
              if self.datastatus:
                  self.datastatus += 1
          
          """
          def start(self):
          if self.data0.contractdetails is not None:
          print('-- Contract Details:')
          print(self.data0.contractdetails)
          
              header = ['Datetime', 'Open', 'High', 'Low', 'Close', 'Volume',
                        'OpenInterest', 'SMA']
              print(', '.join(header))
          
              self.done = False
          
          """
          
          def runstrategy():
          args = parse_args()
          
          # Create a cerebro
          cerebro = bt.Cerebro()
          
          storekwargs = dict(
              token="mytoken",
              account="myaccount",
              practice="practice"
          )
          
          if not args.no_store:
              store = StoreCls(**storekwargs)
          
          if args.broker:
              if args.no_store:
                  broker = BrokerCls(**storekwargs)
              else:
                  broker = store.getbroker()
          
              cerebro.setbroker(broker)
          
          timeframe = bt.TimeFrame.TFrame(args.timeframe)
          # Manage data1 parameters
          tf1 = args.timeframe1
          tf1 = bt.TimeFrame.TFrame(tf1) if tf1 is not None else timeframe
          cp1 = args.compression1
          cp1 = cp1 if cp1 is not None else args.compression
          
          if args.resample or args.replay:
              datatf = datatf1 = bt.TimeFrame.Ticks
              datacomp = datacomp1 = 1
          else:
              datatf = timeframe
              datacomp = args.compression
              datatf1 = tf1
              datacomp1 = cp1
          
          fromdate = None
          if args.fromdate:
              dtformat = '%Y-%m-%d' + ('T%H:%M:%S' * ('T' in args.fromdate))
              fromdate = datetime.datetime.strptime(args.fromdate, dtformat)
          
          DataFactory = DataCls if args.no_store else store.getdata
          
          datakwargs = dict(
              timeframe=datatf, compression=datacomp,
              qcheck=args.qcheck,
              historical=args.historical,
              fromdate=fromdate,
              bidask=args.bidask,
              useask=args.useask,
              backfill_start=not args.no_backfill_start,
              backfill=not args.no_backfill,
              tz=args.timezone
          )
          
          if args.no_store and not args.broker:   # neither store nor broker
              datakwargs.update(storekwargs)  # pass the store args over the data
          
          data0 = DataFactory(dataname=args.data0, **datakwargs)
          
          data1 = None
          if args.data1 is not None:
              if args.data1 != args.data0:
                  datakwargs['timeframe'] = datatf1
                  datakwargs['compression'] = datacomp1
                  data1 = DataFactory(dataname=args.data1, **datakwargs)
              else:
                  data1 = data0
          
          rekwargs = dict(
              timeframe=timeframe, compression=args.compression,
              bar2edge=not args.no_bar2edge,
              adjbartime=not args.no_adjbartime,
              rightedge=not args.no_rightedge,
              takelate=not args.no_takelate,
          )
          
          if args.replay:
              cerebro.replaydata(dataname=data0, **rekwargs)
          
              if data1 is not None:
                  rekwargs['timeframe'] = tf1
                  rekwargs['compression'] = cp1
                  cerebro.replaydata(dataname=data1, **rekwargs)
          
          elif args.resample:
              cerebro.resampledata(dataname=data0, **rekwargs)
          
              if data1 is not None:
                  rekwargs['timeframe'] = tf1
                  rekwargs['compression'] = cp1
                  cerebro.resampledata(dataname=data1, **rekwargs)
          
          else:
              cerebro.adddata(data0)
              if data1 is not None:
                  cerebro.adddata(data1)
          
          if args.valid is None:
              valid = None
          else:
              valid = datetime.timedelta(seconds=args.valid)
          # Add the strategy
          cerebro.addstrategy(TestStrategy,
                              smaperiod=args.smaperiod,
                              trade=args.trade,
                              exectype=bt.Order.ExecType(args.exectype),
                              stake=args.stake,
                              stopafter=args.stopafter,
                              valid=valid,
                              cancel=args.cancel,
                              donotcounter=args.donotcounter,
                              sell=args.sell)
          
          # Live data ... avoid long data accumulation by switching to "exactbars"
          cerebro.run(exactbars=args.exactbars)
          if args.exactbars < 1:  # plotting is possible
              if args.plot:
                  pkwargs = dict(style='line')
                  if args.plot is not True:  # evals to True but is not True
                      npkwargs = eval('dict(' + args.plot + ')')  # args were passed
                      pkwargs.update(npkwargs)
          
                  cerebro.plot(**pkwargs)
          
          def parse_args(pargs=None):
          parser = argparse.ArgumentParser(
          formatter_class=argparse.ArgumentDefaultsHelpFormatter,
          description='Test Oanda integration')
          
          parser.add_argument('--exactbars', default=1, type=int,
                              required=False, action='store',
                              help='exactbars level, use 0/-1/-2 to enable plotting')
          
          parser.add_argument('--stopafter', default=0, type=int,
                              required=False, action='store',
                              help='Stop after x lines of LIVE data')
          
          parser.add_argument('--no-store',
                              required=False, action='store_true',
                              help='Do not use the store pattern')
          
          parser.add_argument('--debug',
                              required=False, action='store_true',
                              help='Display all info received from source')
          
          parser.add_argument('--token', default="mytoken",
                              required=True, action='store',
                              help='Access token to use')
          
          parser.add_argument('--account', default=None,
                              required=True, action='store',
                              help='Account identifier to use')
          
          parser.add_argument('--live', default=None,
                              required=False, action='store',
                              help='Go to live server rather than practice')
          
          parser.add_argument('--qcheck', default=0.5, type=float,
                              required=False, action='store',
                              help=('Timeout for periodic '
                                    'notification/resampling/replaying check'))
          
          parser.add_argument('--data0', default='EUR_USD',
                              required=True, action='store',
                              help='data 0 into the system')
          
          parser.add_argument('--data1', default=None,
                              required=False, action='store',
                              help='data 1 into the system')
          
          parser.add_argument('--timezone', default=None,
                              required=False, action='store',
                              help='timezone to get time output into (pytz names)')
          
          parser.add_argument('--bidask', default=None,
                              required=False, action='store_true',
                              help='Use bidask ... if False use midpoint')
          
          parser.add_argument('--useask', default=None,
                              required=False, action='store_true',
                              help='Use the "ask" of bidask prices/streaming')
          
          parser.add_argument('--no-backfill_start',
                              required=False, action='store_true',
                              help='Disable backfilling at the start')
          
          parser.add_argument('--no-backfill',
                              required=False, action='store_true',
                              help='Disable backfilling after a disconnection')
          
          parser.add_argument('--historical',
                              required=False, action='store_true',
                              help='do only historical download')
          
          parser.add_argument('--fromdate',
                              required=False, action='store',
                              help=('Starting date for historical download '
                                    'with format: YYYY-MM-DD[THH:MM:SS]'))
          
          parser.add_argument('--smaperiod', default=20, type=int,
                              required=False, action='store',
                              help='Period to apply to the Simple Moving Average')
          
          pgroup = parser.add_mutually_exclusive_group(required=False)
          
          pgroup.add_argument('--replay',
                              required=False, action='store_true',
                              help='replay to chosen timeframe')
          
          pgroup.add_argument('--resample',
                              required=False, action='store_true',
                              help='resample to chosen timeframe')
          
          parser.add_argument('--timeframe', default=bt.TimeFrame.Names[0],
                              choices=bt.TimeFrame.Names,
                              required=False, action='store',
                              help='TimeFrame for Resample/Replay')
          
          parser.add_argument('--compression', default=1, type=int,
                              required=False, action='store',
                              help='Compression for Resample/Replay')
          
          parser.add_argument('--timeframe1', default=None,
                              choices=bt.TimeFrame.Names,
                              required=False, action='store',
                              help='TimeFrame for Resample/Replay - Data1')
          
          parser.add_argument('--compression1', default=None, type=int,
                              required=False, action='store',
                              help='Compression for Resample/Replay - Data1')
          
          parser.add_argument('--no-takelate',
                              required=False, action='store_true',
                              help=('resample/replay, do not accept late samples'))
          
          parser.add_argument('--no-bar2edge',
                              required=False, action='store_true',
                              help='no bar2edge for resample/replay')
          
          parser.add_argument('--no-adjbartime',
                              required=False, action='store_true',
                              help='no adjbartime for resample/replay')
          
          parser.add_argument('--no-rightedge',
                              required=False, action='store_true',
                              help='no rightedge for resample/replay')
          
          parser.add_argument('--broker',
                              required=False, action='store_true',
                              help='Use Oanda as broker')
          
          parser.add_argument('--trade',
                              required=False, action='store_true',
                              help='Do Sample Buy/Sell operations')
          
          parser.add_argument('--sell',
                              required=False, action='store_true',
                              help='Start by selling')
          
          parser.add_argument('--donotcounter',
                              required=False, action='store_true',
                              help='Do not counter the 1st operation')
          
          parser.add_argument('--exectype', default=bt.Order.ExecTypes[0],
                              choices=bt.Order.ExecTypes,
                              required=False, action='store',
                              help='Execution to Use when opening position')
          
          parser.add_argument('--stake', default=10, type=int,
                              required=False, action='store',
                              help='Stake to use in buy operations')
          
          parser.add_argument('--valid', default=None, type=float,
                              required=False, action='store',
                              help='Seconds to keep the order alive (0 means DAY)')
          
          parser.add_argument('--cancel', default=0, type=int,
                              required=False, action='store',
                              help=('Cancel a buy order after n bars in operation,'
                                    ' to be combined with orders like Limit'))
          
          # Plot options
          parser.add_argument('--plot', '-p', nargs='?', required=False,
                              metavar='kwargs', const=True,
                              help=('Plot the read data applying any kwargs passed\n'
                                    '\n'
                                    'For example (escape the quotes if needed):\n'
                                    '\n'
                                    '  --plot style="candle" (to plot candles)\n'))
          
          if pargs is not None:
              return parser.parse_args(pargs)
          
          return parser.parse_args()
          
          if name == 'main':
          runstrategy()
          
          1 Reply Last reply Reply Quote 0
          • C
            cortex last edited by backtrader

            from your clues I found out the time frame didn't work if I g below the Minutes.
            Ticks didn't works and seconds didn't work.
            with minutes I have the following error message:

            --------------------------------------------------
            Strategy Created
            --------------------------------------------------
            Datetime, Open, High, Low, Close, Volume, OpenInterest, SMA
            ***** DATA NOTIF: NOTSUBSCRIBED
            
            Process finished with exit code 0
            

            when I use Oandpy without BT It works and I don't need to specify the Account the token is enough.
            do you know why TIcks and seconds did not work ?

            I sorry can you please erase , the topic I created by error it was supposed to be the answer of this topic.

            Thank you very much

            oanda = oandapy.API(environment="practice", access_token="mytoken ")
            
            response = oanda.get_prices(instruments="EUR_USD")
            prices = response.get("prices")
            asking_price = prices[0].get("ask")
            
            
            
            marketdata= oanda.get_history(instrument="EUR_USD",granularity="M1",candleFormat="midpoint", start=startdt, end=enddt)
            
            candle=marketdata['candles']
            print (type(candle))
            
            1 Reply Last reply Reply Quote 0
            • B
              backtrader administrators last edited by

              The data feed documentation says:

                  This data feed supports only this mapping of ``timeframe`` and
                  ``compression``, which comply with the definitions in the OANDA API
                  Developer's Guid::
                      (TimeFrame.Seconds, 5): 'S5',
                      (TimeFrame.Seconds, 10): 'S10',
                      (TimeFrame.Seconds, 15): 'S15',
                      (TimeFrame.Seconds, 30): 'S30',
                      (TimeFrame.Minutes, 1): 'M1',
                      (TimeFrame.Minutes, 2): 'M3',
                      (TimeFrame.Minutes, 3): 'M3',
                      (TimeFrame.Minutes, 4): 'M4',
                      (TimeFrame.Minutes, 5): 'M5',
                      (TimeFrame.Minutes, 10): 'M5',
                      (TimeFrame.Minutes, 15): 'M5',
                      (TimeFrame.Minutes, 30): 'M5',
                      (TimeFrame.Minutes, 60): 'H1',
                      (TimeFrame.Minutes, 120): 'H2',
                      (TimeFrame.Minutes, 180): 'H3',
                      (TimeFrame.Minutes, 240): 'H4',
                      (TimeFrame.Minutes, 360): 'H6',
                      (TimeFrame.Minutes, 480): 'H8',
                      (TimeFrame.Days, 1): 'D',
                      (TimeFrame.Weeks, 1): 'W',
                      (TimeFrame.Months, 1): 'M',
              

              That means that (Minutes, 1) is supported if you only specified --timeframe Minutes. If you specified --timeframe Seconds, that implies a compression of 1 and it is not supported. Those limits are specified here:

              • http://developer.oanda.com/rest-live/rates/

              Yes, one can receive ticks with the Streaming API (which backtrader uses to build subsequent bars in real-time), but backfilling wouldn't then be possible.

              1 Reply Last reply Reply Quote 0
              • B
                backtrader administrators last edited by

                This is a run of the sample right now (with account and token changed)

                $ ./oandatest.py --account 0000000 --token A-B --data0 EUR_USD --timeframe Minutes
                --------------------------------------------------
                Strategy Created
                --------------------------------------------------
                -- Contract Details:
                {u'pip': u'0.0001', u'instrument': u'EUR_USD', u'maxTradeUnits': 10000000, u'displayName': u'EUR/USD'}
                Datetime, Open, High, Low, Close, Volume, OpenInterest, SMA
                ***** DATA NOTIF: DELAYED
                Data0, 0001, 736326.863194, 2016-12-28T20:43:00.000000, 1.041095, 1.041100, 1.041070, 1.041100,      7, 0, nan
                Data0, 0002, 736326.863889, 2016-12-28T20:44:00.000000, 1.041080, 1.041145, 1.041055, 1.041105,     17, 0, nan
                Data0, 0003, 736326.864583, 2016-12-28T20:45:00.000000, 1.041115, 1.041205, 1.041110, 1.041110,     11, 0, nan
                Data0, 0004, 736326.865278, 2016-12-28T20:46:00.000000, 1.041070, 1.041070, 1.040885, 1.040920,     13, 0, nan
                Data0, 0005, 736326.865972, 2016-12-28T20:47:00.000000, 1.040895, 1.040925, 1.040895, 1.040905,      5, 0, 1.041028
                ...
                ...
                ...
                Data0, 0500, 736327.236806, 2016-12-29T05:41:00.000000, 1.045880, 1.045880, 1.045880, 1.045880,      1, 0, 1.045891
                ***** DATA NOTIF: LIVE
                Data0, 0501, 736327.236821, 2016-12-29T05:41:01.375075, 1.045800, 1.045800, 1.045800, 1.045800,      0, 0, 1.045871
                ...
                
                This is with a standard `Oanda` account with no special permissions whatsoever. With the default settings the sample uses the `practice` server.
                1 Reply Last reply Reply Quote 0
                • C
                  cortex last edited by backtrader

                  Hello thank you for your response:
                  I took the sample and used the same parameters as you. except my account and my token

                  I still have :

                  --------------------------------------------------
                  Strategy Created
                  --------------------------------------------------
                  Datetime, Open, High, Low, Close, Volume, OpenInterest, SMA
                  ***** DATA NOTIF: NOTSUBSCRIBED
                  

                  Process finished with exit code 0

                  However when I import data and use the rest API of oanda I didn't need to specify the account and it work anyway.
                  I can receive historical data.
                  I use a demo account.

                  1 Reply Last reply Reply Quote 0
                  • B
                    backtrader administrators last edited by

                    No contract is being returned for your request and hence the answer: NOT_SUBSCRIBED

                    Unless it would be the obvious (pointed out in the README)

                    Oanda (needs oandapy) (REST API Only - v20 does not support streaming)

                    B C 4 Replies Last reply Reply Quote 0
                    • B
                      backtrader administrators @backtrader last edited by

                      And of course the token is not needed to access the data. But the sample is also ready for trading and that's why it requires the token.

                      You can remove that limitation in the sample.

                      1 Reply Last reply Reply Quote 0
                      • C
                        cortex @backtrader last edited by

                        @backtrader
                        Hello Dro,
                        I'm trying to use the sample oandatest.py but I have this error message.
                        "
                        traceback (most recent call last):
                        File "C:/Users/demo/PycharmProjects/oandatest.py", line 31, in <module>
                        StoreCls = bt.stores.OandaStore
                        AttributeError: 'module' object has no attribute 'OandaStore'
                        "

                        I use the last version of backtrader and I have installed ondapyV20
                        I use the token and account name not the account number .
                        My account is a V20 type.

                        I utilise the last version of the sample oandatest.py.

                        do you have any idea how to make this sample works ? did anyone had the same problem ?

                        1 Reply Last reply Reply Quote 0
                        • C
                          cortex @backtrader last edited by

                          @backtrader
                          please forget the my question : V20 is not supported with ondatest.py I need to ask the support for a oldversion account.

                          1 Reply Last reply Reply Quote 0
                          • C
                            cortex @backtrader last edited by

                            @backtrader
                            I have asked for a legacy account . at the end of the year legacy account wont access the api service anymore.
                            I try with the legacy account (2121212 )

                            here the code :
                            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
                            from backtrader.utils import flushfile # win32 quick stdout flushing

                            StoreCls = bt.stores.OandaStore
                            DataCls = bt.feeds.OandaData
                            #BrokerCls = bt.brokers.OandaBroker

                            class TestStrategy(bt.Strategy):
                            params = dict(
                            smaperiod=5,
                            trade=False,
                            stake=10,
                            exectype=bt.Order.Market,
                            stopafter=0,
                            valid=None,
                            cancel=0,
                            donotcounter=False,
                            sell=False,
                            usebracket=False,
                            )

                            def __init__(self):
                                # To control operation entries
                                self.orderid = list()
                                self.order = None
                            
                                self.counttostop = 0
                                self.datastatus = 0
                            
                                # Create SMA on 2nd data
                                self.sma = bt.indicators.MovAv.SMA(self.data, period=self.p.smaperiod)
                            
                                print('--------------------------------------------------')
                                print('Strategy Created')
                                print('--------------------------------------------------')
                            
                            def notify_data(self, data, status, *args, **kwargs):
                                print('*' * 5, 'DATA NOTIF:', data._getstatusname(status), *args)
                                if status == data.LIVE:
                                    self.counttostop = self.p.stopafter
                                    self.datastatus = 1
                            
                            def notify_store(self, msg, *args, **kwargs):
                                print('*' * 5, 'STORE NOTIF:', msg)
                            
                            def notify_order(self, order):
                                if order.status in [order.Completed, order.Cancelled, order.Rejected]:
                                    self.order = None
                            
                                print('-' * 50, 'ORDER BEGIN', datetime.datetime.now())
                                print(order)
                                print('-' * 50, 'ORDER END')
                            
                            def notify_trade(self, trade):
                                print('-' * 50, 'TRADE BEGIN', datetime.datetime.now())
                                print(trade)
                                print('-' * 50, 'TRADE END')
                            
                            def prenext(self):
                                self.next(frompre=True)
                            
                            def next(self, frompre=False):
                                txt = list()
                                txt.append('Data0')
                                txt.append('%04d' % len(self.data0))
                                dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
                                txt.append('{:f}'.format(self.data.datetime[0]))
                                txt.append('%s' % self.data.datetime.datetime(0).strftime(dtfmt))
                                txt.append('{:f}'.format(self.data.open[0]))
                                txt.append('{:f}'.format(self.data.high[0]))
                                txt.append('{:f}'.format(self.data.low[0]))
                                txt.append('{:f}'.format(self.data.close[0]))
                                txt.append('{:6d}'.format(int(self.data.volume[0])))
                                txt.append('{:d}'.format(int(self.data.openinterest[0])))
                                txt.append('{:f}'.format(self.sma[0]))
                                print(', '.join(txt))
                            
                                if len(self.datas) > 1 and len(self.data1):
                                    txt = list()
                                    txt.append('Data1')
                                    txt.append('%04d' % len(self.data1))
                                    dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
                                    txt.append('{}'.format(self.data1.datetime[0]))
                                    txt.append('%s' % self.data1.datetime.datetime(0).strftime(dtfmt))
                                    txt.append('{}'.format(self.data1.open[0]))
                                    txt.append('{}'.format(self.data1.high[0]))
                                    txt.append('{}'.format(self.data1.low[0]))
                                    txt.append('{}'.format(self.data1.close[0]))
                                    txt.append('{}'.format(self.data1.volume[0]))
                                    txt.append('{}'.format(self.data1.openinterest[0]))
                                    txt.append('{}'.format(float('NaN')))
                                    print(', '.join(txt))
                            
                                if self.counttostop:  # stop after x live lines
                                    self.counttostop -= 1
                                    if not self.counttostop:
                                        self.env.runstop()
                                        return
                            
                                if not self.p.trade:
                                    return
                            
                                if self.datastatus and not self.position and len(self.orderid) < 1:
                                    if not self.p.usebracket:
                                        if not self.p.sell:
                                            # price = round(self.data0.close[0] * 0.90, 2)
                                            price = self.data0.close[0] - 0.005
                                            self.order = self.buy(size=self.p.stake,
                                                                  exectype=self.p.exectype,
                                                                  price=price,
                                                                  valid=self.p.valid)
                                        else:
                                            # price = round(self.data0.close[0] * 1.10, 4)
                                            price = self.data0.close[0] - 0.05
                                            self.order = self.sell(size=self.p.stake,
                                                                   exectype=self.p.exectype,
                                                                   price=price,
                                                                   valid=self.p.valid)
                            
                                    else:
                                        print('USING BRACKET')
                                        price = self.data0.close[0] - 0.05
                                        self.order, _, _ = self.buy_bracket(size=self.p.stake,
                                                                            exectype=bt.Order.Market,
                                                                            price=price,
                                                                            stopprice=price - 0.10,
                                                                            limitprice=price + 0.10,
                                                                            valid=self.p.valid)
                            
                                    self.orderid.append(self.order)
                                elif self.position and not self.p.donotcounter:
                                    if self.order is None:
                                        if not self.p.sell:
                                            self.order = self.sell(size=self.p.stake // 2,
                                                                   exectype=bt.Order.Market,
                                                                   price=self.data0.close[0])
                                        else:
                                            self.order = self.buy(size=self.p.stake // 2,
                                                                  exectype=bt.Order.Market,
                                                                  price=self.data0.close[0])
                            
                                    self.orderid.append(self.order)
                            
                                elif self.order is not None and self.p.cancel:
                                    if self.datastatus > self.p.cancel:
                                        self.cancel(self.order)
                            
                                if self.datastatus:
                                    self.datastatus += 1
                            
                            def start(self):
                                if self.data0.contractdetails is not None:
                                    print('-- Contract Details:')
                                    print(self.data0.contractdetails)
                            
                                header = ['Datetime', 'Open', 'High', 'Low', 'Close', 'Volume',
                                          'OpenInterest', 'SMA']
                                print(', '.join(header))
                            
                                self.done = False
                            

                            def runstrategy():
                            args = parse_args()

                            # Create a cerebro
                            cerebro = bt.Cerebro()
                            
                            storekwargs = dict(
                                token=args.token,
                                account=args.account,
                                practice=not args.live
                            )
                            
                            if not args.no_store:
                                store = StoreCls(**storekwargs)
                            
                            if args.broker:
                                if args.no_store:
                                    broker = BrokerCls(**storekwargs)
                                else:
                                    broker = store.getbroker()
                            
                                cerebro.setbroker(broker)
                            
                            timeframe = bt.TimeFrame.TFrame(args.timeframe)
                            # Manage data1 parameters
                            tf1 = args.timeframe1
                            tf1 = bt.TimeFrame.TFrame(tf1) if tf1 is not None else timeframe
                            cp1 = args.compression1
                            cp1 = cp1 if cp1 is not None else args.compression
                            
                            if args.resample or args.replay:
                                datatf = datatf1 = bt.TimeFrame.Ticks
                                datacomp = datacomp1 = 1
                            else:
                                datatf = timeframe
                                datacomp = args.compression
                                datatf1 = tf1
                                datacomp1 = cp1
                            
                            fromdate = None
                            if args.fromdate:
                                dtformat = '%Y-%m-%d' + ('T%H:%M:%S' * ('T' in args.fromdate))
                                fromdate = datetime.datetime.strptime(args.fromdate, dtformat)
                            
                            DataFactory = DataCls if args.no_store else store.getdata
                            
                            datakwargs = dict(
                                timeframe=datatf, compression=datacomp,
                                qcheck=args.qcheck,
                                historical=args.historical,
                                fromdate=fromdate,
                                bidask=args.bidask,
                                useask=args.useask,
                                backfill_start=not args.no_backfill_start,
                                backfill=not args.no_backfill,
                                tz=args.timezone
                            )
                            
                            if args.no_store and not args.broker:   # neither store nor broker
                                datakwargs.update(storekwargs)  # pass the store args over the data
                            
                            data0 = DataFactory(dataname=args.data0, **datakwargs)
                            
                            data1 = None
                            if args.data1 is not None:
                                if args.data1 != args.data0:
                                    datakwargs['timeframe'] = datatf1
                                    datakwargs['compression'] = datacomp1
                                    data1 = DataFactory(dataname=args.data1, **datakwargs)
                                else:
                                    data1 = data0
                            
                            rekwargs = dict(
                                timeframe=timeframe, compression=args.compression,
                                bar2edge=not args.no_bar2edge,
                                adjbartime=not args.no_adjbartime,
                                rightedge=not args.no_rightedge,
                                takelate=not args.no_takelate,
                            )
                            
                            if args.replay:
                                cerebro.replaydata(data0, **rekwargs)
                            
                                if data1 is not None:
                                    rekwargs['timeframe'] = tf1
                                    rekwargs['compression'] = cp1
                                    cerebro.replaydata(data1, **rekwargs)
                            
                            elif args.resample:
                                cerebro.resampledata(data0, **rekwargs)
                            
                                if data1 is not None:
                                    rekwargs['timeframe'] = tf1
                                    rekwargs['compression'] = cp1
                                    cerebro.resampledata(data1, **rekwargs)
                            
                            else:
                                cerebro.adddata(data0)
                                if data1 is not None:
                                    cerebro.adddata(data1)
                            
                            if args.valid is None:
                                valid = None
                            else:
                                valid = datetime.timedelta(seconds=args.valid)
                            # Add the strategy
                            cerebro.addstrategy(TestStrategy,
                                                smaperiod=args.smaperiod,
                                                trade=args.trade,
                                                exectype=bt.Order.ExecType(args.exectype),
                                                stake=args.stake,
                                                stopafter=args.stopafter,
                                                valid=valid,
                                                cancel=args.cancel,
                                                donotcounter=args.donotcounter,
                                                sell=args.sell,
                                                usebracket=args.usebracket)
                            
                            # Live data ... avoid long data accumulation by switching to "exactbars"
                            cerebro.run(exactbars=args.exactbars)
                            if args.exactbars < 1:  # plotting is possible
                                if args.plot:
                                    pkwargs = dict(style='line')
                                    if args.plot is not True:  # evals to True but is not True
                                        npkwargs = eval('dict(' + args.plot + ')')  # args were passed
                                        pkwargs.update(npkwargs)
                            
                                    cerebro.plot(**pkwargs)
                            

                            def parse_args(pargs=None):
                            parser = argparse.ArgumentParser(
                            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                            description='Test Oanda integration')

                            parser.add_argument('--exactbars', default=1, type=int,
                                                required=False, action='store',
                                                help='exactbars level, use 0/-1/-2 to enable plotting')
                            
                            parser.add_argument('--stopafter', default=0, type=int,
                                                required=False, action='store',
                                                help='Stop after x lines of LIVE data')
                            
                            parser.add_argument('--no-store',
                                                required=False, action='store_true',
                                                help='Do not use the store pattern')
                            
                            parser.add_argument('--debug',
                                                required=False, action='store_true',
                                                help='Display all info received from source')
                            
                            parser.add_argument('--token', default=None,
                                                required=True, action='store',
                                                help='Access token to use')
                            
                            parser.add_argument('--account', default=None,
                                                required=True, action='store',
                                                help='Account identifier to use')
                            
                            parser.add_argument('--live', default=None,
                                                required=False, action='store',
                                                help='Go to live server rather than practice')
                            
                            parser.add_argument('--qcheck', default=0.5, type=float,
                                                required=False, action='store',
                                                help=('Timeout for periodic '
                                                      'notification/resampling/replaying check'))
                            
                            parser.add_argument('--data0', default=None,
                                                required=True, action='store',
                                                help='data 0 into the system')
                            
                            parser.add_argument('--data1', default=None,
                                                required=False, action='store',
                                                help='data 1 into the system')
                            
                            parser.add_argument('--timezone', default=None,
                                                required=False, action='store',
                                                help='timezone to get time output into (pytz names)')
                            
                            parser.add_argument('--bidask', default=None,
                                                required=False, action='store_true',
                                                help='Use bidask ... if False use midpoint')
                            
                            parser.add_argument('--useask', default=None,
                                                required=False, action='store_true',
                                                help='Use the "ask" of bidask prices/streaming')
                            
                            parser.add_argument('--no-backfill_start',
                                                required=False, action='store_true',
                                                help='Disable backfilling at the start')
                            
                            parser.add_argument('--no-backfill',
                                                required=False, action='store_true',
                                                help='Disable backfilling after a disconnection')
                            
                            parser.add_argument('--historical',
                                                required=False, action='store_true',
                                                help='do only historical download')
                            
                            parser.add_argument('--fromdate',
                                                required=False, action='store',
                                                help=('Starting date for historical download '
                                                      'with format: YYYY-MM-DD[THH:MM:SS]'))
                            
                            parser.add_argument('--smaperiod', default=5, type=int,
                                                required=False, action='store',
                                                help='Period to apply to the Simple Moving Average')
                            
                            pgroup = parser.add_mutually_exclusive_group(required=False)
                            
                            pgroup.add_argument('--replay',
                                                required=False, action='store_true',
                                                help='replay to chosen timeframe')
                            
                            pgroup.add_argument('--resample',
                                                required=False, action='store_true',
                                                help='resample to chosen timeframe')
                            
                            parser.add_argument('--timeframe', default=bt.TimeFrame.Names[1],
                                                choices=bt.TimeFrame.Names,
                                                required=False, action='store',
                                                help='TimeFrame for Resample/Replay')
                            
                            parser.add_argument('--compression', default=1, type=int,
                                                required=False, action='store',
                                                help='Compression for Resample/Replay')
                            
                            parser.add_argument('--timeframe1', default=None,
                                                choices=bt.TimeFrame.Names,
                                                required=False, action='store',
                                                help='TimeFrame for Resample/Replay - Data1')
                            
                            parser.add_argument('--compression1', default=None, type=int,
                                                required=False, action='store',
                                                help='Compression for Resample/Replay - Data1')
                            
                            parser.add_argument('--no-takelate',
                                                required=False, action='store_true',
                                                help=('resample/replay, do not accept late samples'))
                            
                            parser.add_argument('--no-bar2edge',
                                                required=False, action='store_true',
                                                help='no bar2edge for resample/replay')
                            
                            parser.add_argument('--no-adjbartime',
                                                required=False, action='store_true',
                                                help='no adjbartime for resample/replay')
                            
                            parser.add_argument('--no-rightedge',
                                                required=False, action='store_true',
                                                help='no rightedge for resample/replay')
                            
                            parser.add_argument('--broker',
                                                required=False, action='store_true',
                                                help='Use Oanda as broker')
                            
                            parser.add_argument('--trade',
                                                required=False, action='store_true',
                                                help='Do Sample Buy/Sell operations')
                            
                            parser.add_argument('--sell',
                                                required=False, action='store_true',
                                                help='Start by selling')
                            
                            parser.add_argument('--usebracket',
                                                required=False, action='store_true',
                                                help='Test buy_bracket')
                            
                            parser.add_argument('--donotcounter',
                                                required=False, action='store_true',
                                                help='Do not counter the 1st operation')
                            
                            parser.add_argument('--exectype', default=bt.Order.ExecTypes[0],
                                                choices=bt.Order.ExecTypes,
                                                required=False, action='store',
                                                help='Execution to Use when opening position')
                            
                            parser.add_argument('--stake', default=10, type=int,
                                                required=False, action='store',
                                                help='Stake to use in buy operations')
                            
                            parser.add_argument('--valid', default=None, type=float,
                                                required=False, action='store',
                                                help='Seconds to keep the order alive (0 means DAY)')
                            
                            parser.add_argument('--cancel', default=0, type=int,
                                                required=False, action='store',
                                                help=('Cancel a buy order after n bars in operation,'
                                                      ' to be combined with orders like Limit'))
                            
                            # Plot options
                            parser.add_argument('--plot', '-p', nargs='?', required=False,
                                                metavar='kwargs', const=True,
                                                help=('Plot the read data applying any kwargs passed\n'
                                                      '\n'
                                                      'For example (escape the quotes if needed):\n'
                                                      '\n'
                                                      '  --plot style="candle" (to plot candles)\n'))
                            
                            if pargs is not None:
                                return parser.parse_args(pargs)
                            
                            return parser.parse_args()
                            

                            if name == 'main':
                            runstrategy()

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

                              @cortex hello,

                              I'm learn to use backtrader ,and I'm trying to use the Oandatest.py with some problem. errormsg is the same with you.

                              I want to know how to run oandatest.py succeed, I have oanda account and token. and pip install oandapy.

                              but I can't run it succeed. please give me a hand. thanks very much.

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