# Python 因子分析 # 因子分析是基于Auto-Trader Python Toolbox(以下简称atrader)的一项额外功能,专门用于因子的分析,其功能包括因子函数的编写,因子结果的计算,因子的分析结果展示等。 与策略的结构框架不一样,atrader没有使用复杂的事件驱动框架来实现,所以,因子分析不像策略,没有<font color=red>明确的账户、资金和持仓</font>的概念,也不存在在策略里常用的<font color=red>下单操作、资金查询、持仓信息查询、委托信息查询、成交信息查询、止盈止损</font>等操作,对应的API将<font color=red>**不允许**</font>在因子分析的功能中使用。 以下内容将着重描述因子分析的独特功能,其他部分请查阅[Python API说明](https://www.digquant.com.cn/at.php?mod=python) 以下API中带有”★” 的表示为只能在<font color=red>因子计算</font>中使用,无法在<font color=red>命令行</font>以及在<font color=red>策略函数</font>中使用 如仍无法解决您的问题,可以通过[社区](https://www.digquant.com.cn/forum.php?mod=forumdisplay&fid=3)、QQ群、电子邮件或者客服电话告诉我们,谢谢 # 因子函数的编写 # ### 从atrader中引入因子计算模块 ### ---------- atrader中的因子计算模块与策略模块不在同一个目录下,用户需引入 <font color=red>`atrader.calcfactor`</font> 这个模块。 **示例:引入因子计算模块** ```python # *_*coding:utf-8 *_* from atrader.calcfactor import * def init(context:ContextFactor): # 注册因子PE reg_factor(['PE']) def calc_factor(context: ContextFactor): # 获取注册的因子PE的数值 result = get_reg_factor(context.reg_factor[0], df=True) # 提取因子的数值 result = result['value'].values # 将结果转换为列 return result.reshape(-1,1) if __name__ == "__main__": # 投资域为上证50 run_factor(factor_name='example_factor', file_path='.', targets='SZ50', begin_date='2017-01-01', end_date='2017-03-01', fq=1) ``` 整个因子计算的步骤 1. 引入<font color=red>`atrader.calcfactor`</font> 这个模块 2. 设置初始化 `init函数` 3. 设置因子计算逻辑 [calc_factor函数](#calc_factor) ,并返回因子的数值序列 4. 因子计算入口 [run_factor](#run_factor) 处订阅投资域,设定计算的开始和结束时间 5. 执行计算 ### 初始化 ### ---------- 初始化是指通过 `init函数` 初始化处理,与策略的初始化操作一样,每次启动时都会先执行初始化的操作,且只会执行一次,具体操作可以见[策略的初始化](https://www.digquant.com.cn/at.php?mod=python#h2-atrader--14) ### 因子计算 ### ---------- 因子计算是指根据 [因子计算入口](#run_factor) 处指定的投资域,根据因子计算的具体逻辑,<font color=red>**按日频(交易日)**</font>计算每一个成分股标的的因子数值并返回过程。类似于策略,通过 [calc_factor函数](#calc_factor) 实现因子计算的整体逻辑,可以完成以下几个操作· **<font size=3>- 获取注册数据</font>** 通过 `get_reg_kdata` 获取注册的行情数据,使用方式与策略结构一样 通过 `get_reg_factor` 获取注册的因子数据,使用方式与策略结构一样 通过 `get_reg_userdata` 获取注册的外部数据,使用方式与策略结构一样 通过 `get_reg_userindi` 获取注册的自建函数结构,使用方式与策略结构一样 **<font size=3>- 获取因子自序列数值</font>** 在一些特点的场景中,因子数值的计算有时间序列上的依赖,本期的因子数值会依赖于过去的因子数值计算,类似于AR(1),因此需要专门的API来获取过往期数的因子数据,具体的使用请见[获取因子自序列数值](#get_auto_value)。 ### 返回因子数值 ### ---------- 因子计算函数必需将因子的结果返回,目前仅支持<font color=red>**shape为(n,1)的ndarray**</font>,其中n为投资域的成分股数量。 # 因子分析的结果 # 当因子的计算代码开始运行后,Auto-Trader(以下简称AT)的界面上会显示因子分析的结果,具体的分析结果解析,请见[新手指引-因子分析](#https://www.digquant.com.cn/documents/10)。 用户可以根据界面的指引和研究的需求,调整因子分析的参数,具体可参考[新手指引-因子分析](#https://www.digquant.com.cn/documents/10)。 # 重要概念 # <span id="context"></span> ### context —— 上下文对象 ### ---------- 类似于策略里的context对象,因子分析里也需要使用context作为上下文对象在不同函数之间传递。虽然两者都使用context作为上下文对象,但在应用时会有所不同。策略里的context为`Context对象`的实例化,因子分析里的context为`ContextFactor对象`的实例化,对比下,因子分析里的context会缺少一部分的属性和函数,主要为: **context.account —— 账户对象** **context.account_list —— 账户列表** <font color=red size=2>注意:当同时引入atrader与atrader.calc_factor时,由于context命名一样,会根据导入顺序,后者覆盖前者,导致运行出错!!</font> # 因子分析API介绍 # ## 基本函数 ## <span id="run_factor"></span> ### run_factor - 因子计算入口 ### ---------- **函数原型:** run_factor(factor_namee='', file_path='', targets='',begin_data='', end_date='', fq=1) **参数:** |参数名|类型|说明 |:-|:-|:-| |factor_name|str|因子名 |file_path|str|因子计算的文件路径 |targets|str|投资域简称,支持指数和行业的简称,其中'AllSecA'代表全A |begin_date|str or datetime.datetime|开始日期,使用'yyyy-mm-dd'格式,或者%Y-%m-%d格式 |end_date|str or datetime.datetime|结束日期,使用'yyyy-mm-dd'格式,或者%Y-%m-%d格式 |fq|int|复权类型,取值参考[FQ](#https://www.digquant.com.cn/at.php?mod=python#h3-fq--116),默认为不复权 **示例:** ```python run_factor(factor_name='example_factor', file_path='.', targets='SZ50', begin_date='2017-01-01',end_date='2017-03-01', fq=1) ``` **注意:** 1. <font color=red size=3>` factor_name `</font>会出现在AT的页面中,用于方便用户对不同因子进行区分 2. <font color=red size=3>` file_path `</font> 指具体运行的策略文件的具体路径,需要带文件的后缀名,如策略文件名为test,则需要填写为'test.py',可以使用`'.'`表示当前文件 3. 因子计算只支持<font color=red size=3>` 2007年1月1日 `</font>之后的数据 ## 因子计算 ## <span id="calc_factor"></span> ### ★ calc_factor - 因子计算主体函数 ### ---------- **函数原型:** calc_factor(context) **参数:** |参数名|类型|说明 |:-|:-|:-| |context|[context对象](#context)|上下文对象,为`ContextFactor对象`的实例化 **示例:** ```python def calc_factor(context: ContextFactor): # 获取注册的因子PE的数值 result = get_reg_factor(context.reg_factor[0], df=True) # 提取因子的数值 result = result['value'].values # 将结果转换为列 return result.reshape(-1,1) ``` **注意:** 1. <font color=red size=3>` calc_factor 函数 `</font>里不能执行注册数据的命令 2. <font color=red size=3>` calc_factor 函数 `</font>必须要设置返回值,返回格式为**shape为(n,1)的ndarray**</font>,其中n为投资域的成分股数量。 ## 因子数据获取 ## <span id="get_auto_value"></span> ### ★ get_auto_value - 获取因子自序列数据 ### ---------- **函数原型:** get_auto_value(length=1) **参数:** |参数名|类型|说明 |:-|:-|:-| |length|int|获取过往因子自序列的期数,默认为1 **返回:** pandas.DataFrame |key|类型|说明| |:-|:-|:-| |date|datatime.datetime|交易日| |code|str|标的代码| |target_idx |int|标的索引号| |value|float|因子数值| **示例:** ```python data = get_auto_value(length=2) ``` **注意:** 1. <font color=red size=3>` length=1 `</font>表示获取前1期的因子自序列数值。当获取过往期数的日期超过[因子计算入口](#run_factor)中定义的开始日期,则会返回`nan` 2. 若在 [calc_factor函数](#calc_factor) 里没有按照要求的数据格式返回时,通过 `get_auto_value` 返回的数值为`nan` # 示例 # ### 过去10天收益率因子 ### ---------- ```python """ @software: PyCharm @time: 2019/2/18 """ from atrader.calcfactor import * def init(context:ContextFactor): reg_kdata('day', 1)#注册日频数据 def calc_factor(context: ContextFactor): data = get_reg_kdata(reg_idx=context.reg_kdata[0],length=10, fill_up=True, df=True) #每只股票取10根Bar if data['close'].isna().any(): return np.repeat(np.nan,len(context.target_list)).reshape(-1,1)#如果数据长度不够,返回Nan值 data['open'] = data['open'].replace(0,np.nan) # 将停牌股票开盘价设为Nan last_day = data[9:len(context.target_list)*10:10].set_index('target_idx') #取第一天数据 first_day = data[0:len(context.target_list)*10:10].set_index('target_idx') #取第十天数据 factor = last_day['close']/first_day['open']-1 #计算10天的收益率,停牌的股票此时会算成Nan return np.array(factor).reshape(-1,1) #返回特定格式 if __name__ == "__main__": run_factor(factor_name='past_ten_day_return', file_path='.', targets='SZ50', begin_date='2017-01-01', end_date='2017-12-13', fq=1) ``` ### alpha 101 N日内的背离程度 ### ---------- ```python """ @software: PyCharm @time: 2019/2/26 """ from atrader.calcfactor import * import scipy.stats as st import numpy as np def init(context:ContextFactor): reg_kdata('day', 1) def calc_factor(context: ContextFactor): data = get_reg_kdata(reg_idx=context.reg_kdata[0], length=10, fill_up=True, df=True) # 每只股票取15根Bar if data['close'].isna().any(): return np.repeat(np.nan, len(context.target_list)).reshape(-1, 1) #时间不够长之前返回空值 data['open'] = data['open'].replace(0, np.nan) #识别停牌股票 data.dropna(inplace=True) #去掉停牌股票,否则会导致下一步报错 data['intraday_return'] = data['close'] / data['open'] - 1 factor = data.groupby('target_idx').apply( lambda x: st.spearmanr(x['intraday_return'], x['volume'])[0]).reset_index() # 针对每只股票的收盘价变化,和成交量变化求秩相关系数 factor.columns=['target_idx','factor'] #修改列名 if len(factor['target_idx'])!=len(context.target_list):#长度不一致的话需要补齐 temp = pd.DataFrame({'target_idx':list(range(len(context.target_list)))}) factor=temp.merge(factor,how='left',on='target_idx')#匹配长度 result = factor['factor'].values return result.reshape(-1, 1)#返回因子值 if __name__ == "__main__": run_factor(factor_name='correlation_return_volume', file_path='.', targets='SZ50', begin_date='2017-01-01', end_date='2017-12-13', fq=1) ``` ### 复合因子 ### ---------- ```python """ @software: PyCharm @time: 2019/02/27 """ # *_*coding:utf-8 *_* from atrader.calcfactor import * import numpy as np from numpy import NaN def init(context:ContextFactor): # 注册因子PE reg_factor(['PE','NegMktValue']) def calc_factor(context: ContextFactor): # 获取注册的因子PE, NegMktValue的数值 result = get_reg_factor(context.reg_factor[0], df=True) factor_data1 = result[result.factor=="PE"] factor_data1 =factor_data1.reset_index( drop=True ) factor_data1[factor_data1.value< 0] = NaN factor_data1['value'] = (factor_data1['value']-np.nanmean(factor_data1['value']))/np.nanstd(factor_data1['value']) factor_data1.rename(columns={"value": "PE"}, inplace=True) factor_data2 = result[result.factor=="NegMktValue"] factor_data2 =factor_data2.reset_index( drop=True ) factor_data2['value'] = (factor_data2['value']-np.nanmean(factor_data2['value']))/np.nanstd(factor_data2['value']) factor_data2.rename(columns={"value": "NegMktValue"}, inplace=True) res_m= pd.merge( factor_data1, factor_data2, how='left',on='target_idx' ) res_m['bind_score']= res_m['PE']+res_m['NegMktValue'] # 提取因子的数值 result = res_m['bind_score'].values # 将结果转换为列 return result.reshape(-1,1) if __name__ == "__main__": # 投资域为上证50 run_factor(factor_name='factor_demo_dqr', file_path='.', targets='SZ50', begin_date='2017-01-01', end_date='2017-03-01', fq=1) ```
contact@digquant.com.cn

联系

邮箱

0755-8695-2080

联系

电话

关注

微信

关注

QQ

回到

顶部