Example #1
0
    def __init__(self,
                 pcontracts,
                 dt_start="1980-1-1",
                 dt_end="2100-1-1",
                 n=None,
                 spec_date={}):  # 'symbol':[,]
        """
        Args:
            pcontracts (list): list of pcontracts(string)

            dt_start (datetime/str): start time of all pcontracts

            dt_end (datetime/str): end time of all pcontracts

            n (int): last n bars

            spec_date (dict): time range for specific pcontracts
        """
        self.finished_data = []
        pcontracts = map(lambda x: x.upper(), pcontracts)
        self.pcontracts = pcontracts
        self._combs = []
        self._data_manager = DataManager()
        # str(PContract): DataWrapper
        if settings['source'] == 'csv':
            self.pcontracts = self._parse_pcontracts(self.pcontracts)
        self._default_pcontract = self.pcontracts[0]
        self._all_data, self._max_window = self._load_data(
            self.pcontracts, dt_start, dt_end, n, spec_date)
        self.context = Context(self._all_data, self._max_window)
Example #2
0
 def __init__(self, pcontracts,
                    dt_start="1980-1-1",
                    dt_end="2100-1-1",
                    n = None,
                    spec_date = { }): # 'symbol':[,]
     """ 
     Args:
         pcontracts (list): list of pcontracts(string)
         dt_start (datetime/str): start time of all pcontracts
         dt_end (datetime/str): end time of all pcontracts
         n (int): last n bars
         spec_date (dict): time range for specific pcontracts
     """
     self.finished_data = []
     pcontracts = map(lambda x: x.upper(), pcontracts)
     self.pcontracts = pcontracts
     self._combs = []
     self._data_manager = DataManager()
     # str(PContract): DataWrapper
     self.pcontracts = self._parse_pcontracts(self.pcontracts)
     self._all_data, self._max_window = self._load_data(self.pcontracts,
                                                         dt_start,
                                                         dt_end,
                                                         n,
                                                         spec_date)
     self.context = Context(self._all_data, self._max_window)
Example #3
0
 def add_strategies(self, settings):
     for setting in settings:
         strategy = setting['strategy']
         ctx = Context(self._all_data, strategy.name, setting, strategy,
                       self._max_window)
         ctx.data_ref.default_pcontract = self.pcontracts[0]
         self._contexts.append(ctx)
         yield (Profile(ctx.marks, ctx.blotter, ctx.data_ref))
Example #4
0
 def __init__(self, pcontracts, window_size=0, dt_start=datetime(1980,1,1),
         dt_end=datetime(2100,1,1), spec_date = { }): # 'symbol':[,]
     series.g_rolling = False if window_size == 0 else True
     series.g_window = window_size
     self.all_data = OrderedDict()     # str(PContract): DataWrapper
     self.finished_data = []
     pcontracts = map(lambda x: x.upper(), pcontracts)
     self.pcontracts = pcontracts
     self._combs = []
     self._window_size = window_size + 1
     self._data_manager = DataManager()
     for pcon in pcontracts:
         if pcon in spec_date:
             dt_start = spec_date[pcon][0]
             dt_end = spec_date[pcon][1]
         assert(dt_start < dt_end)
         self.load_data(pcon, dt_start, dt_end)
     self.context = Context(self.all_data)
Example #5
0
 def __init__(self, pcontracts, window_size=0, dt_start=datetime(1980,1,1),
              dt_end=datetime(2100,1,1)):
     series.g_rolling = False if window_size == 0 else True
     series.g_window = window_size
     self.dt_start = dt_start
     self.dt_end = dt_end
     self.all_data = { }     # PContract -> DataWrapper
     self.ticks = { }
     self.pcontracts = pcontracts
     self._combs = []
     self._window_size = window_size
     for pcon in pcontracts:
         self.load_data(pcon, dt_start, dt_end)
         self.ticks[pcon.contract] = 0
     self.context = Context(self.all_data, self.ticks)
Example #6
0
 def __init__(self, pcontracts,
                    dt_start="1980-1-1",
                    dt_end="2100-1-1",
                    spec_date = { }): # 'symbol':[,]
     """ 
     Args:
         pcontracts (list): list of pcontracts(string)
         dt_start (datetime/str): start time of all pcontracts
         dt_end (datetime/str): end time of all pcontracts
         spec_date (dict): time range for specific pcontracts
     """
     self.finished_data = []
     pcontracts = map(lambda x: x.upper(), pcontracts)
     self.pcontracts = pcontracts
     self._combs = []
     self._all_data = self._load_data(self.pcontracts, dt_start, dt_end, spec_date)
     self.context = Context(self._all_data)
 def __init__(self, pcontracts, window_size=0, dt_start=datetime(1980,1,1),
         dt_end=datetime(2100,1,1), spec_date = { }): # 'symbol':[,]
     series.g_rolling = False if window_size == 0 else True
     series.g_window = window_size
     self.all_data = { }     # PContract -> DataWrapper
     self.finished_data = []
     self.pcontracts = pcontracts
     self._combs = []
     self._window_size = window_size + 1
     self._data_manager = DataManager()
     for pcon in pcontracts:
         if pcon in spec_date:
             dt_start = spec_date[pcon][0]
             dt_end = spec_date[pcon][1]
         assert(dt_start < dt_end)
         self.load_data(pcon, dt_start, dt_end)
     self.context = Context(self.all_data)
