def __QA_backtest_prepare(self): """ 这是模型内部的 初始化,主要是初始化一些账户和市场资产 写成了私有函数 @yutiansut 2017/7/20 """ if len(str(self.strategy_start_date))==10: self.strategy_start_time=str(self.strategy_start_date)+' 15:00:00' elif len(str(self.strategy_start_date))==19: self.strategy_start_time=str(self.strategy_start_date) self.strategy_start_date=str(self.strategy_start_date)[0:10] else: QA_util_log_info('Wrong start date format') if len(str(self.strategy_end_date))==10: self.strategy_end_time=str(self.strategy_end_date)+' 15:00:00' elif len(str(self.strategy_end_date))==19: self.strategy_end_time=str(self.strategy_end_date) self.strategy_end_date=str(self.strategy_end_date)[0:10] else: QA_util_log_info('Wrong end date format') # 重新初始账户资产 self.market = QA_Market(self.commission_fee_coeff) self.setting.QA_setting_init() self.account.init() self.start_real_date = QA_util_get_real_date( self.strategy_start_date, self.trade_list, 1) self.start_real_time=str(self.start_real_date)+' '+self.strategy_start_time.split(' ')[1] self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date( self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) self.end_real_time=str(self.end_real_date)+' '+self.strategy_end_time.split(' ')[1] # 重新初始化账户的cookie self.account.account_cookie = str(random.random()) # 初始化股票池的市场数据 if self.benchmark_type in ['I','index']: self.benchmark_data = QA_fetch_index_day_adv( self.benchmark_code, self.start_real_date, self.end_real_date) elif self.benchmark_type in ['S','stock']: self.benchmark_data = QA_fetch_stock_day_adv( self.benchmark_code, self.start_real_date, self.end_real_date) if self.backtest_type in ['day', 'd', '0x00']: self.market_data = QA_fetch_stocklist_day_adv( self.strategy_stock_list, self.trade_list[self.start_real_id - int( self.strategy_gap+1)], self.trade_list[self.end_real_id]).to_qfq() elif self.backtest_type in ['1min', '5min', '15min', '30min', '60min']: self.market_data = QA_fetch_stocklist_min_adv( self.strategy_stock_list, QA_util_time_gap(self.start_real_time,self.strategy_gap+1,'<',self.backtest_type), QA_util_time_gap(self.end_real_time,1,'>',self.backtest_type), self.backtest_type).to_qfq() elif self.backtest_type in ['index_day']: self.market_data = QA_fetch_index_day_adv(self.strategy_stock_list, self.trade_list[self.start_real_id - int( self.strategy_gap+1)], self.end_real_date) elif self.backtest_type in ['index_1min', 'index_5min', 'index_15min', 'index_30min', 'index_60min']: self.market_data = QA_fetch_index_min_adv( self.strategy_stock_list, QA_util_time_gap(self.start_real_time,self.strategy_gap+1,'<',self.backtest_type.split('_')[1]), QA_util_time_gap(self.end_real_time,1,'>',self.backtest_type.split('_')[1]), self.backtest_type.split('_')[1])
def __QA_backtest_init_class(self): """ 这是模型内部的 初始化,主要是初始化一些账户和市场资产 写成了私有函数 @yutiansut 2017/7/20 """ # 重新初始账户资产 self.setting.QA_setting_init() self.account.init() self.start_real_date = QA_util_get_real_date(self.strategy_start_date, self.trade_list, 1) self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date(self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) # 重新初始化账户的cookie self.account.account_cookie = str(random.random()) # 初始化股票池的市场数据 self.market_data = QA_fetch_stocklist_day( self.strategy_stock_list, self.setting.client.quantaxis.stock_day, [ self.trade_list[self.start_real_id - int(self.strategy_gap)], self.trade_list[self.end_real_id] ])
def now_time(): return str( QA_util_get_real_date( str(datetime.date.today() - datetime.timedelta(days=1)), trade_date_sse, -1)) + ' 15:00:00' if datetime.datetime.now().hour < 15 else str( QA_util_get_real_date(str(datetime.date.today()), trade_date_sse, -1)) + ' 15:00:00'
def now_time(): real_date = str(QA_util_get_real_date(str(datetime.date.today() - datetime.timedelta(days=1)), trade_date_sse, -1)) str_now = real_date + ' 17:00:00' if datetime.datetime.now().hour < 15 \ else str(QA_util_get_real_date(str(datetime.date.today()), trade_date_sse, -1)) + ' 15:00:00' return date_conver_to_new_format(str_now)
def __QA_backtest_prepare(self): """ 这是模型内部的 初始化,主要是初始化一些账户和市场资产 写成了私有函数 @yutiansut 2017/7/20 """ # 重新初始账户资产 self.market = QA_Market(self.commission_fee_coeff) self.setting.QA_setting_init() self.account.init() self.start_real_date = QA_util_get_real_date(self.strategy_start_date, self.trade_list, 1) self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date(self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) # 重新初始化账户的cookie self.account.account_cookie = str(random.random()) # 初始化股票池的市场数据 self.benchmark_data = QA_fetch_index_day_adv(self.benchmark_code, self.start_real_date, self.end_real_date) if self.backtest_type in ['day', 'd', '0x00']: self.market_data = QA_fetch_stocklist_day_adv( self.strategy_stock_list, self.trade_list[self.start_real_id - int(self.strategy_gap)], self.trade_list[self.end_real_id]).to_qfq() elif self.backtest_type in ['1min', '5min', '15min', '30min', '60min']: self.market_data = QA_fetch_stocklist_min_adv( self.strategy_stock_list, self.trade_list[self.start_real_id - int(self.strategy_gap)], self.trade_list[self.end_real_id + 1], self.backtest_type).to_qfq() elif self.backtest_type in ['index_day']: self.market_data = QA_fetch_index_day_adv( self.strategy_stock_list, self.trade_list[self.start_real_id - int(self.strategy_gap)], self.trade_list[self.end_real_id]) elif self.backtest_type in [ 'index_1min', 'index_5min', 'index_15min', 'index_30min', 'index_60min' ]: self.market_data = QA_fetch_index_min_adv( self.strategy_stock_list, self.start_real_date, self.end_real_date, self.backtest_type.split('_')[1])
def QA_backtest_init(self): # 设置回测的开始结束时间 try: self.QA_backtest_import_setting() except: sys.exit() self.strategy_start_date = str( self.__backtest_setting['backtest']['strategy_start_date']) self.strategy_end_date = str( self.__backtest_setting['backtest']['strategy_end_date']) # 设置回测标的,是一个list对象,不过建议只用一个标的 # gap是回测时,每日获取数据的前推日期(交易日) self.strategy_gap = int( self.__backtest_setting['backtest']['strategy_gap']) # 设置全局的数据库地址,回测用户名,密码,并初始化 self.setting.QA_util_sql_mongo_ip = str( self.__backtest_setting['backtest']['database_ip']) self.setting.QA_setting_user_name = str( self.__backtest_setting['backtest']['username']) self.setting.QA_setting_user_password = str( self.__backtest_setting['backtest']['password']) self.setting.QA_setting_init() # 回测的名字 self.strategy_name = str( self.__backtest_setting['backtest']['strategy_name']) # 股票的交易日历,真实回测的交易周期,和交易周期在交易日历中的id self.trade_list = QA_fetch_trade_date( self.setting.client.quantaxis.trade_date) self.benchmark_code = self.__backtest_setting['backtest'][ 'benchmark_code'] """ 这里会涉及一个区间的问题,开始时间是要向后推,而结束时间是要向前推,1代表向后推,-1代表向前推 """ self.start_real_date = QA_util_get_real_date(self.strategy_start_date, self.trade_list, 1) self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date(self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) self.__QA_backtest_set_stock_list() self.account.init_assest = self.__backtest_setting['account'][ 'account_assets']
def now_time(): """ 1. 当前日期如果是交易日且当前时间在 17:00 之前,默认行情取到上个交易日收盘 2. 当前日期如果是交易日且当前时间在 17:00 之后,默认行情取到当前交易日收盘 """ return (str( QA_util_get_real_date( str(datetime.date.today() - datetime.timedelta(days=1)), trade_date_sse, -1, )) + " 17:00:00" if datetime.datetime.now().hour < TRADE_HOUR_END else str( QA_util_get_real_date(str(datetime.date.today()), trade_date_sse, -1)) + " 17:00:00")
def QA_fetch_get_index_day(code, start_date, end_date, ip='119.147.212.81', port=7709): api = TdxHq_API() start_date = QA_util_get_real_date(start_date, trade_date_sse, 1) end_date = QA_util_get_real_date(end_date, trade_date_sse, -1) with api.connect(ip, port): data = [] for i in range(10): data += api.get_index_bars(9, 1, code, (9 - i) * 800, 800) data = api.to_df(data) data['date'] = data['datetime'].apply(lambda x: x[0:10]) data['date'] = pd.to_datetime(data['date']) data = data.set_index('date', drop=False) data = data.drop( ['year', 'month', 'day', 'hour', 'minute', 'datetime'], axis=1) return data[start_date:end_date]
def get_stock_industry(self, code, start, end): codex = [] if isinstance(code, list): pass else: code = [code] start = QA_util_get_real_date(start) end = QA_util_get_real_date(end) for coder in code: if '.' in coder: codex.append(coder) else: codex.append(coder + '.XSHG' if coder[0] == '6' else coder + '.XSHE') res = self.execute( "SELECT * FROM quantaxis.citis_industry WHERE ((`date` >= '{}')) AND (`date` <= '{}') AND (`order_book_id` IN ({}))" .format(start, end, "'{}'".format( "','".join(codex)))).drop_duplicates(['date', 'order_book_id']) return res
def QA_backtest_init(self): """既然是被当做装饰器使用,就需要把变量设置放在装饰函数的前面,把函数放在装饰函数的后面""" # 设置回测的开始结束时间 self.strategy_start_date = str('2017-01-05') self.strategy_end_date = str('2017-07-01') # 设置回测标的,是一个list对象,不过建议只用一个标的 # gap是回测时,每日获取数据的前推日期(交易日) self.strategy_gap = int(60) # 设置全局的数据库地址,回测用户名,密码,并初始化 self.setting.QA_util_sql_mongo_ip = str('127.0.0.1') self.setting.QA_setting_user_name = str('admin') self.setting.QA_setting_user_password = str('admin') self.setting.QA_setting_init() # 回测的名字 self.strategy_name = str('example') # 股票的交易日历,真实回测的交易周期,和交易周期在交易日历中的id self.trade_list = QA_fetch_trade_date( self.setting.client.quantaxis.trade_date) self.benchmark_code = 'hs300' """ 这里会涉及一个区间的问题,开始时间是要向后推,而结束时间是要向前推,1代表向后推,-1代表向前推 """ self.start_real_date = QA_util_get_real_date(self.strategy_start_date, self.trade_list, 1) self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date(self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) self.strategy_stock_list = ['000001', '000002', '000004'] self.account.init_assest = 1000000 self.backtest_bid_model = 'market_price'
def QA_fetch_get_stock_day(code, start_date,end_date,ip='119.147.212.81',port=7709): if str(code)[0]=='6': #0 - 深圳, 1 - 上海 market_code=1 else: market_code=0 start_date=QA_util_get_real_date(start_date,trade_date_sse,1) end_date=QA_util_get_real_date(end_date,trade_date_sse,-1) with api.connect(ip, port): # 判断end_date在哪个位置 index_0=str(datetime.date.today()) index_of_index_0=trade_date_sse.index(index_0) index_of_index_end=trade_date_sse.index(end_date) index_of_index_start=trade_date_sse.index(start_date) index_of_end=index_of_index_0-index_of_index_end index_length=index_of_index_end+1-index_of_index_start #data = api.get_security_bars(9, market_code, code,index_of_end, index_length) # 返回普通list data = api.to_df(api.get_security_bars(9, market_code, code,index_of_end, index_length)) # 返回DataFrame return data
def QA_fetch_get_stock_day(code, start_date,end_date,ip='119.147.212.81',port=7709): api = TdxHq_API() if str(code)[0]=='6': #0 - 深圳, 1 - 上海 market_code=1 else: market_code=0 start_date=QA_util_get_real_date(start_date,trade_date_sse,1) end_date=QA_util_get_real_date(end_date,trade_date_sse,-1) with api.connect(ip, port): data=[] for i in range(10): data+=api.get_security_bars(9,market_code,code,(9-i)*800,800) data=api.to_df(data) data['date']=data['datetime'].apply(lambda x:x[0:10]) data['date']=pd.to_datetime(data['date']) data = data.set_index('date') data = data.drop(['year','month','day','hour','minute','datetime'],axis=1) return data[start_date:end_date]
def __QA_backtest_prepare(self): """ 这是模型内部的 初始化,主要是初始化一些账户和市场资产 写成了私有函数 @yutiansut 2017/7/20 """ # 重新初始账户资产 self.setting.QA_setting_init() self.account.init() self.start_real_date = QA_util_get_real_date(self.strategy_start_date, self.trade_list, 1) self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date(self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) # 重新初始化账户的cookie self.account.account_cookie = str(random.random()) # 初始化股票池的市场数据 if self.backtest_type in ['day', 'd', '0x00']: self.market_data = QA_fetch_stocklist_day( self.strategy_stock_list, [ self.trade_list[self.start_real_id - int(self.strategy_gap)], self.trade_list[self.end_real_id] ]) elif self.backtest_type in ['min', 'm', '0x01']: self.market_data = QA_fetch_stocklist_min( self.strategy_stock_list, [ self.trade_list[self.start_real_id - int(self.strategy_gap)], self.trade_list[self.end_real_id] ])
def get_index_weight(self, code, start, end): codex = [] if isinstance(code, list): pass else: code = [code] start = QA_util_get_real_date(start) end = QA_util_get_real_date(end) start = start[0:8] + '01' end = end[0:8] + '01' for coder in code: if '.' in coder: codex.append(coder) else: codex.append(coder + '.XSHE' if coder[0] == '6' else coder + '.XSHG') res = self.execute( "SELECT * FROM quantaxis.index_weight WHERE ((`date` >= '{}')) AND (`date` <= '{}') AND (`index_code` IN ({}))" .format(start, end, "'{}'".format( "','".join(codex)))).drop_duplicates(['date', 'order_book_id']) return res
#%% data = QA.QAFetch.QATdx.QA_fetch_get_stock_transaction('000001','2015-06-05','2015-06-06') data.index = pd.to_datetime(data.index) type(data.index[0])('2019-01-01') #%% data = QA.QAFetch.QATdx.QA_fetch_get_future_list() data['signal'] = data['code'].apply(lambda x:x[-2:]) data[data['signal'].isin(['L8','L9'])] 1300/8200 assert False STOCK_DAY = (['code', 'open', 'high', 'low','close', 'volume', 'amount', 'date'],'date') ['code','open'] in from QUANTAXIS.QAUtil import (DATABASE, QA_Setting, QA_util_date_stamp, QA_util_date_valid, QA_util_dict_remove_key, QA_util_log_info, QA_util_code_tostr, QA_util_date_str2int, QA_util_date_int2str, QA_util_sql_mongo_sort_DESCENDING, QA_util_time_stamp, QA_util_to_json_from_pandas, trade_date_sse,QA_util_dateordatetime_valid,QA_util_to_anyformat_from_pandas, QA_util_get_last_day,QA_util_get_next_day,QA_util_get_real_date) QA_util_time_stamp('2016-01-01 09:00:00') QA_util_time_stamp('2016-01-01') QA_util_time_stamp('2016-01-01 00:00:00') QA_util_get_real_date(QA_util_get_last_day('2019-07-01'), towards = -1) QA_util_get_real_date(QA_util_get_next_day('2019-07-01'), towards = 1)
def QA_fetch_daily_basic( code: Union[str, List, Tuple] = None, start: Union[str, pd.Timestamp, datetime.datetime] = None, end: Union[str, pd.Timestamp, datetime.datetime] = None, cursor_date: Union[str, pd.Timestamp, datetime.datetime] = None, fields: Union[str, Tuple, List] = None) -> pd.DataFrame: """获取全部股票每日重要的基本面指标,可用于选股分析、报表展示等 Args: code (Union[str, List, Tuple], optional): 指定股票代码或列表, 默认为 None,获取全市场 start (Union[str, pd.Timestamp, datetime.datetime], optional): 起始日期,默认为 None end (Union[str, pd.Timestamp, datetime.datetime], optional): 结束日期,默认为 None cursor_date (Union[str, pd.Timestamp, datetime.datetime], optional): 指定日期,与 start 和 end 冲突,只能选择 cursor_date 或者 start, end fields (Union[str, Tuple, List], optional): 指定 fields Returns: pd.DataFrame: 以日期,股票名为 Multiindex 的基本信息 """ if isinstance(code, str): code = (code, ) if not code: if (not start) and (not cursor_date): raise ValueError( "[ERROR]\tstart and end and cursor_date cannot all be none!") if not cursor_date: if not end: end_stamp = QA_util_date_stamp(datetime.date.today()) else: end_stamp = QA_util_date_stamp(end) start_stamp = QA_util_date_stamp(start) qry = { "trade_date_stamp": { "$gte": start_stamp, "$lte": end_stamp } } else: real_trade_date = QA_util_get_real_date(cursor_date) trade_date_stamp = QA_util_date_stamp(real_trade_date) qry = {"trade_date_stamp": trade_date_stamp} else: if (not start) and (not cursor_date): raise ValueError( "[ERROR]\tstart and end and cursor_date cannot all be none!") if not cursor_date: if not end: end_stamp = QA_util_date_stamp(datetime.date.today()) else: end_stamp = QA_util_date_stamp(end) start_stamp = QA_util_date_stamp(start) qry = { "code": { "$in": code }, "trade_date_stamp": { "$gte": start_stamp, "$lte": end_stamp } } else: real_trade_date = QA_util_get_real_date(cursor_date) trade_date_stamp = QA_util_date_stamp(real_trade_date) qry = {"code": {"$in": code}, "trade_date_stamp": trade_date_stamp} coll = DATABASE.daily_basic cursor = coll.find(qry) df = pd.DataFrame(cursor) if df.empty: return df df = df.rename(columns={"trade_date": "date"}).drop(columns="_id") df.date = pd.to_datetime( df.date).dt.tz_localize(None).dt.tz_localize('Asia/Shanghai') df = df.set_index(["date", "code"]).sort_index() if not fields: return df return df[fields]
def now_time_tradedate(): return str(QA_util_get_real_date(str(da.today() - timedelta(days=1)), trade_date_sse, -1)) + \ ' 17:00:00' if dt.now().hour < 15 else str(QA_util_get_real_date( str(da.today()), trade_date_sse, -1)) + ' 15:00:00'
def __QA_backtest_prepare(self): """ 这是模型内部的 初始化,主要是初始化一些账户和市场资产 写成了私有函数 @yutiansut 2017/7/20 """ self.strategy_stock_list = np.unique( self.strategy_stock_list).tolist() # 保证不会重复 if len(str(self.strategy_start_date)) == 10: self.strategy_start_time = str( self.strategy_start_date) + ' 15:00:00' elif len(str(self.strategy_start_date)) == 19: self.strategy_start_time = str(self.strategy_start_date) self.strategy_start_date = str(self.strategy_start_date)[0:10] else: self.__QA_backtest_log_info(self, 'Wrong start date format') if len(str(self.strategy_end_date)) == 10: self.strategy_end_time = str(self.strategy_end_date) + ' 15:00:00' elif len(str(self.strategy_end_date)) == 19: self.strategy_end_time = str(self.strategy_end_date) self.strategy_end_date = str(self.strategy_end_date)[0:10] else: self.__QA_backtest_log_info(self, 'Wrong end date format') # 重新初始账户资产 self.market = QA_Market(self.commission_fee_coeff) self.setting.QA_setting_init() self.account.init() self.account_d_value.append(self.account.init_assest) self.start_real_date = QA_util_get_real_date(self.strategy_start_date, self.trade_list, 1) self.start_real_time = str( self.start_real_date) + ' ' + self.strategy_start_time.split( ' ')[1] self.start_real_id = self.trade_list.index(self.start_real_date) self.end_real_date = QA_util_get_real_date(self.strategy_end_date, self.trade_list, -1) self.end_real_id = self.trade_list.index(self.end_real_date) self.end_real_time = str(self.end_real_date) + \ ' ' + self.strategy_end_time.split(' ')[1] # 重新初始化账户的cookie self.account.account_cookie = str(random.random()) # 初始化股票池的市场数据 if self.benchmark_type in ['I', 'index']: self.benchmark_data = QA_fetch_index_day_adv( self.benchmark_code, self.trade_list[self.start_real_id - 1], self.end_real_date) elif self.benchmark_type in ['S', 'stock']: self.benchmark_data = QA_fetch_stock_day_adv( self.benchmark_code, self.trade_list[self.start_real_id - 1], self.end_real_date) if self.backtest_type in ['day', 'd', '0x00']: self.market_data = QA_fetch_stocklist_day_adv( self.strategy_stock_list, self.trade_list[self.start_real_id - int(self.strategy_gap + 1)], self.trade_list[self.end_real_id]).to_qfq() elif self.backtest_type in ['1min', '5min', '15min', '30min', '60min']: self.market_data = QA_fetch_stocklist_min_adv( self.strategy_stock_list, QA_util_time_gap(self.start_real_time, self.strategy_gap + 1, '<', self.backtest_type), QA_util_time_gap(self.end_real_time, 1, '>', self.backtest_type), self.backtest_type).to_qfq() elif self.backtest_type in ['index_day']: self.market_data = QA_fetch_index_day_adv( self.strategy_stock_list, self.trade_list[self.start_real_id - int(self.strategy_gap + 1)], self.end_real_date) elif self.backtest_type in [ 'index_1min', 'index_5min', 'index_15min', 'index_30min', 'index_60min' ]: self.market_data = QA_fetch_index_min_adv( self.strategy_stock_list, QA_util_time_gap(self.start_real_time, self.strategy_gap + 1, '<', self.backtest_type.split('_')[1]), QA_util_time_gap(self.end_real_time, 1, '>', self.backtest_type.split('_')[1]), self.backtest_type.split('_')[1]) self.market_data_dict = dict( zip(list(self.market_data.code), self.market_data.splits())) self.market_data_hashable = self.market_data.dicts self.dirs = '.{}QUANTAXIS_RESULT{}{}{}{}{}'.format( os.sep, os.sep, self.topic_name, os.sep, self.stratey_version, os.sep) os.makedirs(self.dirs, exist_ok=True)