class Backtest(QA_Backtest): ''' 多线程模式回测示例 ''' def __init__(self, market_type, frequence, start, end, code_list, commission_fee): super().__init__(market_type, frequence, start, end, code_list, commission_fee) self.user = QA_User() mastrategy = MAStrategy() # maminstrategy = MAMINStrategy() # maminstrategy.reset_assets(1000) # self.portfolio, self.account = self.user.register_account(mastrategy) self.user = QA_User(user_cookie='user_admin') self.portfolio = self.user.new_portfolio('folio_admin') self.portfolio, self.account = self.user.register_account(mastrategy) def after_success(self): QA_util_log_info(self.account.history_table) risk = QA_Risk(self.account, benchmark_code='000300', benchmark_type=MARKET_TYPE.INDEX_CN) print(risk().T) self.account.save() risk.save()
class Backtest(QA_Backtest): def __init__(self, market_type, frequence, start, end, code_list, commission_fee): super().__init__(market_type, frequence, start, end, code_list, commission_fee) cpsstrategy = CaoPanShouStrategy() self.user = QA_User(user_cookie='user_admin') self.portfolio = self.user.new_portfolio('folio_admin_caopanshou') # self.account = self.portfolio.new_account() # self.portfolio, self.account = self.user.register_account(cpsstrategy, portfolio_cookie='folio_admin') self.portfolio, self.account = self.user.register_account(cpsstrategy) # account = QA_Account(user_cookie='user_admin', # portfolio_cookie='portfolio_admin', # account_cookie='account_admin') # self.user = QA_User.register_account(account) # self.portfolio, self.account = self.user.register_account(cpsstrategy) def after_success(self): QA_util_log_info(self.account.history_table) risk = QA_Risk(self.account, benchmark_code='000300', benchmark_type=MARKET_TYPE.INDEX_CN) print(risk().T) self.account.save() risk.save()
class Backtest(QA_Backtest): ''' 多线程模式回测示例 ''' def __init__(self, market_type, frequence, start, end, code_list, commission_fee): super().__init__(market_type, frequence, start, end, code_list, commission_fee) self.user = QA_User() mastrategy = MAStrategy() maminstrategy = MAMINStrategy() # maminstrategy.reset_assets(1000) # self.portfolio, self.account = self.user.register_account(mastrategy) self.user = QA_User(user_cookie='user_admin') self.portfolio = self.user.new_portfolio('folio_admin') self.portfolio, self.account = self.user.register_account(mastrategy) def after_success(self): QA_util_log_info(self.account.history_table) risk = QA_Risk(self.account, benchmark_code='000300', benchmark_type=MARKET_TYPE.INDEX_CN) print(risk().T) risk.plot_assets_curve() risk.plot_dailyhold() risk.plot_signal() self.account.save() risk.save()
class QA_Backtest(): """BACKTEST BACKTEST的主要目的: - 引入时间轴环境,获取全部的数据,然后按生成器将数据迭代插入回测的BROKER (这一个过程是模拟在真实情况中市场的时间变化和价格变化) - BROKER有了新数据以后 会通知MARKET交易前置,MARKET告知已经注册的所有的ACCOUNT 有新的市场数据 - ACCOUNT 获取了新的市场函数,并将其插入他已有的数据中(update) - ACCOUNT 底下注册的策略STRATEGY根据新的市场函数,产生新的买卖判断,综合生成信号 - 买卖判断通过交易前置发送给对应的BROKER,进行交易 - BROKER发送SETTLE指令 结束这一个bar的所有交易,进行清算 - 账户也进行清算,更新持仓,可卖,可用现金等 - 迭代循环直至结束回测 - 回测去计算这段时间的各个账户收益,并给出综合的最终结果 """ def __init__(self, market_type, frequence, start, end, code_list, commission_fee, username='******', password='******', portfolio_cookie='qatestportfolio'): """ :param market_type: 回测的市场 MARKET_TYPE.STOCK_CN , :param frequence: 'day' '1min' '5min' '15min' '30min' '60min' :param start: 开始日期 :param end: 结束日期 :param code_list: 股票代码池 :param commission_fee: 交易佣金 """ self.user = QA_User(username=username, password=password) self.if_settled = False self.account = None self.portfolio = self.user.new_portfolio(portfolio_cookie) # 🛠todo market_type 应该放在 QA_Market对象里的一个属性 self.market = QA_Market(if_start_orderthreading=True) self.market_type = market_type self.frequence = frequence self.broker = QA_BacktestBroker(commission_fee) self.broker_name = 'backtest_broker' self.start = start self.end = end self.code_list = code_list # 🛠todo 检查start日期和结束end日期是否正确 # 🛠todo 检查code list 是否合法 # 根据 市场类型,回测周期频率, 和股票代码列表 获取回测数据 if self.market_type is MARKET_TYPE.STOCK_CN and self.frequence is FREQUENCE.DAY: # 获取日线级别的回测数据 self.ingest_data = QA_fetch_stock_day_adv( self.code_list, self.start, self.end).to_qfq().panel_gen elif self.market_type is MARKET_TYPE.STOCK_CN and self.frequence[ -3:] == 'min': # 获取分钟级别的回测数据 self.ingest_data = QA_fetch_stock_min_adv( self.code_list, self.start, self.end, self.frequence).to_qfq().panel_gen else: QA_util_log_info("{} 的市场类型没有实现!".format(market_type)) def _generate_account(self): """ generate a simple account """ self.account = self.portfolio.new_account() def start_market(self): """ start the market thread and register backtest broker thread QAMarket 继承QATrader, QATrader 中有 trade_engine属性 , trade_engine类型是QA_Engine从 QA_Thread继承 """ # 启动 trade_engine 线程 self.market.start() print('market start') # 注册 backtest_broker ,并且启动和它关联线程QAThread 存放在 kernels 词典中, { 'broker_name': QAThread } self.market.register(self.broker_name, self.broker) # 通过 broke名字 新建立一个 QAAccount 放在的中 session字典中 session 是 { 'cookie' , QAAccount } self.market.login(self.broker_name, self.account.account_cookie, self.account) self.market._sync_orders() def run(self): """generator driven data flow """ # 如果出现了日期的改变 才会进行结算的事件 print('start: running') _date = None for data in self.ingest_data: # 对于在ingest_data中的数据 # <class 'QUANTAXIS.QAData.QADataStruct.QA_DataStruct_Stock_day'> date = data.date[0] print('current date : {}'.format(date)) print('current time : {}'.format(data.datetime[0])) if self.market_type is MARKET_TYPE.STOCK_CN: # 如果是股票市场 if _date != date: # 如果新的date # 前一天的交易日已经过去 # 往 broker 和 account 发送 settle 事件 try: print('try to settle') self.market._settle(self.broker_name) self.market.next_tradeday() except Exception as e: raise e # 基金 指数 期货 elif self.market_type in [ MARKET_TYPE.FUND_CN, MARKET_TYPE.INDEX_CN, MARKET_TYPE.FUTURE_CN ]: self.market._settle(self.broker_name) self.broker.run( QA_Event(event_type=ENGINE_EVENT.UPCOMING_DATA, market_data=data)) # 生成 UPCOMING_DATA 事件放到 队列中去执行 self.market.upcoming_data(self.broker_name, data) _date = date # 最后收盘的平仓 self.market._settle(self.broker_name) self.after_success() def after_success(self): """called when all trading fininshed, for performance analysis """ print('after success') for po in self.user.portfolio_list.values(): for ac in po.accounts.values(): print(ac.hold) print(ac.history_table) ac.save() self.stop() def stop(self): """stop all the market trade enging threads and all subthreads """ self.market.trade_engine.stop_all() self.market.trade_engine.stop()
class QA_Backtest(): """BACKTEST BACKTEST的主要目的: - 引入时间轴环境,获取全部的数据,然后按生成器将数据迭代插入回测的BROKER (这一个过程是模拟在真实情况中市场的时间变化和价格变化) - BROKER有了新数据以后 会通知MARKET交易前置,MARKET告知已经注册的所有的ACCOUNT 有新的市场数据 - ACCOUNT 获取了新的市场函数,并将其插入他已有的数据中(update) - ACCOUNT 底下注册的策略STRATEGY根据新的市场函数,产生新的买卖判断,综合生成信号 - 买卖判断通过交易前置发送给对应的BROKER,进行交易 - BROKER发送SETTLE指令 结束这一个bar的所有交易,进行清算 - 账户也进行清算,更新持仓,可卖,可用现金等 - 迭代循环直至结束回测 - 回测去计算这段时间的各个账户收益,并给出综合的最终结果 """ def __init__( self, market_type, frequence, start, end, code_list, commission_fee, username='******', password='******', portfolio_cookie='qatestportfolio' ): """ :param market_type: 回测的市场 MARKET_TYPE.STOCK_CN , :param frequence: 'day' '1min' '5min' '15min' '30min' '60min' :param start: 开始日期 :param end: 结束日期 :param code_list: 股票代码池 :param commission_fee: 交易佣金 """ self.user = QA_User(username=username, password=password) self.if_settled = False self.account = None self.portfolio = self.user.new_portfolio(portfolio_cookie) # 🛠todo market_type 应该放在 QA_Market对象里的一个属性 self.market = QA_Market(if_start_orderthreading=True) self.market_type = market_type self.frequence = frequence self.broker = QA_BacktestBroker(commission_fee) self.broker_name = 'backtest_broker' self.start = start self.end = end self.code_list = code_list # 🛠todo 检查start日期和结束end日期是否正确 # 🛠todo 检查code list 是否合法 # 根据 市场类型,回测周期频率, 和股票代码列表 获取回测数据 if self.market_type is MARKET_TYPE.STOCK_CN and self.frequence is FREQUENCE.DAY: # 获取日线级别的回测数据 self.ingest_data = QA_fetch_stock_day_adv( self.code_list, self.start, self.end ).to_qfq().panel_gen elif self.market_type is MARKET_TYPE.STOCK_CN and self.frequence[ -3:] == 'min': # 获取分钟级别的回测数据 self.ingest_data = QA_fetch_stock_min_adv( self.code_list, self.start, self.end, self.frequence ).to_qfq().panel_gen else: QA_util_log_info("{} 的市场类型没有实现!".format(market_type)) def _generate_account(self): """ generate a simple account """ self.account = self.portfolio.new_account() def start_market(self): """ start the market thread and register backtest broker thread QAMarket 继承QATrader, QATrader 中有 trade_engine属性 , trade_engine类型是QA_Engine从 QA_Thread继承 """ # 启动 trade_engine 线程 self.market.start() print('market start') # 注册 backtest_broker ,并且启动和它关联线程QAThread 存放在 kernels 词典中, { 'broker_name': QAThread } self.market.register(self.broker_name, self.broker) # 通过 broke名字 新建立一个 QAAccount 放在的中 session字典中 session 是 { 'cookie' , QAAccount } self.market.login( self.broker_name, self.account.account_cookie, self.account ) self.market._sync_orders() def run(self): """generator driven data flow """ # 如果出现了日期的改变 才会进行结算的事件 print('start: running') _date = None for data in self.ingest_data: # 对于在ingest_data中的数据 # <class 'QUANTAXIS.QAData.QADataStruct.QA_DataStruct_Stock_day'> date = data.date[0] print('current date : {}'.format(date)) print('current time : {}'.format(data.datetime[0])) if self.market_type is MARKET_TYPE.STOCK_CN: # 如果是股票市场 if _date != date: # 如果新的date # 前一天的交易日已经过去 # 往 broker 和 account 发送 settle 事件 try: print('try to settle') self.market._settle(self.broker_name) self.market.next_tradeday() except Exception as e: raise e # 基金 指数 期货 elif self.market_type in [MARKET_TYPE.FUND_CN, MARKET_TYPE.INDEX_CN, MARKET_TYPE.FUTURE_CN]: self.market._settle(self.broker_name) self.broker.run( QA_Event( event_type=ENGINE_EVENT.UPCOMING_DATA, market_data=data ) ) # 生成 UPCOMING_DATA 事件放到 队列中去执行 self.market.upcoming_data(self.broker_name, data) _date = date # 最后收盘的平仓 self.market._settle(self.broker_name) self.after_success() def after_success(self): """called when all trading fininshed, for performance analysis """ print('after success') for po in self.user.portfolio_list.values(): for ac in po.accounts.values(): print(ac.hold) print(ac.history_table) ac.save() self.stop() def stop(self): """stop all the market trade enging threads and all subthreads """ self.market.trade_engine.stop_all() self.market.trade_engine.stop()