量化投资策略与技术学习PART1:量化选股之再谈多因子模型

量化选股就是利用数量化的方法选择股票组合,期望该股票组合能够获得超越基准收益率的投资行为。量化选股策略总的来说可以分为两类:第一类是基本面选股;第二类是市场行为选股。
本章中基本面选股介绍了多因子模型、风格轮动模型和行业轮动模型;市场行为选股介绍了资金流模型、动量反转模型、一致预期模型、趋势追踪模型和筹码选股模型。
多因子选股模型基本原理是采用一系列的因子作为选股标准,满足这些因子的股票则被买入,不满足的则卖出。多因子模型相对来说比较稳定,因为在不同的市场条件下,总有一些因子会发挥作用。
风格轮动选股模型是利用市场的风格特征进行投资,比如有时候市场偏好于小盘股,有时候偏好于大盘股,如果是在风格转换的初期介入,则可以获取较大的超额收益。
行业轮动与风格轮动类似,由于经济周期的原因,总有一些行业先启动,有的行业跟随。在经济周期过程中,依次对这些轮动的行业进行配置,则比买入持有策略有更好的效果。
资金流选股的基本思想是利用资金的流向来判断股票的涨跌,如果资金流入,则股票价格应该上涨;如果资金流出,则股票价格应该下跌。所以将资金流入流出情况编成指标,则可利用该指标来判断在未来一段时间股票价格的涨跌情况。
动量反转模型是指股票的强弱变化情况,过去一段时间强势的股票在未来一段时间继续保持强势,过去一段时间弱势的股票在未来一段时间继续保持弱势,这叫做动量效应。过去一段时间强势的股票在未来一段时间会走弱,过去一段时间弱势的股票在未来一段时间会走强,这叫做反转效应。如果判断动量效应会持续,则应该买入强势股;如果判断会出现反转效应,则应该买入弱势股。
一致性预期是指市场上的投资者可能会对某些信息产生一致的看法。比如大多数分析师看好某只股票,可能这只股票的价格在未来一段时间会上涨;如果大多数分析师看空某只股票,可能这只股票的价格在未来一段时间会下跌。一致性预测策略就是利用大多数分析师的看法来进行股票买卖的操作。
趋势追踪属于图形交易的一种,就是当股价出现上涨趋势的时候,则追涨买入;当股价出现下跌趋势的时候,则杀跌卖出,其本质上是一种追涨杀跌的策略。判断趋势的指标有很多种,包括MA、EMA、MACD等其中最简单也是最有效的是均线策略。
筹码选股是另外一种市场行为策略,其基本思想是:如果主力资金要拉升一只股票,则会慢慢收集筹码;如果主力资金要卖出一只股票,则会慢慢分派筹码。所以根据筹码的分布和变动情况,就可以预测股票价格未来是上涨还是下跌。

有关量化选股业绩评价要从两方面来考虑:一个是收益率,另一个是风险指数(最大回撤)。量化选股需要考虑的是在承担多大的风险情况下的收益率情况(夏普比)

夏普比率衡量基金的风险收益比,即每承受一单位总风险,可以相较无风险利率产生多少超额收益。因此,夏普比率越大,代表基金的收益风险表现越好。夏普比率 =(基金年化收益率 - 无风险利率) / 基金年化波动率。举例来说,如果基金A的夏普比率为0.5,而同类型基金的平均夏普比率为0.2,则意味着基金A的风险收益表现优于同类型基金的平均水平。

多因子模型

在前面我们已经讲过一次多因子模型,这回我们再深入学习一下这个策略。
市场上的投资者,不管是价值投资者,还是投机者,或者短线交易者,都会根据某些因子来判断股票的涨跌。当有一群交易者同时采用某个因子的时候,就会造成该因子有效。例如,当很多投资者认为低PE的价值型股票是好的投资标的时,他们纷纷买入低PE的股票,会使得该股票价格出现上涨,或者超越市场。这样就使得低PE这个因子的有效性得以体现,这就是一个自我证实的过程。本节的多因子模型就是要研究市场上哪些因子对最终收益率的作用比较大,他们在不同市场阶段的表现如何。

基本概念

多因子模型的优点是能够综合很多信息最后得出一个选股结果。各种多因子模型的核心区别一是因子的选取,二是在如何用多因子综合得到一个最终的判断。
一般而言,多因子选股模型有两种判断方法:一是打分法;二是回归法。
打分法就是根据各个因子的大小对股票进行打分,然后按照一定的权重加权得到一个总分,根据总分再对股票进行筛选。打分法根据加权方法不同又可以分为静态加权和动态加权。打分法的优点是相对比较稳健,不容易受到极端值的影响。
回归法就是用过去的股票的收益率对多因子进行回归,得到一个回归方程,然后把最新的因子值代入回归方程得到一个对未来股票收益的预判,最后以此作为依据进行选股。回归法的优点是能够比较及时地调整股票对各因子地敏感性,而且不同的股票对不同因子的敏感性也可以不同。回归法的缺点是容易受到极端值的影响,在股票对因子敏感度变化较大的市场情况下效果也比较差。

