百天计划之37篇,关于“AI智能量化投研平台”搭建。
昨天我们把前端页面搭建完毕,可以展示简单的列表以及交易日频序列,这是最基础的第一步。
今天重点要实现列表的筛选。
筛选功能有基于基础信息的,比如市值,距离到日期还有多远,另外还有基于时间序列的,比如价格小于130,或者转股溢价率等等。
01 基础查询
到期日大于今天,且摘牌日期为空的,即为当前可以交易的,发行中的可转债列表,一共458支。
02 正股价与转股价
基础信息查询比较简单,而涉及的到日频数据的查询则相对复杂,比如我们需要最新的转股价,正股价,还是转债本身的价格。
若是基于mongo本身去查询,性能比较高,若涉及复杂计算,比如MACD>0这样的技术指标更慢。如果使用传统数据库,则需要做数据预计算,然后更新到basic表里去备查。但是这样做,就非常不灵活,一般我们的查询是“临时起意”。
这时,qlib的数据库就很好地派上用场了。
qlib的初始化函数:
def init_qlib(data_dir): provider_uri = data_dir qlib.init(provider_uri=provider_uri, region=REG_CN)
在web框架里调用,需要使用 app.on_event fastapi的装饰器,只会在启动时运行一次:
@app.on_event('startup') def init_app(): init_qlib(DATA_DIR_QLIB_BOND)
而后使用Qlib的数据查询,
def query_df(start_date, end_date): expressionDFilter = ExpressionDFilter(rule_expression='$close>130') instruments = D.instruments(market='all') df = D.features(instruments, ['$close', '$close<130','Ref($close,20)'], start_time=start_date, end_time=end_date, freq='day') print(df) return df
qlib最擅长的是时间序列计算,有预加载,缓存等功能,此外,它外针对财务数据,设计PIT格式(季度频次)。
不过无法跨库查询,需要使用的数据,均需要入qlib_data库。
不过就算使用mongodb这样的数据,若我们要使用全市场数据来回测“双低”策略,同样面临处理这样的数据。
读出所有的数据,然后对应的code去读其正股价时间序列,而后concat在一起,然后再分别计算各种指标。若是指定几支转债是没有问题的,但需要考虑全市场选债,这个对于mongo而言就太慢了。
03 构建正股信息
basic:
def build_stock_basic(): df = get_stock_basic() df['_id'] = df['ts_code'] write_df('stock_basic', df, drop_tb_if_exist=True)
A股一共4900+支股票。
daily:
这里与转债的时间序列数据类似:
def update_all_stock_daily(): # 获取所有列表,有日期,从最近的日期开始读。 items = list(get_db()['stock_basic'].find({}, {'ts_code': 1, '_id': 0})) if items and len(items) == 0: logger.error("读股票列表为空") return for i, item in enumerate(items): code = item['ts_code'] logger.debug("{}-{}-{}".format(i, code, i / len(items))) date = get_daily_last_date(code, tb_name='stock_daily', code_field='code', date_field='date') logger.debug(date) df = get_symbol_data_with_factor(code, date) df['_id'] = df['code'] + '_' + df['date'] print(df.tail()) write_df('stock_daily', df) break
04 难点:正股价如何整合到qlib_data中
def get_stock_df_from_mongo(code, start_date=None): query_stock = {'code': '601818.SH'} if start_date: query_stock['date'] = {'$gte': start_date} df_stock = get_db()['stock_daily'].find(query_stock, {'o_close': 1, 'date': 1, '_id': 0}) df_stock = pd.DataFrame(list(df_stock)) df_stock.index = df_stock['date'] del df_stock['date'] df_stock.rename(columns={'o_close': 'stk_close'}, inplace=True) return df_stock
把正股价读进来,与转债的数据融合后入qlib。
由于转债数量不多,可以每天全量建索引也问题不大。增量的话,记录本次update的日期。
小结:
1、今天完成了转债数据的基础查询,更重要的是,多维度数据整合到qlib数据。
2、坚持并不容易,越早先的工作越是“低垂”之果,越往后越有难度,进入“爬坡”期。
可转债列表页与日频交易数据呈现:fastapi+antV G2
fastapi定时任务,增量构建可转债交易数据入mongo和qlib
fastapi+mongo+qlib:体系化构建AI量化投研平台
飞狐,科技公司CTO,用AI技术做量化投资;以投资视角观历史,解时事;专注个人成长与财富自由。