量化交易:公司基本面的量化

公司的基本面因素一直具备滞后性,令基本面的量化出现巨大困难。而从上市公司的基本面因素来看,一般只有每个季度的公布期才会有财务指标的更新,而这种财务指标的滞后性对股票表现是否有影响呢?如何去规避基本面滞后产生的风险呢?下面我们将重点介绍量化交易在公司基本面分析上的应用,即平时常说的 基本面量化(Quantamental)。

反映公司经营优劣的指标

首先我们简单介绍下可能运用在量化策略上的基本面指标,相信大部分投资者都对上市公司的基本面有一定的了解,上市公司的基本面情况总是同公司业绩相关,而衡量业绩的主要基本面指标有每股收益、净资产收益率、主营业务收入等等。

而上市公司财务指标又常常存在相关的性质,比如每股收益和主营业务收入和产品毛利率相关,所以当我们把一堆财务指标放在一起统计可能就会产生相关性问题,从而降低了模型对市场走势的解释程度。因此,如何选出合适的独立性指标就成为我们进行财务指标量化模型设计的基础。

那么怎样的财务指标会较真实的反映上市公司的经营优劣呢?

  • 具有延续性的财务指标,比如近三年净利润增速,这一个指标把3年的净利润增速平均起来,这种增长性具备一定的长期特征;

  • 与现金流相关的指标,由于涉及真实的资金往来,现金流能够比较真实反映上市公司的经营状况。

每股现金流量/每股业绩

每股现金流量比每股盈余更能显示从事资本性支出及支付股利的能力。每股现金流量通常比每股盈余要高,这是因为公司正常经营活动所产生的净现金流量还会包括一些从利润中扣除出去但又不影响现金流出的费用调整项目,如折旧费等。但每股现金流量也有可能低于每股盈余。一家公司的每股现金流量越高,说明这家公司的每股普通股在一个会计年度内所赚得的现金流量越多;反之,则表示每股普通股所赚得的现金流量越少。

而每股现金流量常常与上市公司的业绩、总股本相关,所以用每股现金流量/每股业绩来衡量上市公司的现金流动情况,比单纯用每股盈余更为合理。

净资产收益率

净资产收益率又称股东权益收益率,是净利润与平均股东权益的百分比,是公司税后利润除以净资产得到的百分比率,该指标反映股东权益的收益水平,用以衡量公司运用自有资本的效率。指标值越高,说明投资带来的收益越高。

净资产收益率通过净资金去计量每年上市公司收益的百分比,净资产收益率比每股净利润,资产收益率等更合理的衡量归于于股东的上市公司权益的增值速度。

销售毛利率

销售毛利率,表示每一元销售收入扣除销售成本后,有多少钱可以用于各项期间费用和形成盈利。 销售毛利率是企业销售净利率的最初基础,没有足够大的毛利率便不能盈利。

在分析企业主营业务的盈利空间和变化趋势时,销售毛利率是一个重要指标。该指标的优点在于可以对企业某一主要产品或主要业务的盈利状况进行分析,这对于判断企业核心竞争力的变化趋势及其企业成长性极有帮助。

基本面量化的具体实现

  • 确定三个财务因子为销售毛利率、净资产收益率、每股现金流量/每股业绩

  • 通过features数据接口获取全市场3000多家上市公司的财务数据

  • 单独筛选每个财务因子前500的上市公司

  • 最终确定三个因子都能排在前500的股票篮子

  • 买入该股票篮子,等权重买入

  • 一个月换仓一次,买入新确定的股票篮子

回测结果:

从策略结果来看,年化收益26.9%,应该超过了大部分公募基金,虽然回撤很大,但细心地伙伴可以看出是发生在15年股灾期间和16年熔断期间,如果配合择时模型,想必效果会更好。尤其是值得注意的是,该策略在17年还取得了稳定正收益。本例子只作为如何使用财务数据进行基本面量化的样例策略,便于大家能够快速上手开发策略。

策略案例 

数据准备函数

def prepare(context):
    # 确定起始时间
    start_date = context.start_date
    # 确定结束时间
    end_date = context.end_date
    instruments = context.instruments
    fields = ['fs_gross_profit_margin_0', 'fs_roe_0', 'fs_free_cash_flow_0', 'fs_net_profit_0']
    raw_data = D.features(instruments, start_date, end_date, fields)
    raw_data['cash_flow/profit'] = raw_data['fs_free_cash_flow_0'] / raw_data['fs_net_profit_0']
    context.daily_buy_stock = pd.DataFrame(raw_data.groupby('date').apply(seek_stock))
    