Example #8
0
class ExecuteUnit(object):
    """ 策略执行的物理单元,支持多个组合同时运行。
    """
    def __init__(self, pcontracts,
                       dt_start="1980-1-1",
                       dt_end="2100-1-1",
                       spec_date = { }): # 'symbol':[,]
        """ 
        Args:
            pcontracts (list): list of pcontracts(string)
            dt_start (datetime/str): start time of all pcontracts
            dt_end (datetime/str): end time of all pcontracts
            spec_date (dict): time range for specific pcontracts
        """
        self.finished_data = []
        pcontracts = map(lambda x: x.upper(), pcontracts)
        self.pcontracts = pcontracts
        self._combs = []
        self._all_data = self._load_data(self.pcontracts, dt_start, dt_end, spec_date)
        self.context = Context(self._all_data)

    def _init_strategies(self):
        for pcon, dcontext in self._all_data.iteritems():
            # switch context
            self.context.switch_to_contract(pcon)
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_init(self.context)

    def add_comb(self, comb, settings):
        """ 添加策略组合组合
        
        Args:
            comb (list): 一个策略组合
        """
        self._combs.append(comb)
        num_strategy = len(comb) 
        if 'capital' not in settings:
            settings['capital'] = 1000000.0 # 默认资金
        assert (settings['capital'] > 0)
        if num_strategy == 1:
            settings['ratio'] = [1]
        elif num_strategy > 1 and 'ratio' not in settings:
            settings['ratio'] = [1.0/num_strategy] * num_strategy
        assert('ratio' in settings) 
        assert(len(settings['ratio']) == num_strategy)
        assert(sum(settings['ratio']) == 1)
        assert(num_strategy>=1)
        ctxs = []
        for i, s in enumerate(comb):
            iset = { }
            if settings:
                iset = { 'capital': settings['capital'] * settings['ratio'][i] }
                #logger.debug(iset)
            ctxs.append(StrategyContext(s.name, iset))
        self.context.add_strategy_context(ctxs)
        blotters = [ ctx.blotter for ctx in  ctxs]
        return blotter.Profile(blotters, self._all_data, self.pcontracts[0], len(self._combs)-1)

    def run(self):
        # 初始化策略自定义时间序列变量
        print 'runing strategies..' 
        self._init_strategies()
        print 'on_bars..' 
        # todo 对单策略优化
        has_next = True
        tick_test = settings['tick_test']
        # 遍历每个数据轮, 次数为数据的最大长度
        for pcon, data in self._all_data.iteritems():
            self.context.switch_to_contract(pcon)
            self.context.rolling_forward()
        while True:
            # 遍历数据轮的所有合约
            for pcon, data in self._all_data.iteritems():
                self.context.switch_to_contract(pcon)
                if self.context.time_aligned():
                    self.context.update_system_vars()
                    # 组合遍历
                    for i, combination in enumerate(self._combs):
                        # 策略遍历
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            self.context.update_user_vars()
                            s.on_symbol(self.context)
            ## 默认的是第一个合约
            self.context.switch_to_contract(self.pcontracts[0])
            # 每轮数据的最后处理
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j, True)
                    self.context.process_trading_events(append=True)
                    s.on_bar(self.context)
                    if not tick_test:
                        # 保证有可能在当根Bar成交
                        self.context.process_trading_events(append=False)
            self.context.ctx_datetime = datetime(2100,1,1)
            # 
            toremove = []
            for pcon, data in self._all_data.iteritems():
                self.context.switch_to_contract(pcon)
                has_next = self.context.rolling_forward()
                if not has_next:
                    toremove.append(pcon)
            if toremove:
                for key in toremove:
                    del self._all_data[key]
                if len(self._all_data) == 0:
                    # 策略退出后的处理
                    for i, combination in enumerate(self._combs):
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            s.on_exit(self.context)
                    return
            #print "*********" 

    def _load_data(self, pcontracts, dt_start, dt_end, spec_date):
        all_data = OrderedDict()     # str(PContract): DataWrapper
        self._data_manager = DataManager()
        for pcon in pcontracts:
            if pcon in spec_date:
                dt_start = spec_date[pcon][0]
                dt_end = spec_date[pcon][1]
            assert(dt_start < dt_end)
            wrapper = self._data_manager.get_bars(pcon, dt_start, dt_end)
            all_data[pcon] = DataContext(wrapper)
        return all_data
