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__(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 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))
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__(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__(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)
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
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
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
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
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