当前位置: 首页 > news >正文

Python量化交易学习——Part12:回归模型的典型应用

回归模型在很多的时候被应用于对股票的基本面数据进行分析,例如经典的CAPM模型、Fama-French三因子模型以及最新的PB_ROE模型等。这些都是已经应用于现实中的金融市场并获得较好收益的经典模型。本章将通过介绍PB_ROE模型,进一步讲解回归分析在实战过程中的使用。

PB-ROE 回归模型的使用

选股的核心思想在于寻找价格低于内在价值的股票,从而获取未来价格修复的收益。具体来看,符合价值投资理念的标的首先要有良好的基本面,其次要有合理的价格。PB-ROE选股模型便是价值投资中的一种经典方法。该模型中,ROE作为基本面指标,用于衡量公司质地是否优良,PE作为估值指标,用于衡量当前价格是否低估。

市净率(Price-to-Book Ratio,简称P/B PBR)指的是每股股价与每股净资产的比率。 市净率可用于股票投资分析,一般来说市净率较低的股票,投资价值较高,相反,则投资价值较低;但在判断投资价值时还要考虑当时的市场环境以及公司经营情况、盈利能力等因素。
股东权益报酬率=可供普通股东分配的净利润/平均普通股东权益×100%,这个比率通常也被称为净资产收益率,英文缩写ROE

因此PB-ROE选股策略可以概况为以下几点:
(1)获取股票的PB\ROE数据,建立PB-ROE数据之间的回归模型;
(2)一般来说,净资产收益率高的股票,市净率也应该高一些,因此可以根据回归模型计算单个股票拟合后的PB值,与真实PB值进行比较,并对差值进行排序,当(真实PB-预测PB)的值越大,说明股票越被高估,当值越小,说明越被低估。
(3)根据排序后的结果进行股票买卖
(4)在导入股票的时候,我们只选择了沪深主板的股票,原因很简单,因为我没有创业板和科创板买卖权限…

