美文网首页
3.8 Rolling over Futures

3.8 Rolling over Futures

作者: wanggs66 | 来源:发表于2020-04-20 23:36 被阅读0次

    对于没有主连合约数据的期货,我们可以通过RollOver将数据拼接起来。
    可以这样:

    import backtrader as bt
    
    cerebro = bt.Cerebro()
    data0 = bt.feeds.MyFeed(dataname='Expiry0')
    data1 =   bt.feeds.MyFeed(dataname='Expiry1')
    ...
    dataN = bt.feeds.MyFeed(dataname='ExpiryN')
    
    drollover = cerebro.rolloverdata(data0, data1, ..., dataN, name='MyRoll', **kwargs)
    
    cerebro.run()
    

    或者:

    import backtrader as bt
    
    cerebro = bt.Cerebro()
    data0 = bt.feeds.MyFeed(dataname='Expiry0')
    data1 = bt.feeds.MyFeed(dataname='Expiry1')
    ...
    dataN = bt.feeds.MyFeed(dataname='ExpiryN')
    
    drollover = bt.feeds.RollOver(data0, data1, ..., dataN, dataname='MyRoll', **kwargs)
    cerebro.adddata(drollover)
    
    cerebro.run()
    

    Options for the Roll-Over

    • checkdate (default: None) 一旦进入助理合约到期日所在的星期数(或者其他设定的日期范围),则用下一期合约作为主连合约
    • checkcondition (default: None) 一旦下一期合约成交量超过当前助理合约,则进行主连合约替换

    Example:

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    
    import argparse
    import bisect
    import calendar
    import datetime
    
    import backtrader as bt
    
    
    class TheStrategy(bt.Strategy):
        def start(self):
            header = ['Len', 'Name', 'RollName', 'Datetime', 'WeekDay', 'Open',
                      'High', 'Low', 'Close', 'Volume', 'OpenInterest']
            print(', '.join(header))
    
        def next(self):
            txt = list()
            txt.append('%04d' % len(self.data0))
            txt.append('{}'.format(self.data0._dataname))
            # Internal knowledge ... current expiration in use is in _d
            txt.append('{}'.format(self.data0._d._dataname))
            txt.append('{}'.format(self.data.datetime.date()))
            txt.append('{}'.format(self.data.datetime.date().strftime('%a')))
            txt.append('{}'.format(self.data.open[0]))
            txt.append('{}'.format(self.data.high[0]))
            txt.append('{}'.format(self.data.low[0]))
            txt.append('{}'.format(self.data.close[0]))
            txt.append('{}'.format(self.data.volume[0]))
            txt.append('{}'.format(self.data.openinterest[0]))
            print(', '.join(txt))
    
    
    def checkdate(dt, d):
        # Check if the date is in the week where the 3rd friday of Mar/Jun/Sep/Dec
    
        # EuroStoxx50 expiry codes: MY
        # M -> H, M, U, Z (Mar, Jun, Sep, Dec)
        # Y -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 -> year code. 5 -> 2015
        MONTHS = dict(H=3, M=6, U=9, Z=12)
    
        M = MONTHS[d._dataname[-2]]
    
        centuria, year = divmod(dt.year, 10)
        decade = centuria * 10
    
        YCode = int(d._dataname[-1])
        Y = decade + YCode
        if Y < dt.year:  # Example: year 2019 ... YCode is 0 for 2020
            Y += 10
    
        exp_day = 21 - (calendar.weekday(Y, M, 1) + 2) % 7
        exp_dt = datetime.datetime(Y, M, exp_day)
    
        # Get the year, week numbers
        exp_year, exp_week, _ = exp_dt.isocalendar()
        dt_year, dt_week, _ = dt.isocalendar()
    
        # print('dt {} vs {} exp_dt'.format(dt, exp_dt))
        # print('dt_week {} vs {} exp_week'.format(dt_week, exp_week))
    
        # can switch if in same week
        return (dt_year, dt_week) == (exp_year, exp_week)
    
    
    def checkvolume(d0, d1):
        return d0.volume[0] < d1.volume[0]  # Switch if volume from d0 < d1
    
    
    def runstrat(args=None):
        args = parse_args(args)
    
        cerebro = bt.Cerebro()
    
        fcodes = ['199FESXM4', '199FESXU4', '199FESXZ4', '199FESXH5', '199FESXM5']
        store = bt.stores.VChartFile()
        ffeeds = [store.getdata(dataname=x) for x in fcodes]
    
        rollkwargs = dict()
        if args.checkdate:
            rollkwargs['checkdate'] = checkdate
    
            if args.checkcondition:
                rollkwargs['checkcondition'] = checkvolume
    
        if not args.no_cerebro:
            if args.rollover:
                cerebro.rolloverdata(name='FESX', *ffeeds, **rollkwargs)
            else:
                cerebro.chaindata(name='FESX', *ffeeds)
        else:
            drollover = bt.feeds.RollOver(*ffeeds, dataname='FESX', **rollkwargs)
            cerebro.adddata(drollover)
    
        cerebro.addstrategy(TheStrategy)
        cerebro.run(stdstats=False)
    
        if args.plot:
            pkwargs = dict(style='bar')
            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='Sample for Roll Over of Futures')
    
        parser.add_argument('--no-cerebro', required=False, action='store_true',
                            help='Use RollOver Directly')
    
        parser.add_argument('--rollover', required=False, action='store_true')
    
        parser.add_argument('--checkdate', required=False, action='store_true',
                            help='Change during expiration week')
    
        parser.add_argument('--checkcondition', required=False,
                            action='store_true',
                            help='Change when a given condition is met')
    
        # 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:\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__':
        runstrat()

    相关文章

      网友评论

          本文标题:3.8 Rolling over Futures

          本文链接:https://www.haomeiwen.com/subject/titeihtx.html