class ExecuteUnit(object):
    """ 策略执行的物理单元,支持多个策略同时运行。
        每个执行单元都可能跟踪多个数据(策略用到的周期合约数据集合)。
        其中第一个合约为"主合约" 。 每个执行器可加载多个策略,只要数据需求不超过pcontracts。

        :ivar dt_begin: 策略执行的时间起点。
        :ivar dt_end: 策略执行的时间终点。
        :ivar pcontracts: 策略用到的周期合约数据集合。
        :ivar _strategies: 策略集合。
        :ivar datasource: 数据源。

    """
    def __init__(self, pcontracts, window_size=0, dt_start=datetime(1980,1,1),
            dt_end=datetime(2100,1,1), spec_date = { }): # 'symbol':[,]
        series.g_rolling = False if window_size == 0 else True
        series.g_window = window_size
        self.all_data = { }     # PContract -> DataWrapper
        self.finished_data = []
        self.pcontracts = pcontracts
        self._combs = []
        self._window_size = window_size + 1
        self._data_manager = DataManager()
        for pcon in pcontracts:
            if pcon in spec_date:
                dt_start = spec_date[pcon][0]
                dt_end = spec_date[pcon][1]
            assert(dt_start < dt_end)
            self.load_data(pcon, dt_start, dt_end)
        self.context = Context(self.all_data)

    def _init_strategies(self):
        for pcon, dcontext in self.all_data.iteritems():
            # switch context
            self.context.switch_to_contract(pcon)
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_init(self.context)

    def add_comb(self, comb, settings = { }):
        """ 添加策略组合组合
        
        Args:
            comb (list): 一个策略组合
        """
        self._combs.append(comb)
        if settings:
            num_strategy = len(comb) 
            assert (settings['captial'] > 0)
            assert len(settings['ratio']) == num_strategy
            assert(sum(settings['ratio']) == 1)
        ctxs = []
        for i, s in enumerate(comb):
            iset = { }
            if settings:
                iset = { 'captial': settings['captial'] * settings['ratio'][i] }
                logger.debug(iset)
            ctxs.append(StrategyContext(s.name, iset))
        self.context.add_strategy_context(ctxs)
        blotters = [ ctx.blotter for ctx in  ctxs]
        return blotter.Profile(blotters, self.all_data, self.pcontracts[0], len(self._combs)-1)

    def run(self):
        # 初始化策略自定义时间序列变量
        print 'runing strategies..' 
        self._init_strategies()
        print 'on_bars..' 
        # todo 对单策略优化
        has_next = True
        # 遍历每个数据轮, 次数为数据的最大长度
        for pcon, data in self.all_data.iteritems():
            self.context.switch_to_contract(pcon)
            self.context.rolling_foward()
        while True:
            # 遍历数据轮的所有合约
            for pcon, data in self.all_data.iteritems():
                self.context.switch_to_contract(pcon)
                if self.context.time_aligned():
                    self.context.update_system_vars()
                    # 组合遍历
                    for i, combination in enumerate(self._combs):
                        # 策略遍历
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            self.context.update_strategy_environment(i, j)
                            self.context.update_user_vars()
                            s.on_bar(self.context)
            # 每轮数据的最后处理
            #print "*********" 
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    # 只有在on_final引用跨合约数据才有保证。
                    s.on_final(self.context)
                    self.context.process_trading_events()
            self.context.last_date = datetime(2100,1,1)
            # 
            toremove = []
            for pcon, data in self.all_data.iteritems():
                self.context.switch_to_contract(pcon)
                has_next = self.context.rolling_foward()
                if not has_next:
                    toremove.append(pcon)
            if toremove:
                for key in toremove:
                    del self.all_data[key]
                if len(self.all_data) == 0:
                    # 策略退出后的处理
                    for i, combination in enumerate(self._combs):
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            s.on_exit(self.context)
                    return
                 
                    
    def load_data(self, pcontract, dt_start=datetime(1980,1,1), dt_end=datetime(2100,1,1)):
        """ 加载周期合约数据
        
        Args:
            pcontract (PContract): 周期合约

            dt_start(datetime): 开始时间

            dt_end(datetime): 结束时间

        Returns:
            pd.DataFrame. k线数据
        """
        try:
            return self.all_data[str(pcontract)]
        except KeyError:
            wrapper = self._data_manager.load_bars(pcontract, dt_start, dt_end, self._window_size)
            window_size = len(wrapper.data) if not series.g_rolling else self._window_size
            self.all_data[pcontract] = DataContext(wrapper, window_size)
            return wrapper
