Python量化交易学习——Part4:基于基本面的单因子选股策略

本文介绍了Python量化交易中基于基本面的单因子选股策略。通过选取净利润增长率作为因子,建立沪深300股票池,对股票进行排序并选择排名靠前的公司进行买入。实测结果显示,该策略的收益率优于沪深300基准,显示出因子的有效性。
摘要由CSDN通过智能技术生成

技术分析与基本面分析是股票价格分析最基础也是最经典的两个部分。技术分析是针对交易曲线及成交量等指标进行分析,基本面分析是基于公司的基本素质进行分析。
一般来说选股要先选行业,在选个股,之后根据技术分析选择买卖节点,因此针对行业及个股的基本面分析是选股的基础。

常用选股因子

在选择股票的时候,首先要找到的就是可以帮你做出决定的因素,如净利润/ROE/净利润增长率等,这些被称为因子。

因子实例
规模因子如总市值、流通市值、自由流通市值等;市值越小,其操作涨跌所需要的资金越少,股票就越容易暴涨暴跌。
估值因子市盈率(TTM)、市净率、市销率、市现率、企业价值倍数等
成长因子营业收入同比增长率、营业利润同比增长率等
盈利因子净资产收益率(ROE)、总资产报酬率、销售毛利率,销售净利率
动量反转因子前一个月涨跌幅、前两个月涨跌幅等
交投因子前一个月日均换手率
波动因子前一个月波动率、前一个月振幅
股东因子户均持股比例、户均持股比例变化、机构持股比例变化
一致性预测因子如研报或分析师预测当年净利润增长率、最近一个月预测净利润上调幅度等

可以选择一些自己常用的因子,比如净利润增长率、市盈率等,一个一个计算不同因子的收益,看看效果如何,效果好的就留下下,效果不好的则剔除选择下一个继续测算。

应用实例

建立股票池

首先应该建立相应的股票池,才能用的上述因子对股票进行分析。在这里我们先采用股指组成的成分股来作为股票池,首先是通过对应函数获取对应股指的成分股。——获取成分股数据

stk_get_index_constituents(index, trade_date=None)

在这里插入图片描述
以沪深300为例,指数代码为SHSE.000300,我们可以通过如下代码提取其成分股数据,并将其保存到表格中

import gm.api as gm
import numpy as np

gm.set_token("自己的token码")  # 输入自己的token
index = "SHSE.000300"
HS300_array = gm.stk_get_index_constituents(index='SHSE.000300')
HS300_array.to_csv("HS300_list.csv")

运行结果如下:
在这里插入图片描述
我们可以通过np.asarray函数提取成分股股指的代码:

import gm.api as gm
import numpy as np

gm.set_token("自己的token码")
index = "SHSE.000300"
HS300_array = gm.stk_get_index_constituents(index='SHSE.000300')
HS300_array.to_csv("HS300_list.csv")
HS300_symbol_array = HS300_array['symbol'].values #方法1
#HS300_symbol_array = HS300_array.get("symbol")   #方法2
HS300_symbol_list = list(HS300_symbol_array)
print(HS300_symbol_list)

打印结果如下:
在这里插入图片描述
至此,我们的股票池已经建立起来了,保存在HS300_symbol_list数组中,之后我们便通过各个因子对股票池里的股票进行分析,找到我们需要买入的大牛股。

选择因子

掘金量化提供的财务数据分析因子可以在帮助文档中查找(掘金量化财务数据函数)
我们以衍生财务指标中的净利润同比增长率(net_prof_yoy)为研究因子,对沪深300指数的成分股进行分析,查询衍生财务数据的函数有两个:

stk_get_finance_deriv(symbol, fields, rpt_type=None, data_type=None, start_date=None, end_date=None, df=False) #查询单个股票的衍生财务数据
stk_get_finance_deriv_pt(symbols, fields, rpt_type=None, data_type=None, date=None, df=False) #查询多个股票的衍生财务数据

在这里插入图片描述
在这里插入图片描述
对沪深300成分股净利润增长率分析的代码如下:

import gm.api as gm
import numpy as np
import datetime

gm.set_token("自己的token码")
index = "SHSE.000300"
HS300_array = gm.stk_get_index_constituents(index='SHSE.000300')
HS300_array.to_csv("HS300_list.csv")
HS300_symbol_array = HS300_array['symbol'].values #方法1
#HS300_symbol_array = HS300_array.get("symbol")   #方法2
HS300_symbol_list = list(HS300_symbol_array)
print(HS300_symbol_list)

# net_prof_yoy 净利润同比增长率
day_time,hour_and_mins = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')).split(" ")  #调用datetime函数获取最新时间
NPGRT = gm.stk_get_finance_deriv_pt(symbols=HS300_symbol_list,fields="net_prof_yoy",date=day_time,df=True)
print(NPGRT.head(5))  #打印头5条数据

执行结果如下,我们打印出了头5条成分股的净利润增长率,net_prof_yoy这列就是:
在这里插入图片描述

对单因子进行排序

对应净利润增长率来说,肯定是越高越好,因此我们需要根据因子对成分股进行排序,选择出我们需要的大牛股。
这里我们只需要在上边程序中增加如下代码

