多因子策略
因子
因子就是在选择一只股票时,能够帮助你做出决定的一个因素
类型 | |
---|---|
规模因子 | 1. 总市值 2. 流通市值 3. 自由流通市值 4. 小市值因子(市值越小,其操纵涨跌所需要的资金越少,股票被操纵的可能性就越大) |
估值因子 | 1. 市盈率(TTM) 2. 市净率 3. 市销率 4. 市现率 5. 企业价值倍数 |
成长因子 | 1. 营业收入同比增长率 2. 营业利润同比增长率 3. 归属于母公司的近利润同比增长率 4. 经营活动产生的现金流金额同比增长率 |
盈利因子 | 1. 净资产收益率(ROE) 2. 总资产报酬率(ROA) 3. 销售毛利率 4. 销售净利率 |
动量反转因子 | 指的是单个标的涨跌幅度的反转效应明显(简单地说,就是涨得多就要跌,跌得多就要涨,远离要回归,价格归于价值。这个其实就是在股市里说得补涨补跌) 1. 前一个月涨跌幅 2. 前2个月涨跌幅 3. 前3个月涨跌幅 4. 前6个月涨跌幅 |
交投因子 | 1. 前一个月日均换手率 |
波动因子 | 1. 前一个月的波动率 2. 前一个月的振幅 |
股东因子 | 1. 户均持股比例 2. 户均持股比例变化 3. 机构持股比例变化 |
一致性预测因子 | 1. 研报或者分析师预测当年净利润增长率 2. 主营业务收入增长率 3. 最近一个月预测净利润上调幅度 4. 最近一个月预测主营业务收入上调幅度 5. 最近一个月上调评级占比 预测收入增长的越高越好,净利润增长的越高越好,支出费用越低越好 |
选取因子
选取股票池
get_history_constituents(index, start_date=None, end_date=None)
参数名 | 类型 | 说明 |
---|---|---|
index | str | 指数代码 |
start_date | str or datetime.datetime or None | 开始时间 (%Y-%m-%d 格式) 默认 None 表示当前日期 |
end_date | str or datetime.datetime or None | 结束时间 (%Y-%m-%d 格式) 默认 None 表示当前日期 |
函数返回的数据每月发布一次,故返回的数据是月频数据,trade_date为各月最后一天
from gm.api import *
symbol_list = get_history_constituents(index="SHSE.000016", start_date='2017-07-10')
参数名 | 类型 | 说明 |
---|---|---|
constituents | dict | 股票代码作为key, 所占权重作为value的键值对 |
trade_date | datetime.datetime | 交易日期 |
import pprint
pprint.pprint(symbol_list[0])
{'constituents': {'SHSE.600000': 3.3299999237060547,
'SHSE.600016': 4.510000228881836,
'SHSE.600028': 1.4199999570846558,
'SHSE.600029': 0.6299999952316284,
'SHSE.600030': 3.0299999713897705,
'SHSE.600036': 5.849999904632568,
'SHSE.600048': 1.659999966621399,
'SHSE.600050': 1.399999976158142,
'SHSE.600100': 0.550000011920929,
'SHSE.600104': 2.3399999141693115,
'SHSE.600111': 0.8999999761581421,
'SHSE.600340': 0.8100000023841858,
'SHSE.600485': 0.5699999928474426,
'SHSE.600518': 1.3700000047683716,
'SHSE.600519': 5.360000133514404,
'SHSE.600547': 0.5299999713897705,
'SHSE.600606': 0.6399999856948853,
'SHSE.600837': 2.6700000762939453,
'SHSE.600887': 2.7799999713897705,
'SHSE.600919': 0.25,
'SHSE.600958': 1.1299999952316284,
'SHSE.600999': 0.9100000262260437,
'SHSE.601006': 1.149999976158142,
'SHSE.601088': 0.8500000238418579,
'SHSE.601166': 4.909999847412109,
'SHSE.601169': 2.5299999713897705,
'SHSE.601186': 1.3300000429153442,
'SHSE.601198': 0.4399999976158142,
'SHSE.601211': 2.0899999141693115,
'SHSE.601229': 0.3799999952316284,
'SHSE.601288': 3.1500000953674316,
'SHSE.601318': 12.5,
'SHSE.601328': 3.9000000953674316,
'SHSE.601336': 1.059999942779541,
'SHSE.601390': 1.4600000381469727,
'SHSE.601398': 2.640000104904175,
'SHSE.601601': 2.380000114440918,
'SHSE.601628': 1.0199999809265137,
'SHSE.601668': 3.4200000762939453,
'SHSE.601688': 1.440000057220459,
'SHSE.601766': 2.180000066757202,
'SHSE.601788': 0.6600000262260437,
'SHSE.601800': 0.5600000023841858,
'SHSE.601818': 1.4900000095367432,
'SHSE.601857': 0.8799999952316284,
'SHSE.601881': 0.17000000178813934,
'SHSE.601901': 0.8100000023841858,
'SHSE.601985': 0.8100000023841858,
'SHSE.601988': 1.8300000429153442,
'SHSE.601989': 1.309999942779541},
'trade_date': datetime.datetime(2017, 7, 31, 0, 0, tzinfo=tzfile('PRC'))}
从财务数据表提取因子
查询基本面数据最新n条
get_fundamentals_n(table, symbols, end_date, fields=None, filter=None, order_by=None, count=1, df=False)
参数
参数名 | 类型 | 说明 |
---|---|---|
table | str | 表名. 具体表名及fields字段名及filter可过滤的字段参考 财务数据文档 |
symbols | str | 标的代码, 多个代码可用 ,(英文逗号)分割, 也支持 [‘symbol1’, ‘symbol2’] 这种列表格式 |
end_date | str | 结束时间, (%Y-%m-%d 格式) |
fields | str | 查询字段 (必填) |
filter | str | 查询过滤,使用方法参考get_fundamentals的例3、例4 |
count | int | 每个股票取最近的数量(正整数) |
df | bool | 是否返回dataframe格式, 默认False, 返回list[dict] |
from gm.api import *
set_token("61c4ec11af460c782950cd5ed41faacd5ac560f9")
symbol_list = get_history_constituents(index="SHSE.000016", start_date='2017-07-10')[0].get("constituents").keys()
df = get_fundamentals_n(table="deriv_finance_indicator", symbols=symbol_list, end_date='2017-07-10', fields="NPGRT", count=1, df=True)
print(df)
deriv_finance_indicator
衍生财务指标
NPGRT
归属母公司净利润增长率
返回值
key | value类型 | 说明 |
---|---|---|
symbol | str | 标的代码 |
pub_date | datetime.datetime | 公司发布财报的日期. |
end_date | datetime.datetime | 财报统计的季度的最后一天. |
fields | dict | 相应指定查询 fields 字段的值. 字典key值请参考 财务数据文档 |
对因子进行排序
df = df.sort_values(["NPGRT"], ascending=False)
print(df.head(5))
symbol pub_date end_date NPGRT
38 SHSE.601857 2017-08-25 00:00:00+08:00 2017-06-30 00:00:00+08:00 2300.3789
37 SHSE.600111 2017-08-18 00:00:00+08:00 2017-06-30 00:00:00+08:00 258.2722
22 SHSE.601088 2017-08-26 00:00:00+08:00 2017-06-30 00:00:00+08:00 147.4054
12 SHSE.601006 2017-08-30 00:00:00+08:00 2017-06-30 00:00:00+08:00 107.1203
8 SHSE.600050 2017-08-17 00:00:00+08:00 2017-06-30 00:00:00+08:00 74.3397
单因子选股轮动测试
- 股票池选用上证50的成分股
- 选择股票池中净利润增长率排名前5的5家公司
- 每个月进行调仓,调出排名跌出前5的公司,重新买入进入排名前5的公司
# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
import os
# 策略中必须有init方法
def init(context):
context.index = "SHSE.000016"
context.num = 5
schedule(schedule_func=algo, date_rule="1m", time_rule="09:31:00")
def algo(context):
now = context.now
order_close_all()
symbol_list = get_history_constituents(index=context.index, start_date=now)[0].get("constituents").keys()
df = get_fundamentals_n(table="deriv_finance_indicator", symbols=symbol_list, end_date=now, fields="NPGRT", count=1, df=True)
df = df.sort_values(["NPGRT"], ascending=False)
target_list = df["symbol"].values
target_list = target_list[:context.num]
for symbol in target_list:
order_target_percent(symbol=symbol, percent= 1./context.num, order_type=OrderType_Market, position_side=PositionSide_Long)
def on_backtest_finished(context, indicator):
print(indicator)
if __name__ == '__main__':
run(strategy_id='xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
filename='main.py',
mode=MODE_BACKTEST,
token='xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
backtest_start_time = '2016-01-01 09:00:00',
backtest_end_time='2018-06-25 15:00:00',
backtest_initial_cash=10000000,
backtest_adjust= ADJUST_PREV
)