Example #10
0
class ExecuteUnit(object):
    """ 策略执行的物理单元,支持多个组合同时运行。
    """
    def __init__(self,
                 pcontracts,
                 dt_start="1980-1-1",
                 dt_end="2100-1-1",
                 n=None,
                 spec_date={}):  # 'symbol':[,]
        """
        Args:
            pcontracts (list): list of pcontracts(string)

            dt_start (datetime/str): start time of all pcontracts

            dt_end (datetime/str): end time of all pcontracts

            n (int): last n bars

            spec_date (dict): time range for specific pcontracts
        """
        self.finished_data = []
        pcontracts = map(lambda x: x.upper(), pcontracts)
        self.pcontracts = pcontracts
        self._combs = []
        self._data_manager = DataManager()
        # str(PContract): DataWrapper
        if settings['source'] == 'csv':
            self.pcontracts = self._parse_pcontracts(self.pcontracts)
        self._default_pcontract = self.pcontracts[0]
        self._all_data, self._max_window = self._load_data(
            self.pcontracts, dt_start, dt_end, n, spec_date)
        self.context = Context(self._all_data, self._max_window)

    def _init_strategies(self):
        for pcon, dcontext in self._all_data.iteritems():
            # switch context
            self.context.switch_to_pcontract(pcon)
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_init(self.context)

    @deprecated
    def _parse_pcontracts(self, pcontracts):
        # @TODO test
        code2strpcon, exch_period2strpcon = \
            self._data_manager.get_code2strpcon()
        rst = []
        for strpcon in pcontracts:
            strpcon = strpcon.upper()
            code = strpcon.split('.')[0]
            if code == "*":
                if strpcon == "*":  # '*'
                    for key, value in exch_period2strpcon.iteritems():
                        rst += value
                else:
                    # "*.xxx"
                    # "*.xxx_period"
                    k = strpcon.split('.')[1]
                    for key, value in exch_period2strpcon.iteritems():
                        if '-' in k:
                            if k == key:
                                rst += value
                        elif k == key.split('-')[0]:
                            rst += value
            else:
                try:
                    pcons = code2strpcon[code]
                except IndexError:
                    raise IndexError  # 本地不含该文件
                else:
                    for pcon in pcons:
                        if '-' in strpcon:
                            # "xxx.xxx_xxx.xxx"
                            if strpcon == pcon:
                                rst.append(pcon)
                        elif '.' in strpcon:
                            # "xxx.xxx"
                            if strpcon == pcon.split('-')[0]:
                                rst.append(pcon)
                        elif strpcon == pcon.split('.')[0]:
                            # "xxx"
                            rst.append(pcon)
                        #if strpcon in pcon:
                        #rst.append(strpcon)
        return rst

    def add_comb(self, comb, settings):
        """ 添加策略组合组合

        Args:
            comb (list): 一个策略组合
        """
        self._combs.append(comb)
        num_strategy = len(comb)
        if 'capital' not in settings:
            settings['capital'] = 1000000.0  # 默认资金
            logger.info('BackTesting with default capital 1000000.0.')

        assert (settings['capital'] > 0)
        if num_strategy == 1:
            settings['ratio'] = [1]
        elif num_strategy > 1 and 'ratio' not in settings:
            settings['ratio'] = [1.0 / num_strategy] * num_strategy
        assert ('ratio' in settings)
        assert (len(settings['ratio']) == num_strategy)
        assert (sum(settings['ratio']) - 1.0 < 0.000001)
        assert (num_strategy >= 1)
        ctxs = []
        for i, s in enumerate(comb):
            iset = {}
            if settings:
                iset = {'capital': settings['capital'] * settings['ratio'][i]}
                # logger.debug(iset)
            ctxs.append(StrategyContext(s.name, iset))
        self.context.add_strategy_context(ctxs)
        return blotter.Profile(ctxs, self._all_data, self.pcontracts[0],
                               len(self._combs) - 1)

    def run(self):
        # @TODO max_window 可用来显示回测进度
        # 初始化策略自定义时间序列变量
        logger.info("runing strategies...")
        self._init_strategies()
        pbar = ProgressBar().start()
        # todo 对单策略优化
        has_next = True
        # 遍历每个数据轮, 次数为数据的最大长度
        for pcon, data in self._all_data.iteritems():
            self.context.switch_to_pcontract(pcon)
            self.context.rolling_forward()
        while True:
            self.context.on_bar = False
            # 遍历数据轮的所有合约
            for pcon, data in self._all_data.iteritems():
                self.context.switch_to_pcontract(pcon)
                if self.context.time_aligned():
                    self.context.update_system_vars()
                    # 组合遍历
                    for i, combination in enumerate(self._combs):
                        # 策略遍历
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            self.context.update_user_vars()
                            s.on_symbol(self.context)
            # 确保单合约回测的默认值
            self.context.switch_to_pcontract(self._default_pcontract)
            self.context.on_bar = True
            # 遍历组合策略每轮数据的最后处理
            tick_test = settings['tick_test']
            for i, combination in enumerate(self._combs):
                # print self.context.ctx_datetime, "--"
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    # 确保交易状态是基于开盘时间的。
                    self.context.process_trading_events(at_baropen=True)
                    s.on_bar(self.context)
                    if not tick_test:
                        # 保证有可能在当根Bar成交
                        self.context.process_trading_events(at_baropen=False)
            # print self.context.ctx_datetime
            self.context.ctx_datetime = datetime(2100, 1, 1)
            self.context.ctx_curbar += 1
            if self.context.ctx_curbar <= self._max_window:
                pbar.update(self.context.ctx_curbar * 100.0 / self._max_window)
            #
            toremove = []
            for pcon, data in self._all_data.iteritems():
                self.context.switch_to_pcontract(pcon)
                has_next = self.context.rolling_forward()
                if not has_next:
                    toremove.append(pcon)
            if toremove:
                for key in toremove:
                    del self._all_data[key]
                if len(self._all_data) == 0:
                    # 策略退出后的处理
                    for i, combination in enumerate(self._combs):
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            s.on_exit(self.context)
                    return
        pbar.finish()

    def _load_data(self, strpcons, dt_start, dt_end, n, spec_date):
        all_data = OrderedDict()
        max_window = -1
        logger.info("loading data...")
        pbar = ProgressBar().start()
        pcontracts = [PContract.from_string(s) for s in strpcons]
        pcontracts = sorted(pcontracts, reverse=True)
        for i, pcon in enumerate(pcontracts):
            strpcon = str(pcon)
            if strpcon in spec_date:
                dt_start = spec_date[strpcon][0]
                dt_end = spec_date[strpcon][1]
            assert (dt_start < dt_end)
            if n:
                wrapper = self._data_manager.get_last_bars(strpcon, n)
            else:
                wrapper = self._data_manager.get_bars(strpcon, dt_start,
                                                      dt_end)
            if len(wrapper) == 0:
                continue
            all_data[strpcon] = DataContext(wrapper)
            max_window = max(max_window, len(wrapper))
            pbar.update(i * 100.0 / len(strpcons))
            # progressbar.log('')
        if n:
            assert (max_window <= n)
        pbar.finish()
        if len(all_data) == 0:
            assert (False)
            # @TODO raise
        return all_data, max_window
