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

Python股票交易---均值回归

免责声明:本文提供的信息仅用于教育目的,不应被视为专业投资建议。在做出投资决策时进行自己的研究并谨慎行事非常重要。投资涉及风险,您做出的任何投资决定完全由您自己负责。

在本文中,您将了解什么是均值回归交易算法?如何使用 Python 来实现这一点?

将解释 3 种不同的实现:

  • 基本的
  • Z 分数
  • 统计套利

什么是均值回归交易算法?

均值回归是一种算法,表明价格倾向于恢复到其长期平均值。当股价偏离其历史平均值时,就意味着该资产被超买或超卖。然后,可能会触发交易信号来卖空或买入该工具,并期望其价格将恢复到平均值。

在下文中,您将看到均值回归算法的不同实现。

加载数据集:

在第一个和第二个实现中,我们将使用 Netflix 历史价格:

def  download_stock_data ( ticker,timestamp_start,timestamp_end ): url= f"https://query1.finance.yahoo.com/v7/finance/download/ {ticker} ?period1= {timestamp_start} &period2= {timestamp_end} &interval\ 
=1d&events =history&includeAdjustedClose=true"df = pd.read_csv(url) return df datetime_start=dt.datetime( 2022 , 1 , 1 , 7 , 35 , 51 ) 
datetime_end=dt.datetime.today() # 转换为时间戳:timestamp_start= int(datetime_start.timestamp()) 
timestamp_end= int (datetime_end.timestamp()) ticker= 'NFLX'df = download_stock_data(ticker,timestamp_start,timestamp_end) 
df = df.set_index( '日期' ) 
df.head()

实施 N°1:基本

步骤如下:

  • Netflix 20天移动平均价格计算
  • 计算价格与该移动平均线之间的差异
  • 如果差异为正,则触发卖单。当差额为负数时,就会触发买单。

一方面,如果差值为正,则意味着价格高于 20 日移动平均线。这意味着该资产已超买,它将恢复(减少)至该平均值。因此,卖出订单被触发。

另一方面,如果差值为负,意味着资产超卖,它往往会增加并达到其平均值,从而触发买入订单。

Python代码

我在这张图中绘制了价格与其 20 天移动平均线的关系:

window = 20df[ "ma_20" ] = df[ "Adj Close" ].rolling(window=window).mean() 
df[ "diff" ] = df[ "Adj Close" ] - df[ "ma_20" ] 
df [ 'signal' ] = np.where(df[ "diff" ] > 0 , - 1 , 1 ) Figs=( 8 , 4 ) df[[ 'Adj Close' , "ma_20" ]].plot(figsize=figs ) 
plt.title( "均值回归" ) 
plt.show() df[ 'diff' ].情节(无花果大小=无花果)
#我将信号乘以20能够在图表中清楚地显示出来
( 20 *df[ 'signal' ]).plot(figsize=figs, linestyle= '--' ) 
plt.title( "Diff vs Signal" ) 
plt.legend() 
plt.show() (df[ "Adj Close" ]/df[ "ma_20" ] ).plot(figsize=figs) 
plt.title( "Ratio=Close/ma_20" ) 
plt.show()

我在这张图中绘制了差异(价格 - 20 天移动平均线)和信号。它显示何时触发买入和卖出订单:

在这张图中,我绘制了价格与其移动平均线之间的比率。目标是了解该比率如何振荡。如果在 1 左右,则意味着价格正在恢复到移动平均线。我们可以清楚地看到,2022年4月有一个很大的跳跃。

局限性:

正如您所看到的,在 2022 年 4 月期间,股票价格出现了大幅下跌,并持续了几个月。如果我们遵循基本实施,就会触发买入订单。此时买入将导致接下来几天和几个月的巨大损失。这就是为什么需要将此实现与其他指标结合起来,或者选择不同的计算方法。

回测策略:

