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

ValueError: x and y must have length at least 2.



  • Print error "File "C:\Users\user\Anaconda3\envs\BackTrading\lib\site-packages\scipy\stats\stats.py", line 3392, in pearsonr
    raise ValueError('x and y must have length at least 2.')

    ValueError: x and y must have length at least 2.
    "

      from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
    
      import argparse
      import datetime
    
      import scipy.stats
      import backtrader as bt
      import backtrader.feeds as btfeeds
      import backtrader.indicators as btind
    

    class PairTradingStrategy(bt.Strategy):
    params = dict(
    period20=20,
    period10=10,
    stake=10,
    qty1=0,
    qty2=0,
    status=0,
    )

    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
        self.qty1 = self.p.qty1
        self.qty2 = self.p.qty2
        self.status = self.p.status
        self.profit_fix = 30
        self.profit = 0
        self.cash_aapl = 0
        self.cash_msft = 0
        self.init_close1 = 0
        self.init_close2 = 0
        self.portfolio_value = self.broker.startingcash
    
        # # Signals performed with PD.OLS :
        # self.transform = btind.OLS_TransformationN(self.data0, self.data1,
        #                                            period10=self.p.period10,period20=self.p.period20)
        # self.zscore = self.transform.zscore
    
        # Checking signals built with StatsModel.API :
        # self.ols_transfo = btind.OLS_Transformation(self.data0, self.data1,
        #                                             period=self.p.period,
        #                                             plot=True)
    
    def next(self):
    
        if self.orderid:
            return  # if an order is active, no new orders are allowed
    
        print('*' * 20)
        print('Status is ', self.status)
    
        c10_basket1, p = scipy.stats.pearsonr(self.data0.get(size=self.p.period10),
                                              self.data1.get(size=self.p.period10))
    
        c20_basket1, p = scipy.stats.pearsonr(self.data0.get(size=self.p.period20),
                                              self.data1.get(size=self.p.period20))
        c10_basket1, c20_basket1 = round(c10_basket1, 2), round(c20_basket1, 2)
        self.log('Close, {}'.format(self.datas[0].close[0]))
        self.log('Close, {}'.format(self.datas[1].close[0]))
        print('corr10: {}, corr20: {}'.format(c10_basket1, c20_basket1))
    
        if self.status == 1:
            self.cash_aapl = round((self.data0.close[0] - self.init_close1) * self.qty1, 2)
            self.cash_msft = round((self.init_close2 - self.data1.close[0]) * self.qty2, 2)
            self.profit = round((self.cash_aapl + self.cash_msft), 2)
    
            print('Profit stock1: {}'.format(self.cash_aapl))
            print('Profit stock2: {}'.format(self.cash_msft))
            print('Total profit: {}'.format(self.profit))
    
        if (c10_basket1 > 0.7 and c20_basket1 > 0.7) and (self.status != 1):
    
            # Calculating the number of shares for each stock
            value = 0.5 * self.portfolio_value_basket1  # Divide the cash equally
            x = int(value / (self.data0.close))  # Find the number of shares for Stock1
            y = int(value / (self.data1.close))  # Find the number of shares for Stock2
    
            print('portfolio_value_basket1: {}'.format(self.portfolio_value_basket1))
    
            # Place the order
            self.log('BUY CREATE %s, price = %.2f, qty = %d' % ("AAPL", self.data0.close[0], x))
            self.buy(data=self.data0, size=(x))
    
            self.log('SELL CREATE %s, price = %.2f, qty = %d' % ("MSFT", self.data1.close[0], y))
            self.sell(data=self.data1, size=(y))
    
            self.qty1 = x  # The new open position quantity for Stock1 is x shares
            self.qty2 = y  # The new open position quantity for Stock2 is y shares
            self.init_close1 = self.data0.close[0]
            self.init_close2 = self.data1.close[0]
            self.status = 1  # The current status is "long the spread"
    
        elif (self.profit > self.profit_fix) and self.status == 1:
            print('profit: {}, profit_fix: {}'.format(self.profit, self.profit_fix))
            # Placing the order
            self.log('SELL CREATE %s, price = %.2f, qty = %d' % ("AAPL", self.data0.close[0], self.qty1))
            self.sell(data=self.data0, size=(self.qty1))
    
            self.log('BUY CREATE %s, price = %.2f, qty = %d' % ("MSFT", self.data1.close[0], self.qty2))
            self.buy(data=self.data1, size=(self.qty2))
    
            # Updating the counters with new value
            self.portfolio_value_basket1 += self.profit
            self.qty1, self.qty2 = 0, 0
    
            self.cash_aapl, self.cash_msft, self.profit = 0, 0, 0
    
            self.status = 0
    
    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()
    
    storekwargs = dict(
        host=args.host, port=args.port,
        clientId=args.clientId, timeoffset=not args.no_timeoffset,
        reconnect=args.reconnect, timeout=args.timeout,
        notifyall=args.notifyall, _debug=args.debug
    )
    
    if args.usestore:
        ibstore = bt.stores.IBStore(**storekwargs)
    
    if args.broker:
        if args.usestore:
            broker = ibstore.getbroker()
        else:
            broker = bt.brokers.IBBroker(**storekwargs)
    
        cerebro.setbroker(broker)
    
    timeframe = bt.TimeFrame.TFrame(args.timeframe)
    if args.resample or args.replay:
        datatf = bt.TimeFrame.Ticks
        datacomp = 1
    else:
        datatf = timeframe
        datacomp = args.compression
    
    fromdate = None
    if args.fromdate:
        dtformat = '%Y-%m-%d' + ('T%H:%M:%S' * ('T' in args.fromdate))
        fromdate = datetime.datetime.strptime(args.fromdate, dtformat)
    
    IBDataFactory = ibstore.getdata if args.usestore else bt.feeds.IBData
    
    datakwargs = dict(
        timeframe=datatf, compression=datacomp,
        historical=args.historical, fromdate=fromdate,
        rtbar=args.rtbar,
        qcheck=args.qcheck,
        what=args.what,
        backfill_start=not args.no_backfill_start,
        backfill=not args.no_backfill,
        latethrough=args.latethrough,
        tz=args.timezone
    )
    if not args.usestore and not args.broker:   # neither store nor broker
        datakwargs.update(storekwargs)  # pass the store args over the data
    
    data0 = IBDataFactory(dataname=args.data0, **datakwargs)
    
    data1 = IBDataFactory(dataname=args.data1, **datakwargs)
    
    
    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:
            cerebro.replaydata(dataname=data1, **rekwargs)
    
    elif args.resample:
        cerebro.resampledata(dataname=data0, **rekwargs)
    
        if data1 is not None:
            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:
        datetime.timedelta(seconds=args.valid)
    
    # Add the strategy
    cerebro.addstrategy(PairTradingStrategy,
                        period10=args.period10,
                        period20=args.period20,
                        stake=args.stake)
    
    
    # Add the commission - only stocks like a for each operation
    cerebro.broker.setcommission(commission=args.commperc)
    
    # And run it
    cerebro.run()
    
    # Plot if requested
    if args.plot:
        cerebro.plot(numfigs=args.numfigs, volume=False, zdown=False)
    

    def parse_args():
    parser = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    description='Test Interactive Brokers 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('--plot',
                        required=False, action='store_true',
                        help='Plot if possible')
    
    parser.add_argument('--stopafter', default=0, type=int,
                        required=False, action='store',
                        help='Stop after x lines of LIVE data')
    
    parser.add_argument('--usestore',
                        required=False, action='store_true',
                        help='Use the store pattern')
    
    parser.add_argument('--oldsync', action='store_true',
                        help='Use old data synchronization method')
    
    parser.add_argument('--runnext', action='store_true',
                        help='Use next by next instead of runonce')
    
    parser.add_argument('--notifyall',
                        required=False, action='store_true',
                        help='Notify all messages to strategy as store notifs')
    
    parser.add_argument('--nopreload', action='store_true',
                        help='Do not preload the data')
    
    parser.add_argument('--debug',
                        required=False, action='store_true',
                        help='Display all info received form IB')
    
    parser.add_argument('--period10', default=10, type=int,
                        help='Period to apply to the Simple Moving Average')
    
    parser.add_argument('--period20', default=20, type=int,
                        help='Period to apply to the Simple Moving Average')
    
    parser.add_argument('--host', default='127.0.0.1',
                        required=False, action='store',
                        help='Host for the Interactive Brokers TWS Connection')
    
    parser.add_argument('--qcheck', default=0.5, type=float,
                        required=False, action='store',
                        help=('Timeout for periodic '
                              'notification/resampling/replaying check'))
    
    parser.add_argument('--port', default=7496, type=int,
                        required=False, action='store',
                        help='Port for the Interactive Brokers TWS Connection')
    
    parser.add_argument('--clientId', default=None, type=int,
                        required=False, action='store',
                        help='Client Id to connect to TWS (default: random)')
    
    parser.add_argument('--no-timeoffset',
                        required=False, action='store_true',
                        help=('Do not Use TWS/System time offset for non '
                              'timestamped prices and to align resampling'))
    
    parser.add_argument('--reconnect', default=3, type=int,
                        required=False, action='store',
                        help='Number of recconnection attempts to TWS')
    
    parser.add_argument('--timeout', default=3.0, type=float,
                        required=False, action='store',
                        help='Timeout between reconnection attempts to TWS')
    
    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('--what', default=None,
                        required=False, action='store',
                        help='specific price type for historical requests')
    
    parser.add_argument('--no-backfill_start',
                        required=False, action='store_true',
                        help='Disable backfilling at the start')
    
    parser.add_argument('--latethrough',
                        required=False, action='store_true',
                        help=('if resampling replaying, adjusting time '
                              'and disabling time offset, let late samples '
                              'through'))
    
    parser.add_argument('--no-backfill',
                        required=False, action='store_true',
                        help='Disable backfilling after a disconnection')
    
    parser.add_argument('--rtbar', default=False,
                        required=False, action='store_true',
                        help='Use 5 seconds real time bar updates if possible')
    
    parser.add_argument('--commperc', default=0.005, type=float,
                        help='Percentage commission (0.005 is 0.5%%')
    
    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[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('--no-takelate',
                        required=False, action='store_true',
                        help=('resample/replay, do not accept late samples '
                              'in new bar if the data source let them through '
                              '(latethrough)'))
    
    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 IB as broker')
    
    parser.add_argument('--trade',
                        required=False, action='store_true',
                        help='Do Sample Buy/Sell operations')
    
    parser.add_argument('--donotsell',
                        required=False, action='store_true',
                        help='Do not sell after a buy')
    
    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=int,
                        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'))
    
    return parser.parse_args()
    

    if name == 'main':
    runstrategy()



  • @YELNAr print self.dataX.get(size=self.p.periodXX) results and check what do you pass to pearsonr function. Maybe it is not what it takes.



  • @ab_trader said in ValueError: x and y must have length at least 2.:

    self.dataX.get(size=self.p.periodXX)

    In my laptop, print these types of error, while on another device it is work



  • Which means that the problem can be in the configuration of the environment on your laptop.


Log in to reply
 

});