策略模型

多因子选股模型的建立过程主要分为候选因子的选取、选股因子有效性的校验、有效但冗余因子的剔除、综合评分模型的建立和模型的评价及持续改进5个步骤

1、候选因子的选取

候选因子可以是基本面指标,也可以是技术面指标,还可以是一下其他辅助指标,候选因子的选择主要依赖于经济逻辑和市场经验,但选择更多和更有效的因子无疑是增强模型信息捕获能力、提高收益的关键因素之一。

2、选股因子有效性的校验

一般检验方案主要采用排序的方法检验候选因子的选股有效性。具体而言,对于任意一个候选因子,在模型形成期的第一个月初开始计算市场上每只正常交易股票的该因子的大小,按照从小到大的顺序对样本股票进行排序,并平均分为n个组合,一直持有到月末,在下月初再按照同样的方法重新构建n个组合并持有到月末,每月如此,一直重复到模型形成期末。
组合构建完毕后,计算这N个组合的年化复合收益、相对业绩基准的超出收益、在不同市场状况下的高收益组合跑赢基准和低收益组合跑输基准的概率等。

3、有效但冗余因子的剔除

不同的选股因子可能由于内在的驱动因素相同等原因,所选出的组合在个股构成和收益等方面具有较高的一致性,因此其中的一些因子需要作为冗余因子剔除,而只保留同类中收益最好、区分度最高的因子。

4、综合评分模型的建立

根据模型所得出的综合平均分对股票进行排序,然后根据需要选择排名靠前的股票

5、模型的评价及持续改进

一方面,由于量化选股方法是建立在市场无效或弱有效的前提之下的,随着使用多因子选股模型的投资者数量的不断增加,有些因子会逐渐失效,而另一些新的因子可能被校验有效而加入到模型中;另一方面,一些因子可能在过去的市场环境下比较有效,而随着市场风格的改变,这些因子可能在短期内失效,而另外一些以前无效的因子会在当前市场环境下表现更好。

实战练习

首先建立了一个Multi_factor_stock_selection.py文件,用于存储选股函数

# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
import pandas as pd
import numpy as np
import datetime
"""
《量化投资策略与技术》:量化选股——多因子选股
多因子选股模型的建立过程主要分为候选因子的选取、选股因子有效性的校验、有效但冗余因子的剔除、综合评分模型的建立和模型的评价及持续改进5个步骤
STEP0:建立股票资源池,获取股票代码列表get_symbol_list_all()
STEP1:
STEP2:
STEP3:
STEP4:
STEP5:
"""


"""
函数名:get_symbol_list_all():
输入参数:null
输出参数:target_symbol_list 数据类型:list
函数作用:获取指定指数全部的成分股代码,目前这里选取了上证和中证几个重要的指数建立了股票资源池:可参考文章:https://blog.csdn.net/qq_26285867/article/details/140749688
"""
def get_symbol_list_all():

    A_share_list = {"SHSE.000010": "SHANG_ZHENG180", "SHSE.000009": "SHANG_ZHENG380", "SHSE.000300": "HU_SHEN300",
                     "SHSE.000905": "ZHONG_ZHENG500", "SHSE.000906": "ZHONG_ZHENG800","SHSE.000852": "ZHONG_ZHENG1000"}
    A_share_main = {"600", "601", "602", "603", "000", "001", "002", "003"} #沪深主板股票代码的开头
    symbol_list_all = pd.DataFrame([])
    for key in A_share_list.keys():
        symbol_list = stk_get_index_constituents(key)  # 获取指数成分股数据
        symbol_list_all = pd.concat([symbol_list_all, symbol_list], ignore_index=True)
        # symbol_list_all =symbol_list_all.append(symbol_list)  #新语句中append已经弃用
    symbol_set = symbol_list_all["symbol"].values
    target_symbol_list= []
    for symbol in symbol_set:#从股票池中寻找主板股票
        if symbol[5:8] in A_share_main and symbol not in target_symbol_list:
            target_symbol_list.append(symbol)
    print("沪深主板股票资源池数量",len(target_symbol_list))
    return target_symbol_list
"""
函数名:sort_symbol_by_finance_prime(symbol_list,time,filed,n = 5)
输入参数:symbol_list 数据类型:list 初始股票清单
输入参数:time 查询财务主要指标的时间
输入参数:filed 查询财务主要指标标的
输入参数:n 获得的目标股票个数
输出参数:target_symbol_top,target_symbol_down 输出排序前n个的股票及排序后n个的股票
函数作用:根据主要财务指标对股票池中的股票进行排序,输出前n个股票及后n个股票
"""
def sort_symbol_by_finance_prime(symbol_list,time,filed,n = 5):
    last_day = get_previous_trading_date("SHSE",time)
    choose_symbol_list = []
    data = stk_get_finance_prime_pt(symbols=symbol_list, fields=filed, rpt_type=None, data_type=None, date=last_day, df=True)
    finance_prime = data.sort_values(filed,ascending=False) #根据选择的因子对股票进行排序
    finance_prime = finance_prime.dropna() #删除无效数据
    finance_prime = finance_prime.reset_index(drop=True) #重置索引值
    print(finance_prime)
    target_list = finance_prime["symbol"].values #获得排序后的股票代码清单
    target_symbol_top = target_list[:n] #取列表中前5只作为标的股票
    target_symbol_down = target_list[-n:]  # 取列表中前5只作为标的股票
    print(target_symbol_top)
    print(target_symbol_down)
    return target_symbol_top,target_symbol_down