正如之前所注意到的,2022 年 4 月的价格大幅下跌严重影响了该策略的表现:

# 回测策略
# 计算每日收益
df[ 'returns' ] = df[ 'Adj Close' ].pct_change() # 计算策略收益
df[ 'strategy_returns' ] = df[ 'signal' ] .shift( 1 ) * df[ 'returns' ] # 计算累积收益
df=df.dropna() 
df[ 'cumulative_returns' ] = ( 1 + df[ 'strategy_returns' ]).cumprod() Figs = ( 8 , 4 ) 
# 绘制累积回报
df[ 'cumulative_returns' ].情节(无花果大小=无花果)
plt.title( "累计回报" ) 
plt.show()

实施 N°2:z 分数

该实现可用于量化交易算法:

  • 计算20天移动平均价
  • 计算 20 天的标准差
  • z 分数的计算方法:

如果价格穿过上限(20 天移动平均线 + n_std 标准差),则会触发卖单。这意味着该工具已超买。

如果价格低于下限(20 天移动平均线 - n_std 标准差),则会触发买入订单。

Python代码

window= 20 # 计算50日均线
df[ 'ma_20' ] = df[ 'Adj Close' ].rolling(window=window).mean() # 计算10日均线的标准差
df[ 'std_20' ] = df[ '调整关闭' ].rolling(window=window).std() # 计算 z 分数(偏离平均值的标准差数)df[ 'zscore' ] = (df[ 'Adj Close' ] - df[ 'ma_20' ]) / df[ 'std_20' ] #如果 z 分数小于 n_std (=1),则买入订单
# 如果 z 分数大于 n_std (=1),则卖出订单
# 如果在 -1 到 1 之间,则持有
n_std= 1.25df[ '信号' ] = np.where(df[ 'zscore' ] < -n_std, 1 , np.where(df[ 'zscore' ] > n_std, - 1 , 0 )) Figs=( 8 , 4 ) 
df[ 'signal' ].plot(figsize=figs, linestyle= "--" )    
df[ 'zscore' ].plot(figsize=figs)           
plt.title( "带有 z 分数的均值回归" ) 
plt.图例() 
plt.show()

在此图中,我们有 z 分数,以及买入或卖出订单的交易信号:

upper_band=df[ 'ma_20' ]+n_std*df[ 'std_20' ] 
lower_band=df[ 'ma_20' ]-n_std*df[ 'std_20' ] Figs=( 10 , 6 ) 
df[ 'Adj Close' ].plot (figsize=figs) 
df[ 'ma_20' ].plot(figsize=figs,linestyle= '-.' , color= "w" ) 
upper_band.plot(linestyle= '--' ,label= 'upper_band' ) 
lower_band.情节(线型= ':',标签= 'lower_band')
plt.fill_ Between(df.index,lower_band,upper_band,阿尔法 = 0.3 ) 
plt. 标题(“上限和下限” ) 
plt.legend() 
plt.show()

通过此图,我们可以清楚地看到价格何时超出范围。通过突破上限,股票变得超买,这是进入空头头寸的信号。

当价格下跌并突破下轨时,股票就会超卖,这可以被视为买入信号订单。

回测策略

# 计算每日收益
df[ 'returns' ] = df[ 'Adj Close' ].pct_change() # 计算策略收益
df[ 'strategy_returns' ] = df[ 'signal' ] .shift( 1 ) * df[ ' returns' ] # 计算累计收益
df=df.dropna() 
df[ 'cumulative_returns' ] = ( 1 + df[ 'strategy_returns' ]).cumprod() # 绘制累计收益
df[ 'cumulative_returns' ].plot( Figsize=figs) 
plt.title ( "累计回报" ) 
plt.show()

当 n_std=1.25 时,该策略表现出良好的性能:

尝试修改这个数字,了解它对整体性能的影响

比较