def seek_stock(df):
    ahead_f1 = set(df.sort_values('fs_roe_0',ascending=False)['instrument'][:500])
    ahead_f2 = set(df.sort_values('fs_gross_profit_margin_0',ascending=False)['instrument'][:500])
    ahead_f3 = set(df.sort_values('cash_flow/profit',ascending=False)['instrument'][:500])
    return list(ahead_f1 & ahead_f2 & ahead_f3)

策略逻辑主体函数

# 回测参数设置,initialize函数只运行一次
def initialize(context):
    # 手续费设置
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) 
    # 调仓规则(每月的第一天调仓)
    context.schedule_function(rebalance, date_rule=date_rules.month_start(days_offset=0)) 

# handle_data函数会每天运行一次
def handle_data(context,data):
    pass

# 换仓函数
def rebalance(context, data):
    # 当前的日期
    date = data.current_dt.strftime('%Y-%m-%d')
    # 根据日期获取调仓需要买入的股票的列表
    stock_to_buy = list(context.daily_buy_stock.ix[date][0])
    # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表
    stock_hold_now = [equity.symbol for equity in context.portfolio.positions]
    # 继续持有的股票:调仓时,如果买入的股票已经存在于目前的持仓里,那么应继续持有
    no_need_to_sell = [i for i in stock_hold_now if i in stock_to_buy]
    # 需要卖出的股票
    stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]
  
    # 卖出
    for stock in stock_to_sell:
        # 如果该股票停牌,则没法成交。因此需要用can_trade方法检查下该股票的状态
        # 如果返回真值,则可以正常下单,否则会出错
        # 因为stock是字符串格式,我们用symbol方法将其转化成平台可以接受的形式:Equity格式

        if data.can_trade(context.symbol(stock)):
            # order_target_percent是平台的一个下单接口,表明下单使得该股票的权重为0,
            #   即卖出全部股票,可参考回测文档
            context.order_target_percent(context.symbol(stock), 0)
    
    # 如果当天没有买入的股票,就返回
    if len(stock_to_buy) == 0:
        return

    # 等权重买入 
    weight =  1 / len(stock_to_buy)
    
    # 买入
    for stock in stock_to_buy:
        if data.can_trade(context.symbol(stock)):
            # 下单使得某只股票的持仓权重达到weight,因为
            # weight大于0,因此是等权重买入
            context.order_target_percent(context.symbol(stock), weight)

策略回测接口