# 可以直接提取数据,掘金终端需要打开,接口取数是通过网络请求的方式,效率一般,行情数据可通过subscribe订阅方式
# 设置token, 查看已有token ID,在用户-密钥管理里获取
set_token('自己的token码')
# 查询历史行情, 采用定点复权的方式, adjust指定前复权,adjust_end_time指定复权时间点
day_time, hour_and_mins = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')).split(" ")  # Python time.strftime() 函数用于格式化时间,返回以可读字符串表示的当地时间;详细用法见 https://www.runoob.com/python/att-time-strftime.html
symbol_list = get_symbol_list_all()
filed = ["eps_basic"]
sort_symbol_by_finance_prime(symbol_list,day_time,filed)

回测中比较有效的基本面因子

我选择的掘金终端进行回测,所以以下分类和代号也是参考掘金终端中的分类方式,同时部分指标有可能是因为获取的数据不全而剔除,并未是因为因子无效而剔除,回测函数的代码如下:

# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
import os
import Multi_factor_stock_selection


def init(context):
    # 在init函数中设置全局变量
    # algo执行定时任务函数,只能传context参数
    # index股票池代码,沪深300
    # num买卖股票数据,暂定5只
    # schedule在指定时间自动执行策略算法, 通常用于选股类型策略,每月一次,早上9点31分执行定时任务
    # date_rule执行频率,目前暂时支持1d、1w、1m,其中1w、1m仅用于回测,实时模式1d以上的频率,需要在algo判断日期
    # time_rule执行时间, 注意多个定时任务设置同一个时间点,前面的定时任务会被后面的覆盖
    context.num = 50
    context.filed = ["roa"]
    schedule(schedule_func=algo, date_rule='1m', time_rule='09:31:00') #设置回测方式,定时任务
def algo(context):
    now = context.now #获取当前时间
    order_close_all() #这里为例简化,全部清仓上一阶段股票
    symbol_list = Multi_factor_stock_selection.get_symbol_list_all()
    target_symbol_top, target_symbol_down = Multi_factor_stock_selection.sort_symbol_by_finance_deriv_pt(symbol_list,now,context.filed,context.num)
    # for symbol in target_symbol_down:#买入排名后5名的股票
    for symbol in target_symbol_top: #买入排名前5名的股票
        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__':
    '''
    strategy_id策略ID,由系统生成
    filename文件名,请与本文件名保持一致
    mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    token绑定计算机的ID,可在系统设置-密钥管理中生成
    backtest_start_time回测开始时间
    backtest_end_time回测结束时间
    backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    backtest_initial_cash回测初始资金
    backtest_commission_ratio回测佣金比例
    backtest_slippage_ratio回测滑点比例
    backtest_match_mode市价撮合模式,以下一tick/bar开盘价撮合:0,以当前tick/bar收盘价撮合:1
    '''
    run(strategy_id='自己的策略ID',
        filename='Multi_factor_stock_selection_test.py',
        mode=MODE_BACKTEST,
        token='自己的token码',
        backtest_start_time='2021-03-01 09:00:00',
        backtest_end_time='2023-03-01 15:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=100000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001,
        backtest_match_mode=1)

我首先试了一下选择top5的股票进行买卖,回测区间为2021年8月1日到2022年8月10日这个时间段,但是发现这个里边随机的因素太大了,有的摊到了一只好的股票比如”九安医疗“,整个收益率显得非常高,而我其实想选择的是一个较大概率的事件,因此我后期又把选择的买入的股票提升到50只,相当于建立一个该因子的指数成分股,买卖区间改为2021年3月1日到2023年3月1日,整个沪深300单边下跌的市场(与目前2024年8月的市场情况基本差不多),重新进行回测。
通过回测我发现基本没有哪个参数是非常有效的,甚至有的指标和认知完全不同,ROE指标竟然是低的收益率更高一些,看来用单因子选股这个方案并不是十分靠谱。一些增长率指标还是要好于ROE这种绝对指标,看来市场还是更加关注变化量,而不是很关心绝对值的大小。
,其中比较好的有以下两个:

分类名称代号前5名收益率前5名回撤后5名收益率后5名回撤
财务衍生指标稀释每股收益同比增长率eps_dil_yoy7.27%-26.26%-10.23%-34.22%
财务衍生指标EBIT(正推法)ebit18.26%-18.8%-4.37%-32.18%

后续等有时间我再将多个因子融合试一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值