通过添加股票在触发买入或卖出订单之前必须偏离其移动平均线多少个标准差的限制,与第一段的第一次实施相比,该策略的表现变得更具吸引力。

其他

通过调整计算以适应日内价格,该实现还可用于高频交易。

  • 日内价格可以采样到几秒,甚至几毫秒。
  • 以秒为单位计算的滚动平均值和标准差
  • 如果突破上限或下限,则会触发买入或卖出订单。

实施 N°3:统计套利

在此实施中,我们将研究两只股票之间价差的均值回归:

  • 计算两只股票之间的价差
  • 计算价差的 20 天移动平均线
  • 计算价差 20 天的移动标准差
  • z 分数的计算方法:

Python代码

加载 2 只股票的数据集:Apple 和 Google:

import pandas as pd
import datetime as dtdef download_stock_data(ticker,timestamp_start,timestamp_end):url=f"https://query1.finance.yahoo.com/v7/finance/download/{ticker}?period1={timestamp_start}&period2={timestamp_end}&interval\
=1d&events=history&includeAdjustedClose=true"df = pd.read_csv(url)return df# Determine Start and End dates
datetime_start=dt.datetime(2022, 2, 8, 7, 35, 51)
datetime_end=dt.datetime.today()# Convert to timestamp:
timestamp_start=int(datetime_start.timestamp()) 
timestamp_end=int(datetime_end.timestamp()) tickers=['AAPL','GOOG']df_global=pd.DataFrame()
for ticker in tickers:df_temp = download_stock_data(ticker,timestamp_start,timestamp_end)[['Date','Adj Close']]df_temp = df_temp.set_index('Date')df_temp.columns=[ticker]df_global=pd.concat((df_global, df_temp),axis=1)
df_global.head()

指标计算

# Calculate the spread between two stocks:
ticker_long = 'AAPL'
ticker_short = 'GOOG'
spread = df_global[ticker_long] - df_global[ticker_short]window = 20
n_std = 1.5# Calculate the rolling mean and standard deviation of the spread
rolling_mean = spread.rolling(window=30).mean()
rolling_std = spread.rolling(window=30).std()# Calculate the z-score (number of standard deviations away from the rolling mean)
zscore = (spread - rolling_mean) / rolling_stdupper_band = rolling_mean + n_std * rolling_std
lower_band = rolling_mean - n_std * rolling_std

现在我们绘制不同的指标来查看价差与下限和上限的表现如何:

figs=(8,4)
plt.figure(figsize = figs)
spread.plot(label='Spread = '+ticker_long+' - '+ ticker_short,linestyle='--')
df_global[ticker_long].plot(label=ticker_long+'_price')
df_global[ticker_short].plot(label=ticker_short+'_price')
plt.title("Spread and Prices of {0} and {1}".format(ticker_long,ticker_short))
plt.legend()
plt.show()plt.figure(figsize = figs)
upper_band.plot(label='Upper_band')
lower_band .plot(label='Lower_band')
spread.plot(label = 'Spread = '+ticker_long+' - '+ ticker_short,linestyle='--', color='r')
rolling_mean.plot(label = 'ma_30days_spread', linestyle = '-.')
plt.fill_between(df_global.index,lower_band, upper_band, alpha=0.2)
plt.legend()
plt.show()

价差已突破或低于上限和下限。因此给出了买入或做空价差的交易信号:

回测策略

# Enter a long position if the z-score is less than -n_std
# Enter a short position if the z-score is greater than n_std
signal = np.where(zscore < -n_std, 1, np.where(zscore > n_std, -1, 0))
signal = pd.Series(signal, index=df_global.index)# Calculate the daily returns
returns = df_global[ticker_long].pct_change() - df_global[ticker_short].pct_change()# Calculate the strategy returns : # Shift the signal by one day to compute the returns
strategy_returns = signal.shift(1) * returns# Calculate the cumulative returns
cumulative_returns = (1 + strategy_returns).cumprod()# # Plot the cumulative returns
cumulative_returns.plot(figsize = figs)
plt.title("Cumulative Return with n_std={0}".format(n_std))
plt.show()