# 策略运行调用函数
m=M.trade.v2( 
    instruments=D.instruments(market='CN_STOCK_A'),
    start_date='2013-01-01', 
    end_date='2017-05-01',
    prepare=prepare, # 在实盘或模拟交易,每天会更新数据,因此必须传入数据准备函数
    # 必须传入initialize,只在第一天运行
    initialize=initialize,
    # 必须传入handle_data,每个交易日都会运行
    handle_data=handle_data,
    # 买入以开盘价成交
    order_price_field_buy='open',
    # 卖出也以开盘价成交
    order_price_field_sell='open',
    # 策略本金
    capital_base=1000000,
    # 比较基准:沪深300
    benchmark='000300.INDX',
    m_deps='quantamental'
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/162259.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网站SEO优化

网站SEO优化 浏览722 一、合理的title、description、keywords 搜索对着三项的权重逐个减小,title值强调重点即可;description把页面内容高度概括,不可过分堆砌关键词;keywords列举出重要关键词。 1、title title,…

【教3妹学编程-java基础6】详解父子类变量、代码块、构造函数执行顺序

-----------------第二天------------------------ 本文先论述父子类变量、代码块、构造函数执行顺序的结论, 然后通过举例论证,接着再扩展,彻底搞懂静态代码块、动态代码块、构造函数、父子类、类加载机制等知识体系。 温故而知新&#xff…

ZYNQ_project:LCD

模块框图: 时序图: 代码: /* // 24h000000 4324 9Mhz 480*272 // 24h800000 7084 33Mhz 800*480 // 24h008080 7016 50Mhz 1024*600 // 24h000080 4384 33Mhz 800*480 // 24h800080 1018 70Mhz 1280*800 */ module rd_id(i…

【MySQL】InnoDB和MyISAM区别详解(MySQL专栏启动)

📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…

OpenCV C++ 图像 批处理 (批量调整尺寸、批量重命名)

文章目录 图像 批处理(调整尺寸、重命名)图像 批处理(调整尺寸、重命名) 拿着棋盘格,对着相机变换不同的方角度,采集十张以上(以10~20张为宜);或者棋盘格放到桌上,拿着相机从不同角度一通拍摄。 以棋盘格,第一个内焦点为坐标原点,便于计算世界坐标系下三维坐标; …

【代码随想录】算法训练计划24

回溯模板: 1、77. 组合 题目: 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 思路: 很经典的回溯,也是回溯中模板的经典应用,因而是回溯中的简单题…

97.qt qml-自定义Table之实现ctrl与shift多选

我们之前实现了:93.qt qml-自定义Table优化(新增:水平拖拽/缩放自适应/选择使能/自定义委托)-CSDN博客 实现选择使能的时候,我们只能一行行去点击选中,非常麻烦,所以本章我们实现ctrl多选与shift多选、 所以在Table控件新增两个属性: 1.实现介绍 ctrl多选实现原理:当我…

Redis新操作

1.Bitmaps 1.1概述 Bitmaps可以对位进行操作,实际上它就是一个字符串,可以将Bitmaps想象为一个以位为单位的数组,数组中的每个元素只能存储0或者1,数组的下标在Bitmaps被称为偏移量。 setbit key offset value:设置o…

Filter和ThreadLocal结合存储用户id信息

ThreadLocal并不是一个Thread,而是Thread的局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。ThreadLoc…

M2 Mac Xcode编译报错 ‘***.framework/‘ for architecture arm64

In /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP(anim_decode.o), building for iOS Simulator, but linking in object file built for iOS, file /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP for architecture arm64 这是我当时编译模拟器时报…

cesium 重点区域大屏展示效果(加载行政区划)

cesium 重点区域大屏展示效果(配色不太好看,主要看思路和方法) 1、实现思路(文张最后有**源码 **) 1、第一步将cesium背景调成透明关掉光照大气等效果相关属性都在“viewer.scene”中 2、第二步添加背景图片此背景图片直接用html加css就可以完成 3、第三步添加蒙版效果也…

汇编基础知识

1.1 机器语言 机器语言就是一些二进制代码,存放在内存中。它是机器指令的集合,所谓机器指令就是机器能够正确执行的命令 1.2 汇编语言的产生 1.汇编语言的主体是汇编指令 2.汇编指令实际上就是机器指令的助记符。它们的唯一区别在于书写方式上 寄存器…

S7-1200PLC 作为MODBUSTCP服务器通信(多客户端访问)

S7-1200PLC作为MODBUSTCP服务器端通信编程应用,详细内容请查看下面文章链接: ModbusTcp通信(S7-1200PLC作为服务器端)-CSDN博客文章浏览阅读239次。S7-200Smart plc作为ModbusTcp服务器端的通信S7-200SMART PLC ModbusTCP通信(ModbusTcp服务器)_s7-200 …

Linux嵌入式I2C协议笔记

硬件: 1.I2C结构 在一个SOC中有一个或者多个I2C控制器,一个I2C控制器可以连接一个或多个I2C设备。 I2C总线需要两条线,时钟线SCL和数据线SDA 2.I2C传输数据格式 开始信号(S):SCL为高电平时,SDA山高电平向低电平跳变,开始传送数据。结束信号(P):SCL为高电平时,SDA…

Python中的实例属性和类属性

在这篇文章中,我们将探讨Python中的类是如何工作的,主要介绍实例和类的属性。这些属性是什么,它们之间的区别,以及创建和利用它们的python方法。 类属性与实例属性 首先,我们需要知道什么是实例。实例是属于类的对象。…

Docker安装Zookeeper

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

数据结构前言(空间复杂度)

1.空间复杂度 空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。 空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂…

在Go编程中调用外部命令的几种场景

1.摘要 在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库中, 专门提供了os/exec包来对调用外部程序提供支持, 本文将对调用外部命令的几种使用方法进行总…

Canal+Kafka实现MySQL与Redis数据同步(一)

CanalKafka实现MySQL与Redis数据同步(一) 前言 在很多业务情况下,我们都会在系统中加入redis缓存做查询优化。 如果数据库数据发生更新,这时候就需要在业务代码中写一段同步更新redis的代码。 这种数据同步的代码跟业务代码糅合…

SQL SERVER 2008安装教程

SQL SERVER 2008安装教程 本篇文章介绍了安装SQL Server 2008企业版的软硬件配置要求,安装过程的详细步骤,以及需要注意的事项。 安装步骤 (1). 在安装文件setup.exe上,单击鼠标右键选择“以管理员的身份运行”,如下图所示&#…
最新文章