首页 > 解决方案 > 在 Python 中为 3 个 ETF(EWA、EWC、IGE)实施协整投资组合

问题描述

我正在尝试使用 PE Chan 博士在“算法交易”中描述的策略来实施均值回归投资组合。但是,由于他使用的示例是在 MATLAB 中编写的,因此我无法将它们正确地转换为 Python。我完全无法使用 3 个 ETF 创建协整投资组合。我认为我的问题始于尝试确定对冲,然后建立所需的投资组合。

任何帮助或提示都会非常有用。

因此,我首先下载调整后的价格并创建 W、X 和 Y 数据系列。我选择的时间段是 2007/07/22 到 2012/3/28。

import numpy as np
import pandas as pd
import pandas_datareader.data as web
import matplotlib.pyplot as plt
%matplotlib inline

import statsmodels.api as sm

import datetime

start = datetime.datetime(2007, 7, 22)
end = datetime.datetime(2012, 3, 28)
EWA = web.DataReader('EWA', 'yahoo', start, end)
EWC = web.DataReader('EWC', 'yahoo', start, end)
IGE = web.DataReader('IGE', 'yahoo', start, end)

w = IGE['Adj Close']
x = EWA['Adj Close']
y = EWC['Adj Close']

df = pd.DataFrame([w,x,y]).transpose()
df.columns = ['W','X','Y']
df.plot(figsize=(20,12))

from statsmodels.tsa.vector_ar.vecm import coint_johansen

y3 = df

j_results = coint_johansen(y3,0,1)

print(j_results.lr1)                           
print(j_results.cvt)                           
print(j_results.eig)
print(j_results.evec)
print(j_results.evec[:,0])

那么我应该通过将特征向量 [0.30.., 1.36.., -1.35..] 乘以每种工具的股价来获得 y_port 值来构建投资组合。之后,我进行了相关性测试,以确定该投资组合的每日价格变化与最后一天的价格变化之间的相关性,从而能够确定该系列的半衰期。

我只是通过将特征向量乘以收盘价来做到这一点,我不知道这是否是我出错的地方。

    hedge_ratios = j_results.evec[:,0]
    y_port = (hedge_ratios * df).sum(axis=1)
    y_port.plot(figsize=(20,12))

    y_port_lag = y_port.shift(1)
    y_port_lag[0]= 0
    delta_y = y_port-y_port_lag

    X = y_port_lag
    Y = delta_y
    X = sm.add_constant(X)

    model = OLS(Y,X)
    regression_results  = model.fit()
    regression_results.summary()

然后我计算半衰期,大约是 19 天。

halflife = -np.log(2)/regression_results.params[0]
halflife

我根据书上的说明定义要持有的单位数量(投资组合价值的 -Z 值,基于半衰期的 19 天回溯窗口)。

num_units = -(y_port-y_port.rolling(19).mean())/y_port.rolling(19).std()
num_units.plot(figsize=(20,12))

所以我接下来要采取的步骤是:

  1. 检查数据框是否仍然正确。

  2. 添加之前计算的“要持有的单位数”,它是 y_port 值的负 Z 分数。

  3. 可能有一种更简单的乘法或这样做的方法,但我通过将工具价格乘以由特征向量给出的对冲比率,乘以要持有的投资组合单位的数量来计算我应该为每种工具持有的美元金额。

  4. 最后,我通过将每日变化乘以我持有的单位数量来计算每种工具的 PNL。

结果很糟糕。只是从头到尾一路输。¿ 我哪里搞砸了?¿我怎样才能正确地将特征向量中的值相乘,确定要持有的头寸数量,并正确创建投资组合?

任何帮助将不胜感激。

  1. 我不知道为什么,但是 num_units 系列是“水平的”,我必须在将其附加到 DataFrame 之前对其进行转置。
num_units = num_units.transpose()
df['Portfolio Units'] = num_units
df
df['W $ Units'] = df['W']*hedge_ratios[0]*df['Portfolio Units']
df['X $ Units'] = df['X']*hedge_ratios[1]*df['Portfolio Units']
df['Y $ Units'] = df['Y']*hedge_ratios[2]*df['Portfolio Units']

positions = df[['W $ Units','X $ Units','Y $ Units']]
positions

pnl = pd.DataFrame()

pnl['W Pnl'] = (df['W']/df['W'].shift(1)-1)*df['W $ Units']
pnl['X Pnl'] = (df['X']/df['X'].shift(1)-1)*df['X $ Units']
pnl['Y Pnl'] = (df['Y']/df['Y'].shift(1)-1)*df['Y $ Units']
pnl['Total PNL'] = pnl.sum(axis=1)

pnl['Total PNL'].cumsum().plot(figsize=(20,12))

我知道如果我只是恢复我的位置(不在 y_port 中使用 -1),结果会改变,我会得到正回报。但是,我想知道我做错了什么。使用 -Z 进行均值回归策略是有道理的,我想知道我在哪里犯了错误,这样我就可以跟上本书的其余部分,

标签: python-3.xdataframestatisticsalgorithmic-tradingportfolio

解决方案


我认为您也需要将 df['W $ Units']、df['X $ Units'] 和 df['Y $ Units'] 转换为 1。例如,使用 df['Y $ Units'].shift(1) 代替 df['Y $ Units']。

你得到的结果并不糟糕——这是不现实的。不移动 df['... $ Units'] 您正在展望并使用尚不可用的数据。


推荐阅读