该策略产生的累积回报在整个期间显示出正值。

通过修改模型中的标准差数量 (n_std),您将看到对策略性能的影响。当n_std=1.25时,性能较差。

相关文章:

Python股票交易---均值回归

免责声明&#xff1a;本文提供的信息仅用于教育目的&#xff0c;不应被视为专业投资建议。在做出投资决策时进行自己的研究并谨慎行事非常重要。投资涉及风险&#xff0c;您做出的任何投资决定完全由您自己负责。 在本文中&#xff0c;您将了解什么是均值回归交易算法&#xff…...

机器人制作开源方案 | 桌面级机械臂--本体说明+驱动及控制

一、本体说明 1. 机械臂整体描述 该桌面级机械臂为模块化设计&#xff0c;包含主机模块1个、转台模块1个、二级摆动模块1个、可编程示教盒1个、2种末端执行器、高清摄像头&#xff0c;以及适配器、组装工具、备用零件等。可将模块快速组合为一个带被动关节的串联3自由度机械臂…...

有哪些前端调试和测试工具? - 易智编译EaseEditing

前端开发调试和测试工具帮助开发人员在开发过程中发现和修复问题&#xff0c;确保网站或应用的稳定性和性能。以下是一些常用的前端调试和测试工具&#xff1a; 调试工具&#xff1a; 浏览器开发者工具&#xff1a; 现代浏览器&#xff08;如Chrome、Firefox、Safari等&#…...

【数据结构】手撕单链表

目录 一&#xff0c;链表的概念及结构 二&#xff0c;接口实现 1&#xff0c;单链表的创建 2&#xff0c;接口函数 3&#xff0c;动态创立新结点 4&#xff0c;打印 5&#xff0c;头插 6&#xff0c;头删 7&#xff0c;尾插 8&#xff0c;尾删 9&#xff0c;查找 10&#xff…...

两个git本地如何配置两个ssh密钥for mac

我是在mac上操作的。windows上也差不多一样操作。 1.找到本地的.ssh文件。我的文件结构如下如&#xff1a; 文件结构&#xff1a; &#xff08;1&#xff09;两个known_hosts文件是自动生成的&#xff0c;不用管 &#xff08;2&#xff09;readme文件是我个人记事本记录笔记…...

iOS逆向进阶:iOS进程间通信方案深入探究与local socket介绍

在移动应用开发中&#xff0c;进程间通信&#xff08;Inter-Process Communication&#xff0c;IPC&#xff09;是一项至关重要的技术&#xff0c;用于不同应用之间的协作和数据共享。在iOS生态系统中&#xff0c;进程和线程是基本的概念&#xff0c;而进程间通信方案则为应用的…...

qt day 1

this->setWindowIcon(QIcon("D:\\zhuomian\\wodepeizhenshi.png"));//設置窗口的iconthis->setWindowTitle("鵬哥快聊");//更改名字this->setFixedSize(500,400);//設置尺寸QLabel *qlnew QLabel(this);//創建一個標簽ql->resize(QSize(500,20…...

针对java中list.parallelStream()的多线程数据安全问题我们采用什么方法最好呢?

当使用List.parallelStream()方法进行多线程处理时&#xff0c;可能会涉及到数据安全问题。下面是一些常见的方法来处理parallelStream()的多线程数据安全问题&#xff1a; 1. 使用线程安全的集合&#xff1a;Java中提供了线程安全的集合类&#xff0c;如CopyOnWriteArrayList…...

校园用电安全管理系统可以识别违规电器吗

校园用电安全管理系统是处理恶意用电问题有效手段之一&#xff0c;系统具有实时监测、异常预警、监测设备运行状态、远程控制用电等功能&#xff0c;可以从根本上管理学校用电量&#xff0c;制定合理的用电计划&#xff0c;限制用电成本&#xff0c;避免各种恶意用电行为&#…...