# coding=utf-8
from __future__ import print_function, absolute_import
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as plt
import random
import pandas as pd
from gm.api import *
import datetime
import os
import statsmodels.api as sm
# from MSCI_tools import mcsi_tools as toolsset_token('a7f3404da7e8c9a3aea631b5ae0c893b1d57161d')
now, hour_and_mins = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')).split(" ")# 获取A股除了流动性不足的股票以及ST股票外,入选中证组合的几乎全部的股票清单(沪深主板)
def get_symbol_list_all():A_share_list = {"SHSE.000010": "SHANG_ZHENG180", "SHSE.000016": "SHANG_ZHENG50", "SHSE.000300": "HU_SHEN300","SHSE.000903": "ZHONG_ZHENG100","SHSE.000904": "ZHONG_ZHENG200", "SHSE.000905": "ZHONG_ZHENG500", "SHSE.000906": "ZHONG_ZHENG800","SHSE.000907": "ZHONG_ZHENG700", "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"].valuestarget_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_listdef PB_ROE_strategy(symbol_list,now):last_day = get_previous_trading_date("SHSE",now)ROE = stk_get_finance_deriv_pt(symbols=symbol_list,fields="roe",date=last_day,df=True)ROE = ROE.sort_values(["symbol"],ascending=False)ROE = ROE.reset_index(drop=True)PB = stk_get_daily_valuation_pt(symbols=symbol_list, fields="pb_mrq", trade_date=last_day, df=True)PB = PB.sort_values(["symbol"],ascending=False)PB = PB.reset_index(drop=True)ROE_PB_list = pd.merge(ROE, PB)drop_num =[]for num in range(len(ROE_PB_list)-1):if ROE_PB_list["roe"].values[num] < 0 or ROE_PB_list["pb_mrq"].values[num] > 6:drop_num.append(num)ROE_PB_list = ROE_PB_list.drop(drop_num)ROE_PB_list.dropna()symbol_roe = ROE_PB_list["roe"].values #自变量symbol_pb = ROE_PB_list["pb_mrq"].values #因变量symbol_roe[np.isnan(symbol_roe)] = 0symbol_roe[np.isinf(symbol_roe)] = 0symbol_pb[np.isnan(symbol_pb)] = 0symbol_pb[np.isinf(symbol_pb)] = 0#进行回归分析symbol_roe = sm.add_constant(symbol_roe)model = sm.OLS(symbol_pb, symbol_roe)  # 前面为因变量,后面为自变量result = model.fit()bias, weight = (result.params)  # 前面为截距,后面为斜率ROE_PB_list["PB_new"] = bias + ROE_PB_list["roe"]*weight# print(ROE_PB_list)ROE_PB_list["value"] = ROE_PB_list["PB_new"] -ROE_PB_list["pb_mrq"] #大于0说明是低估ROE_PB_list = ROE_PB_list.sort_values(["value"],ascending=False)ROE_PB_list = ROE_PB_list.reset_index(drop=True)# print(ROE_PB_list)#绘制ROE-PB关系曲线# fig = plt.figure()# #将画图窗口分为1行1列,选择第一块区域做子图# ax = fig.add_subplot(111)# ax.set_title("ROE-PB model")# ax.set_xlabel("ROE")# ax.set_ylabel("PB")# ax.scatter(ROE_PB_list["roe"].values,ROE_PB_list["pb_mrq"].values,c="k",marker=".")# ax.plot(ROE_PB_list["roe"].values,ROE_PB_list["PB_new"].values,c="b")# plt.show()return ROE_PB_list["symbol"].valuessymbol_list = get_symbol_list_all()
PB_ROE_strategy(symbol_list,now)
# symbol_list1 = stk_get_index_constituents("SHSE.000903")
# symbol_list2 = stk_get_index_constituents("SHSE.000016")
# print(symbol_list1)
# print(symbol_list2)
# print(symbol_list1.append(symbol_list2))# coding=utf-8def init(context):# 每天14:50 定时执行algo任务,# algo执行定时任务函数,只能传context参数# date_rule执行频率,目前暂时支持1d、1w、1m,其中1w、1m仅用于回测,实时模式1d以上的频率,需要在algo判断日期# time_rule执行时间, 注意多个定时任务设置同一个时间点,前面的定时任务会被后面的覆盖schedule(schedule_func=algo, date_rule='1m', time_rule='09:31:00')context.count = 1context.num = 5context.fields = "open,high,low,close"def algo(context):now = context.nowlast_day = get_previous_trading_date("SHSE",now)target_symbol_list = get_symbol_list_all()ROE_PB_list = PB_ROE_strategy(target_symbol_list,now)target_list = ROE_PB_list[0:context.num]positions = context.account().positions()for position in positions:symbol = position["symbol"]if symbol not in target_list:order_target_percent(symbol=symbol,percent=0,order_type=OrderType_Market,position_side=PositionSide_Long)positions = context.account().positions()holded_symbol = []for position in positions:symbol = position["symbol"]holded_symbol.append(symbol)print(holded_symbol)for symbol in target_list:if symbol not in holded_symbol:print(symbol)data = history_n(symbol=symbol,frequency='1d',count=2,end_time=now,fields=context.fields,adjust=ADJUST_PREV, df=True)open =data["open"].valuesclose = data["close"].valuesif open[-1] < close[0]*1.08: #没有涨停,涨停就无法买入了order_target_percent(symbol=symbol,percent=(1/context.num)*0.95,order_type=OrderType_Market,position_side=PositionSide_Long)else:pass# 查看最终的回测结果
def on_backtest_finished(context, indicator):print(indicator)if __name__ == '__main__':'''strategy_id策略ID, 由系统生成filename文件名, 请与本文件名保持一致mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID, 可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_initial_cash回测初始资金backtest_commission_ratio回测佣金比例backtest_slippage_ratio回测滑点比例backtest_match_mode市价撮合模式,以下一tick/bar开盘价撮合:0,以当前tick/bar收盘价撮合:1'''run(strategy_id='8e30d6a2-3b4c-11ef-94ca-e073e7f1ba05',filename='pb_roe_strategy.py',mode=MODE_BACKTEST,token='自己的token码',backtest_start_time='2022-11-01 09:30:00',backtest_end_time='2024-06-20 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)

结果如下:从结果看,获得了一定的超额收益,但收益并不明显,通过绘制PB-ROE散点图我们也可以看到,两者之间的关系并不是很明显。
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PostgreSQL 怎样处理数据仓库中维度表和事实表的关联性能?
  • 快速使用BRTR公式出具的大模型Prompt提示语
  • [Vulnhub] Tr0ll3 aircrack-ng+lynx
  • ref和reactive
  • RabbitMQ的工作模式
  • 微服务-注册中心
  • linux之find指令基础
  • STM32智能交通灯系统教程
  • YOWOv2(yowov2)动作识别+Fastreid身份识别 详细安装与实现
  • apt update报错E: Dynamic MMap ran out of room
  • 集成excel工具:自定义导入回调监听器、自定义类型转换器、web中的读
  • JMESPath: 强大的处理JSON数据
  • Python|OpenCV-实现人物的姿态识别检测以及实时计数(18)
  • 解决:WPS,在一个表格中,按多次换行,无法换到下一页
  • Web 性能入门指南-1.5 创建 Web 性能优化文化的最佳实践
  • CSS 三角实现
  • Go 语言编译器的 //go: 详解
  • javascript 哈希表
  • Joomla 2.x, 3.x useful code cheatsheet
  • Js基础知识(四) - js运行原理与机制
  • Spring-boot 启动时碰到的错误
  • ucore操作系统实验笔记 - 重新理解中断
  • 初识 webpack
  • 初识MongoDB分片
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 浮动相关
  • 缓存与缓冲
  • 看域名解析域名安全对SEO的影响
  • 如何编写一个可升级的智能合约
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 我有几个粽子,和一个故事
  • 想写好前端,先练好内功
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​【经验分享】微机原理、指令判断、判断指令是否正确判断指令是否正确​
  • # Java NIO(一)FileChannel
  • # windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次
  • # wps必须要登录激活才能使用吗?
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • #大学#套接字
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (1)(1.13) SiK无线电高级配置(五)
  • (1)SpringCloud 整合Python
  • (2.2w字)前端单元测试之Jest详解篇
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (6)设计一个TimeMap
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (第二周)效能测试
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (一)80c52学习之旅-起始篇
  • (原创) cocos2dx使用Curl连接网络(客户端)