Example #11
0
class ExecuteUnit(object):
    """ 策略执行的物理单元,支持多个组合同时运行。
    """
    def __init__(self, pcontracts,
                       dt_start="1980-1-1",
                       dt_end="2100-1-1",
                       n = None,
                       spec_date = { }): # 'symbol':[,]
        """ 
        Args:
            pcontracts (list): list of pcontracts(string)
            dt_start (datetime/str): start time of all pcontracts
            dt_end (datetime/str): end time of all pcontracts
            n (int): last n bars
            spec_date (dict): time range for specific pcontracts
        """
        self.finished_data = []
        pcontracts = map(lambda x: x.upper(), pcontracts)
        self.pcontracts = pcontracts
        self._combs = []
        self._data_manager = DataManager()
        # str(PContract): DataWrapper
        self.pcontracts = self._parse_pcontracts(self.pcontracts)
        self._all_data, self._max_window = self._load_data(self.pcontracts,
                                                            dt_start,
                                                            dt_end,
                                                            n,
                                                            spec_date)
        self.context = Context(self._all_data, self._max_window)

    def _init_strategies(self):
        for pcon, dcontext in self._all_data.iteritems():
            # switch context
            self.context.switch_to_contract(pcon)
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_init(self.context)

    def _parse_pcontracts(self, pcontracts):
        ## @TODO test
        code2strpcon, exch_period2strpcon = self._data_manager.get_code2strpcon()
        rst = []
        for strpcon in pcontracts:
            strpcon = strpcon.upper()
            code = strpcon.split('.')[0]
            if code == "*" :
                if strpcon == "*" : # '*' 
                    for key, value in exch_period2strpcon.iteritems():
                        rst += value
                else:
                    # "*.xxx" 
                    # "*.xxx_period" 
                    k = strpcon.split('.')[1]
                    for key, value in exch_period2strpcon.iteritems():
                        if '-' in k:
                            if k == key:
                                rst += value 
                        elif k == key.split('-')[0]:
                                rst += value 
            else:
                try:
                    pcons = code2strpcon[code]
                except IndexError:
                    raise IndexError # 本地不含该文件
                else:
                    for pcon in pcons:
                        if '-' in strpcon:
                            # "xxx.xxx_xxx.xxx" 
                            if strpcon == pcon:
                                rst.append(pcon) 
                        elif '.' in strpcon:
                            # "xxx.xxx" 
                            if strpcon == pcon.split('-')[0]:
                                rst.append(pcon) 
                        elif strpcon == pcon.split('.')[0]:
                            # "xxx" 
                            rst.append(pcon) 
                        #if strpcon in pcon:
                            #rst.append(strpcon)
        return rst

    def add_comb(self, comb, settings):
        """ 添加策略组合组合
        
        Args:
            comb (list): 一个策略组合
        """
        self._combs.append(comb)
        num_strategy = len(comb) 
        if 'capital' not in settings:
            settings['capital'] = 1000000.0 # 默认资金
            logger.info('BackTesting with default capital 1000000.0.' )

        assert (settings['capital'] > 0)
        if num_strategy == 1:
            settings['ratio'] = [1]
        elif num_strategy > 1 and 'ratio' not in settings:
            settings['ratio'] = [1.0/num_strategy] * num_strategy
        assert('ratio' in settings) 
        assert(len(settings['ratio']) == num_strategy)
        assert(sum(settings['ratio']) - 1.0 < 0.000001)
        assert(num_strategy>=1)
        ctxs = []
        for i, s in enumerate(comb):
            iset = { }
            if settings:
                iset = { 'capital': settings['capital'] * settings['ratio'][i] }
                #logger.debug(iset)
            ctxs.append(StrategyContext(s.name, iset))
        self.context.add_strategy_context(ctxs)
        blotters = [ ctx.blotter for ctx in  ctxs]
        return blotter.Profile(blotters, self._all_data, self.pcontracts[0], len(self._combs)-1)

    def run(self):
        ## @TODO max_window 可用来显示回测进度
        # 初始化策略自定义时间序列变量
        logger.info("runing strategies...")
        self._init_strategies()
        pbar = ProgressBar().start()
        # todo 对单策略优化
        has_next = True
        tick_test = settings['tick_test']
        # 遍历每个数据轮, 次数为数据的最大长度
        for pcon, data in self._all_data.iteritems():
            self.context.switch_to_contract(pcon)
            self.context.rolling_forward()
        while True:
            self.context.on_bar = False
            # 遍历数据轮的所有合约
            for pcon, data in self._all_data.iteritems():
                self.context.switch_to_contract(pcon)
                if self.context.time_aligned():
                    self.context.update_system_vars()
                    # 组合遍历
                    for i, combination in enumerate(self._combs):
                        # 策略遍历
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            self.context.update_user_vars()
                            s.on_symbol(self.context)
            ## 确保单合约回测的默认值
            self.context.switch_to_contract(self.pcontracts[0])
            self.context.on_bar = True
            # 遍历组合策略每轮数据的最后处理
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j, True)
                    self.context.process_trading_events(at_baropen=True)
                    s.on_bar(self.context)
                    if not tick_test:
                        # 保证有可能在当根Bar成交
                        self.context.process_trading_events(at_baropen=False)
            #print self.context.ctx_datetime
            self.context.ctx_datetime = datetime(2100,1,1)
            self.context.step += 1
            if self.context.step <= self._max_window:
                pbar.update(self.context.step*100.0/self._max_window)
            # 
            toremove = []
            for pcon, data in self._all_data.iteritems():
                self.context.switch_to_contract(pcon)
                has_next = self.context.rolling_forward()
                if not has_next:
                    toremove.append(pcon)
            if toremove:
                for key in toremove:
                    del self._all_data[key]
                if len(self._all_data) == 0:
                    # 策略退出后的处理
                    for i, combination in enumerate(self._combs):
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            s.on_exit(self.context)
                    return
        pbar.finish()

    def _load_data(self, strpcons, dt_start, dt_end, n, spec_date):
        all_data = OrderedDict()     
        max_window = -1
        logger.info("loading data...")
        pbar = ProgressBar().start()
        for i, pcon  in enumerate(strpcons):
            #print "load data: %s" % pcon
            if pcon in spec_date:
                dt_start = spec_date[pcon][0]
                dt_end = spec_date[pcon][1]
            assert(dt_start < dt_end)
            if n:
                wrapper = self._data_manager.get_last_bars(pcon, n)
            else:
                wrapper = self._data_manager.get_bars(pcon, dt_start, dt_end)
            if len(wrapper) == 0:
                continue 
            all_data[pcon] = DataContext(wrapper)
            max_window = max(max_window, len(wrapper))
            pbar.update(i*100.0/len(strpcons))
            #progressbar.log('')
        if n:
            assert(max_window <= n) 
        pbar.finish()
        if len(all_data) == 0:
            assert(False)
            ## @TODO raise
        return all_data, max_window
