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时,性能较差。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+SpringBoot+Mybaties-plus+Vue+ElementUI 高校汉服租赁网站的 设计与实现

一.项目介绍 高校汉服租赁网站分为普通用户以及管理员两类 普通用户&#xff1a; 注册、登录系统、查看汉服首页发帖公告信息、 交流论坛&#xff08;发帖、查看帖子、评论&#xff09;、 公告咨询&#xff08;查看公告以及评论&#xff09;、 汉服信息&#xff08;查…

(线特征)opencv+opencv contribute 配置

写一篇博客&#xff0c;记录开始线特征slam的历程。 在配置环境的时候&#xff0c;可以发现大多数都是用到了opencv3.4.16和其contribute版本&#xff0c;这里进行一个相关操作的教学。配置环境是在Ubuntu下面进行的&#xff0c;建议使用Ubuntu18来进行线特征的配置以及代码的…

高精度地图定位在高速公路自动驾驶系统中的应用

近年来随着汽车保有量不断增加&#xff0c;随之而来的是: ( 1) 严重的交通拥堵&#xff0c;通行效率低下&#xff0c;用在通行上的时间不断增加; ( 2) 交通事故频发&#xff0c;交通事故导致的伤亡人数和费用不断增加&#xff0c;而且绝大多数事故是由人为因素导致的; ( 3) 大气…

脱离束缚:数字化工厂中ARM控制器的革命性应用!

近年来&#xff0c;中国数字经济体系已进入高速增长阶段。制造业作为中国经济高质量发展的重要支撑力量&#xff0c;在面临生产成本不断上涨、关键装备和核心零部件“受制于人”等挑战时&#xff0c;建设数字化工厂已成必然。 数字化工厂数据采集出现的问题 在数字工厂的建设…

Unity3D软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Unity3D是一款全球知名的游戏开发引擎&#xff0c;由Unity Technologies公司开发。它提供了一个跨平台、多功能的开发环境&#xff0c;支持创建2D和3D游戏、交互式应用、虚拟现实、增强现实等多种类型的应用程序。以下是Unity3D…

24.排序,插入排序,交换排序

目录 一. 插入排序 &#xff08;1&#xff09;直接插入排序 &#xff08;2&#xff09;折半插入排序 &#xff08;3&#xff09;希尔排序 二. 交换排序 &#xff08;1&#xff09;冒泡排序 &#xff08;2&#xff09;快速排序 排序&#xff1a;将一组杂乱无章的数据按一…

框架分析(6)-Ruby on Rails

框架分析&#xff08;6&#xff09;-Ruby on Rails 专栏介绍Ruby on Rails核心概念以及组件讲解MVC架构模式约定优于配置强大的ORM支持自动化测试丰富的插件生态系统RESTful路由安全性总结 优缺点优点快速开发简单易学MVC架构强大的ORM支持大量的插件和Gem支持 缺点性能问题学习…

AMBEO 双声道空间音频现已迈进直播制作领域

图片来源&#xff1a;Unsplash&#xff0c;作者&#xff1a;Bence Balla-Schottner AMBEO 双声道空间音频现已迈进直播制作领域 为所有观众解锁更加身临其境的听觉体验 森海塞尔将功能强大的 AMBEO 双声道空间音频技术引入了广播电视直播应用领域&#xff0c;对所有体育赛事广…

基于VHDL语言的汽车测速系统设计_kaic

摘 要 汽车是现代交通工具。车速是一项至关重要的指标。既影响着汽车运输的生产率,又关乎着汽车行驶有没有超速违章&#xff0c;还影响着汽车行驶时人们的人身安全。而伴随着我国国民的安全防范意识的逐步增强&#xff0c;人们也开始越来越关心因为汽车的超速而带来的极其严重…

非科班菜鸡算法学习记录 | 代码随想录算法训练营第51天||309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费 股票总结

309.最佳买卖股票时机含冷冻期 309. Best Time to Buy and Sell Stock with Cooldown(英文力扣连接) 知识点&#xff1a;动规 状态&#xff1a;看思路ok 思路&#xff1a; 四个状态需要想&#xff0c;持有/不持有且过了冷却期/当天卖/正处于冷却期&#xff1b; 具体看注释…

设计模式-组合模式

核心思想 组合模式可以使用一棵树来表示组合模式使得用户可以使用一致的方法操作单个对象和组合对象组合模式又叫部分整体模式&#xff0c;将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;可以更好的实现管理操作&#xff0c;部分-整体对象的操作基本一样&…

【Python】PySpark

前言 Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎。 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器集群&#xff0c;计算TB、PB乃至EB级别的海量数据…