前端(十五)——开源一个用react封装的图片预览组件

&#x1f475;博主&#xff1a;小猫娃来啦 &#x1f475;文章核心&#xff1a;开源一个react封装的图片预览组件 文章目录 组件开源代码下载地址运行效果展示实现思路使用思路和api实现的功能数据和入口部分代码展示 组件开源代码下载地址 Gitee&#xff1a;点此跳转下载 CSDN…...

idea新建Java-maven项目时,出现Dependency ‘ xxx(jar包名)‘ not found的解决方案

项目场景&#xff1a; 项目场景&#xff1a;使用idea创建maven项目时&#xff0c;导入简单依赖时&#xff08;本文以mysql-connector-java为例&#xff09;。 问题描述 问题&#xff1a; 首先&#xff0c;在创建新的maven项目中&#xff0c;出现下列两种情况&#xff1a; &am…...

C# 获取Windows系统版本注意事项

首先通过微软官方文档&#xff1a;https://learn.microsoft.com/zh-cn/windows/win32/sysinfo/operating-system-version了解各个操作系统对应的版本号 下面介绍3种获取版本号的方式及弊端 1. Environment.OSVersion.Version OperatingSystem os Environment.OSVersion;// 判断…...

STM32设计的宠物投喂器(正点原子mini开发板+2.8寸屏)

一、设计需求 【1】 项目背景 在竞争日益激烈的今天,各行各业为提高竞争力,纷纷推出了各种新、奇的事物来吸引消费者。经过长时间的市场调查,发现广大市民及民营企业家大多还采用传统的人工喂养方式,这种方式不但耗费了大量的人力资源,而且由于现在的人力成本的不断增加…...

Python编程——深入了解不可变的元组

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 目录 一、元组是什么 二、元组的定义 1、相同类型组成元组…...

JVM——类加载与字节码技术—类加载器+运行期优化

5.类加载器 jdk的类加载器具有层级关系。 启动类加载器》扩展类加载器》应用程序类加载器》自定义类加载器 对应类加载器只会负责加载对应目录的类。 双亲委派上级机制 应用程序类加载器加载一个类之前会先查询上级加载器是否已经加载过了该类。然后再让上级询问上上级。都…...

[linux实战] 华为云耀云服务器L实例 Java、node环境配置

系列文章目录 第一章 [linux实战] 华为云耀云服务器L实例 Java、node环境配置 文章目录 系列文章目录前言一、任务拆解二、修改密码三、配置安全规则四、远程登录并更新apt五、安装、配置JDK环境5.1、安装openjdk,选择8版本5.2、检查jdk配置 六、安装、配置git6.1、安装git6.2…...

python面试:使用cProfile剖析程序性能

我们需要安装tuna&#xff1a;pip install tuna 程序执行完毕后&#xff0c;我们会得到一个results.prof&#xff0c;在CMD中输入指令&#xff1a;“tuna results.prof”。 import time import cProfile import pstatsdef add(x, y):resulting_sum 0resulting_sum xresulti…...

leetcode-188-买卖股票的最佳时机 IV