Example #12
0
class ExecuteUnit(object):
    """ 策略执行的物理单元,支持多个策略同时运行。
        每个执行单元都可能跟踪多个数据(策略用到的周期合约数据集合)。
        其中第一个合约为"主合约" 。 每个执行器可加载多个策略,只要数据需求不超过pcontracts。

        :ivar dt_begin: 策略执行的时间起点。
        :ivar dt_end: 策略执行的时间终点。
        :ivar pcontracts: [str]策略用到的周期合约数据集合。
        :ivar _strategies: 策略集合。
        :ivar datasource: 数据源。

    """
    def __init__(self,
                 pcontracts,
                 window_size=0,
                 dt_start=datetime(1980, 1, 1),
                 dt_end=datetime(2100, 1, 1),
                 spec_date={}):  # 'symbol':[,]
        series.g_rolling = False if window_size == 0 else True
        series.g_window = window_size
        self.all_data = OrderedDict()  # str(PContract): DataWrapper
        self.finished_data = []
        pcontracts = map(lambda x: x.upper(), pcontracts)
        self.pcontracts = pcontracts
        self._combs = []
        self._window_size = window_size + 1
        self._data_manager = DataManager()
        for pcon in pcontracts:
            if pcon in spec_date:
                dt_start = spec_date[pcon][0]
                dt_end = spec_date[pcon][1]
            assert (dt_start < dt_end)
            self.load_data(pcon, dt_start, dt_end)
        self.context = Context(self.all_data)

    def _init_strategies(self):
        for pcon, dcontext in self.all_data.iteritems():
            # switch context
            self.context.switch_to_contract(pcon)
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_init(self.context)

    def add_comb(self, comb, settings={}):
        """ 添加策略组合组合
        
        Args:
            comb (list): 一个策略组合
        """
        self._combs.append(comb)
        if settings:
            num_strategy = len(comb)
            assert (settings['capital'] > 0)
            assert len(settings['ratio']) == num_strategy
            assert (sum(settings['ratio']) == 1)
        ctxs = []
        for i, s in enumerate(comb):
            iset = {}
            if settings:
                iset = {'capital': settings['capital'] * settings['ratio'][i]}
                logger.debug(iset)
            ctxs.append(StrategyContext(s.name, iset))
        self.context.add_strategy_context(ctxs)
        blotters = [ctx.blotter for ctx in ctxs]
        return blotter.Profile(blotters, self.all_data, self.pcontracts[0],
                               len(self._combs) - 1)

    def run(self):
        # 初始化策略自定义时间序列变量
        print 'runing strategies..'
        self._init_strategies()
        print 'on_bars..'
        # todo 对单策略优化
        has_next = True
        # 遍历每个数据轮, 次数为数据的最大长度
        for pcon, data in self.all_data.iteritems():
            self.context.switch_to_contract(pcon)
            self.context.rolling_forward()
        while True:
            # 遍历数据轮的所有合约
            for pcon, data in self.all_data.iteritems():
                self.context.switch_to_contract(pcon)
                if self.context.time_aligned():
                    self.context.update_system_vars()
                    # 组合遍历
                    for i, combination in enumerate(self._combs):
                        # 策略遍历
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            #self.context.switch_to_data(i, j)
                            self.context.update_user_vars()
                            s.on_symbol(self.context)
            ## 默认的是第一个合约
            self.context.switch_to_contract(self.pcontracts[0])
            # 每轮数据的最后处理
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j, True)
                    # 只有在on_final引用跨合约数据才有保证。
                    self.context.process_trading_events(append=True)
                    s.on_bar(self.context)
                    self.context.process_trading_events(append=False)
            self.context.ctx_datetime = datetime(2100, 1, 1)
            #
            toremove = []
            for pcon, data in self.all_data.iteritems():
                self.context.switch_to_contract(pcon)
                has_next = self.context.rolling_forward()
                if not has_next:
                    toremove.append(pcon)
            if toremove:
                for key in toremove:
                    del self.all_data[key]
                if len(self.all_data) == 0:
                    # 策略退出后的处理
                    for i, combination in enumerate(self._combs):
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            s.on_exit(self.context)
                    return
            #print "*********"

    def load_data(self,
                  strpcon,
                  dt_start=datetime(1980, 1, 1),
                  dt_end=datetime(2100, 1, 1)):
        """ 加载周期合约数据
        
        Args:
            strpcon (str): 周期合约

            dt_start(datetime): 开始时间

            dt_end(datetime): 结束时间

        Returns:
            pd.DataFrame. k线数据
        """
        strpcon = strpcon.upper()
        try:
            return self.all_data[strpcon]
        except KeyError:
            wrapper = self._data_manager.get_bars(strpcon, dt_start, dt_end,
                                                  self._window_size)
            window_size = len(
                wrapper.data) if not series.g_rolling else self._window_size
            self.all_data[strpcon] = DataContext(wrapper, window_size)
            return wrapper
