今回は、為替キャリー戦略を分析してみます。
使用するデータは以前紹介した為替データをくりっく365を使って取得したものを用います。
キャリー戦略とは
キャリー戦略は、高金利通貨を買って、低金利通貨を売る戦略です。高金利通貨は買うとその期間に応じて、金利が入ります。一方、売りの低金利通貨に対しては金利を支払う必要がありますが、高金利通貨の方がもらう金利が多いので、差し引きはプラスになります。
この時、高金利通貨と低金利通貨の金利差から得られる利益がスワップポイントになります。
理論的には、金利の受け取り分と購入通貨のリターンが相殺されて、利益は得られないという無裁定条件が成立しますが、現実世界では高金利通貨を買うことで利益が得られる、フォワード・プレミアム・パズルというアノマリーが知られています。
そこで、今回はこのキャリー戦略をシミュレーションしてみます。
Pythonでの実装
まずはデータを処理します。
一部の通貨のスワップポイントの単位が10万通貨単位になっているので、1万通貨単位に変換します。
import pandas as pd
folder = "保存場所"
df = pd.DataFrame()
for i in range(1,21):
df_ = pd.read_csv(folder + f'fx_result ({i}).csv', encoding='shift-jis',header=2)
df = pd.concat([df, df_])
#くりっく365からダウンロードしたデータ
cols = ['USD/JPY', 'EUR/JPY', 'GBP/JPY', 'AUD/JPY', 'CHF/JPY', 'CAD/JPY',
'NZD/JPY', 'ZAR/JPY', 'TRY/JPY', 'NOK/JPY', 'HKD/JPY', 'SEK/JPY',
'PLN/JPY', 'CNY/JPY', 'KRW/JPY', 'INR/JPY', 'MXN/JPY']
cols_10 = ['MXN/JPY', 'ZAR/JPY', 'NOK/JPY', 'HKD/JPY','SEK/JPY']
rtn = pd.pivot(df, columns='商品名', index='取引日', values='前日比').sort_index().astype(float)[cols]
swap_raw = pd.pivot(df, columns='商品名', index='取引日', values='スワップポイント').sort_index().astype(str)[cols]
swap_raw = swap_raw.applymap(lambda x: float(x.replace(',','')) if isinstance(x,str) else x)
swap_raw.loc[:,cols_10] = swap_raw.loc[:,cols_10]/10
price_raw = pd.pivot(df, columns='商品名', index='取引日', values='当日清算価格').sort_index().astype(str)[cols]
price_raw = price_raw.applymap(lambda x: float(x.replace(',','')) if isinstance(x,str) else x)
swap = swap_raw / price_raw/10000*100
スワップポイントによる利回りの高い通貨、低い通貨、中間の通貨の3つに分類して、高い通貨を買い、低い通貨を売ります。
from tqdm import tqdm
result = pd.DataFrame(index=rtn.index, columns=['rtn','swap'])
for i in tqdm(range(len(rtn.index))):
swap_d = swap.iloc[i,:].sort_values().dropna()
if len(swap_d) >= 6:
label_cut = pd.cut(swap_d.rank(),bins=3, labels=['l','m','h'])
h_idx = label_cut[label_cut=='h'].index
l_idx = label_cut[label_cut=='l'].index
drtn = rtn.iloc[i,:][h_idx].mean() - rtn.iloc[i,:][l_idx].mean()
result.loc[rtn.index[i], 'rtn'] = drtn
result.loc[rtn.index[i], 'swap'] = swap.iloc[i,:][h_idx].mean() - swap.iloc[i,:][l_idx].mean()
為替リターンだけで見ると、ややマイナスですが、スワップを加味するときれいな右肩上がりになっています。
import matplotlib.pyplot as plt
result['rtn'].cumsum().plot()
plt.show()
(result['rtn'] + result['swap']).cumsum().plot()