# sort_values函数是对array内部的数据进行排序的函数,ascending=False决定了排序方式是从大到小;
NPGRT = NPGRT.sort_values(["net_prof_yoy"],ascending=False)
print(NPGRT.head(5))

运行结果如下:
在这里插入图片描述
可以看到股票已经根据净利润增长率从大到小进行排列。

单因子选股测试

我们采用以下策略对单因子选股策略进行测试
(1)股票池选择沪深300指数成分股;
(2)选择股票池中净利润增长率排名前5的5家公司进行买入
(3)每个月进行调仓,调出排名跌出前5名的公司,重新买入进入前5名的公司;

以上任务为定时买卖任务,因此我们可以以一个定时策略为模板,建立一个空策略,之后将代码复制到pycharm中进行修改,其中要注意的是,.py文件名需要和pycharm中新建的文件名保持一致,可以看我代码的备注;

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

#init函数是回测框架的初始化函数,可以设置大量的初始化内容
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.index = "SHSE.000300"
    context.num = 5
    schedule(schedule_func=algo, date_rule='1m', time_rule='09:31:00') #设置回测方式,schedule_func 是回测主调用函数,回测主内容写在此处,date_rule是基于回测的时间周期,time_rule是每个时间周期中具体执行的时间点
    
def algo(context):
    now = context.now #获取当前时间
    day_time, hour_and_mins = str(now.strftime('%Y-%m-%d %H:%M:%S')).split(" ")   #  Python time.strftime() 函数用于格式化时间,返回以可读字符串表示的当地时间;详细用法见 https://www.runoob.com/python/att-time-strftime.html
    order_close_all() #这里为例简化,全部清仓上一阶段股票
    HS300_array = stk_get_index_constituents(index=context.index) # 获取沪深300成分股
    HS300_symbol_list = list(HS300_array.get("symbol"))  #将格式转换为list形式
    NPGRT = stk_get_finance_deriv_pt(symbols=HS300_symbol_list, fields="net_prof_yoy", date=day_time, df=True) # 获取沪深300成分股的净利润增长率
    NPGRT_sort = NPGRT.sort_values(["net_prof_yoy"],ascending=False) #对净利润增长率进行排序
    target_list = NPGRT_sort["symbol"].values #获得排序后的股票代码清单
    target_symbol = target_list[:context.num] #取列表中前5只作为标的股票
    for symbol in target_symbol:
        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',    #此次需要写入自己的策略ID
        filename='dan_yin_zi_xuan_gu.py',
        mode=MODE_BACKTEST,
        token='自己的token码',   #此次需要写入自己的token
        backtest_start_time='2020-01-01 09:00:00',
        backtest_end_time='2024-05-31 15:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=10000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001,
        backtest_match_mode=1)

在这里插入图片描述
当我们看到以上运行结果的时候,就证明程序已经开始执行了,这个程序执行时间比较长(我这里耗时约52s),最终回测结果我们可在掘金量化软件中进行查看。
在这里插入图片描述
从回测结果可以看出,沪深300基准收益率为-12.61%,而我们的单因子策略的收益率为+4.65%,跑赢了沪深300。说明这个因子有可能有效,我们可以在通过更多的样本进行回测,以确认方案有效的概率,之后再执行该策略。

函数讲解

在上文中,我们用到了这个买入函数

order_target_percent(symbol=symbol,percent=1/context.num,order_type=OrderType_Market,position_side=PositionSide_Long)  #执行买入操作

这个函数的作用是 调仓到目标持仓比例(总资产的比例),函数原型如下:

order_target_percent(symbol, percent, position_side, order_type, price=0, order_duration=OrderDuration_Unknown, order_qualifier=OrderQualifier_Unknown, account='')

在这里插入图片描述

# position_side 持仓方向
PositionSide_Long = 1                        # 多方向
PositionSide_Short = 2                       # 空方向
#order_type 订单委托类型
OrderType_Limit = 1            # 限价委托 (全部交易所支持)
OrderType_Market = 2           # 市价委托 (上期所和上能所不支持,中金所远期合约不支持,可转债不支持,上交所需要填上price保护限价)
# order_duration 委托时间属性
OrderDuration_FAK = 1           # 即时成交剩余撤销(fill and kill)
OrderDuration_FOK = 2           # 即时全额成交或撤销(fill or kill)
OrderDuration_GFD = 3           # 当日有效(good for day)
OrderDuration_GFS = 4           # 本节有效(good for section)
OrderDuration_GTD = 5           # 指定日期前有效(goodltilldate)
OrderDuration_GTC = 6           # 撤销前有效(goodtillcancel)
OrderDuration_GFA = 7           # 集合竞价前有效(good for auction)
OrderDuration_AHT = 8           # 盘后定价交易(after hour trading)
# order_qualifier 委托成交属性
OrderQualifier_BOC     = 1            # 对方最优价格(best of counterparty)
OrderQualifier_BOP     = 2            # 己方最优价格(best of party)
OrderQualifier_B5TC    = 3            # 最优五档剩余撤销(best 5 then cancel)
OrderQualifier_B5TL    = 4            # 最优五档剩余转限价(best 5 then limit)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值