Example #13
0
class ExecuteUnit(object):
    """ 策略执行的物理单元,支持多个策略同时运行。
        每个执行单元都可能跟踪多个数据(策略用到的周期合约数据集合)。
        其中第一个合约为"主合约" 。 每个执行器可加载多个策略,只要数据需求不超过pcontracts。

        :ivar dt_begin: 策略执行的时间起点。
        :ivar dt_end: 策略执行的时间终点。
        :ivar pcontracts: 策略用到的周期合约数据集合。
        :ivar _strategies: 策略集合。
        :ivar datasource: 数据源。

    """
    def __init__(self, pcontracts, window_size=0, dt_start=datetime(1980,1,1),
                 dt_end=datetime(2100,1,1)):
        series.g_rolling = False if window_size == 0 else True
        series.g_window = window_size
        self.dt_start = dt_start
        self.dt_end = dt_end
        self.all_data = { }     # PContract -> DataWrapper
        self.ticks = { }
        self.pcontracts = pcontracts
        self._combs = []
        self._window_size = window_size
        for pcon in pcontracts:
            self.load_data(pcon, dt_start, dt_end)
            self.ticks[pcon.contract] = 0
        self.context = Context(self.all_data, self.ticks)

    def _init_strategies(self):
        for pcon, dcontext in self.all_data.iteritems():
            # switch context
            self.context.switch_to_contract(pcon)
            for i, combination in enumerate(self._combs):
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_init(self.context)

    def add_comb(self, comb, settings = { }):
        """ 添加策略组合组合
        
        Args:
            comb (list): 一个策略组合
        """
        self._combs.append(comb)
        if settings:
            num_strategy = len(comb) 
            assert (settings['captial'] > 0)
            assert len(settings['ratio']) == num_strategy
            assert(sum(settings['ratio']) == 1)
        ctxs = []
        for i, s in enumerate(comb):
            iset = { }
            if settings:
                iset = { 'captial': settings['captial'] * settings['ratio'][i] }
                logger.debug(iset)
            ctxs.append(StrategyContext(s.name, iset))
        self.context.add_strategy_context(ctxs)
        blotters = [ ctx.blotter for ctx in  ctxs]
        return blotter.Profile(blotters, self.all_data, self.pcontracts[0], len(self._combs)-1)

    def run(self):
        # 初始化策略自定义时间序列变量
        print 'runing strategies..' 
        self._init_strategies()
        print 'on_bars..' 
        # todo 对单策略优化
        has_next = True
        # 遍历每个数据轮, 次数为数据的最大长度
        while True:
            for pcon, data in self.all_data.iteritems():
                ## @todo 时间对齐
                self.context.switch_to_contract(pcon)
                has_next = self.context.rolling_foward()
                if not has_next:
                    # 策略退出后的处理
                    for i, combination in enumerate(self._combs):
                        for j, s in enumerate(combination):
                            self.context.switch_to_strategy(i, j)
                            s.on_exit(self.context)
                    return
            # 组合遍历
            for i, combination in enumerate(self._combs):
                # 遍历数据轮的所有合约
                for pcon, data in self.all_data.iteritems():
                    self.context.switch_to_contract(pcon)
                    # 原子策略遍历
                    for j, s in enumerate(combination):
                        self.context.switch_to_strategy(i, j)
                        self.context.update_strategy_context(i, j)
                        self.context.update_user_vars()
                        s.on_bar(self.context)
                # 每轮数据的最后处理
                for j, s in enumerate(combination):
                    self.context.switch_to_strategy(i, j)
                    s.on_final(self.context)
                    self.context.process_signals()
                    
    def load_data(self, pcontract, dt_start=datetime(1980,1,1), dt_end=datetime(2100,1,1)):
        """ 加载周期合约数据
        
        Args:
            pcontract (PContract): 周期合约

            dt_start(datetime): 开始时间

            dt_end(datetime): 结束时间

        Returns:
            pd.DataFrame. k线数据
        """
        try:
            return self.all_data[str(pcontract)]
        except KeyError:
            ## @todo 时间对齐,长度确认
            data = data_manager.load_bars(pcontract, dt_start, self.dt_end, self._window_size)
            self.all_data[pcontract] = DataContext(data, self._window_size)
            self._data_length = len(data)
            return data