1. 问题描述 https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/description/ 2. 解题代码 public class Solution {public int MaxProfit(int k, int[] prices) {if(prices.Length<2){return 0;}if(k0){return 0;}List<int> listValuenew List<…...

Grounded Language-Image Pre-training论文笔记

Title&#xff1a;Grounded Language-Image Pre-training Code 文章目录 1. 背景2. 方法&#xff08;1&#xff09;Unified Formulation传统目标检测grounding目标检测 &#xff08;2&#xff09;Language-Aware Deep Fusion&#xff08;3&#xff09;Pre-training with Scala…...

成集云 | 钉钉财务费用单同步至畅捷通 | 解决方案

源系统成集云目标系统 方案介绍 财务管理作为企业管理中重要的组成部分&#xff0c;在企业的发展和成长中扮演着重要角色&#xff0c;成集云以钉钉费用单OA审批与畅捷通TCloud系统为例&#xff0c;与钉钉连接器深度融合&#xff0c;通过数据处理和字段匹配实现了费用…...

Redis——》死锁

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…...

URL重定向漏洞

URL重定向漏洞 1. URL重定向1.1. 漏洞位置 2. URL重定向基础演示2.1. 查找漏洞2.1.1. 测试漏洞2.1.2. 加载完情况2.1.3. 验证漏洞2.1.4. 成功验证 2.2. 代码修改2.2.1. 用户端代码修改2.2.2. 攻击端代码修改 2.3. 利用思路2.3.1. 用户端2.3.1.1. 验证跳转 2.3.2. 攻击端2.3.2.1…...

JavaScript(函数,作用域和闭包)

目录 一&#xff0c;什么是函数1.1&#xff0c;常用系统函数1.2&#xff0c;函数声明 1.3&#xff0c;函数表达式二&#xff0c;预解析2.1&#xff0c;函数自调用 2.2&#xff0c;回调函数三&#xff0c;变量的作用域3.1&#xff0c;隐式全局变量 四&#xff0c;作用域与块级作…...

C# 实现 国密SM4/ECB/PKCS7Padding对称加密解密

C# 实现 国密SM4/ECB/PKCS7Padding对称加密解密&#xff0c;为了演示方便本问使用的是Visual Studio 2022 来构建代码的 1、新建项目&#xff0c;之后选择 项目 鼠标右键选择 管理NuGet程序包管理&#xff0c;输入 BouncyCastle 回车 添加BouncyCastle程序包 2、代码如下&am…...

【docker-compose】【nginx】动态配置

需求&#xff1a;部署前端镜像时需要动态修改nginx反向代理的后端服务的ip地址 原.conf配置调整&#xff0c;改为嵌入变量的文件模版Dockerfile 修改&#xff0c;通过envsubst将换将变量注入模版后再运行nginxdocker-compose配置&#xff0c;通过environment动态修改变量 defau…...

ExpressLRS开源之接收机固件编译烧录步骤

ExpressLRS开源之接收机固件编译烧录步骤 1. 源由2. 编译步骤2.1 推荐源代码指定方案2.2 方法一&#xff1a;ELRS Configurator步骤一&#xff1a;下载ELRS Configurator工具步骤二&#xff1a;安装ELRS Configurator工具步骤三&#xff1a;使用ELRS Configurator工具进行配置步…...

提取视频文件里的音频和无声视频

一、提取视频文件里的音频&#xff1a; public static void generateMediaRadio(){// 视频提取器MediaExtractor extractor new MediaExtractor();try {//本地视频文件extractor.setDataSource("/storage/emulated/0/mjyyfep/alpha.mp4");//网络视频文件 // …...

SpringBoot原理

一、Bean原理 1、配置文件的优先级 SpringBoot项目当中支持的三类配置文件&#xff1a; ​ - application.properties - application.yml - application.yaml 配置文件优先级排名&#xff08;从高到低&#xff09;&#xff1a; 1. properties配置文件 2. yml配置文件 3. yaml…...

MySQL事务原理、MVCC详解

事务原理 1 事务基础 1). 事务 事务 是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系 统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 2). 特性 原子性&#xff08;Atomi…...

在Windows操作系统上安装Neo4j数据库

在Windows操作系统上安装Neo4j数据库 一、在Windows操作系统上安装Neo4j数据库 一、在Windows操作系统上安装Neo4j数据库 点击 MySQL可跳转至MySQL的官方下载地址。 在VUE3项目的工程目录中&#xff0c;通过以下命令可生成node_modules文件夹。 npm install&#xff08;1&am…...