7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

BTCとTQQQで何作ろう♪

Posted at

右手はロングで左手はショートでペアトレード♪

newplot.png

import numpy as np
import pandas as pd
import yfinance as yf
import statsmodels.api as sm
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 1. yfinanceでデータ取得
symbols = ['BTC-USD', 'TQQQ']
data = yf.download(symbols, start="2018-01-01")
data = data['Close'].dropna()
data /= data.iloc[0]

# 2. 2つの銘柄の価格データ
asset1 = data['BTC-USD']
asset2 = data['TQQQ']

# 3. 統計的アービトラージを確認するためのOLS回帰
# 資産1を資産2に対して回帰し、ヘッジレシオを計算
#X = sm.add_constant(asset2)
#model = sm.OLS(asset1, X).fit()
#hedge_ratio = model.params[1]
hedge_ratio = 1
print('hedge_ratio:', hedge_ratio)

# 4. スプレッドを計算
spread = asset1 - hedge_ratio * asset2

# 5. スプレッドの平均回帰性を確認(移動平均と標準偏差)
window = 200
spread_mean = spread.rolling(window=window).mean().dropna()
spread_std = spread.rolling(window=window).std().dropna()
spread = spread.loc[spread_mean.index]

# 6. シグナル生成(±1σを超えた場合にエントリー)
long_signal = (spread < (spread_mean - spread_std))  # 割安シグナル
short_signal = (spread > (spread_mean + spread_std))  # 割高シグナル

# 7. ポジション管理
positions = pd.DataFrame(index=spread.index)
positions['asset1'] = np.where(long_signal, 1, np.where(short_signal, -1, 0))
positions['asset2'] = -hedge_ratio * positions['asset1']
# ロングオンリーの戦略にする
#positions['asset1'] = spread <= spread_mean
#positions['asset2'] = spread > spread_mean

# 8. リターン計算
returns = pd.DataFrame(index=spread.index)
returns['asset1'] = positions['asset1'].shift(1) * asset1.pct_change()
returns['asset2'] = positions['asset2'].shift(1) * asset2.pct_change()

# 総リターン
returns['total'] = returns.sum(axis=1)

# 9. リターンの累積プロット
cumulative_returns = (1 + returns['total']).cumprod()
cum_btc = (1 + asset1.pct_change()).cumprod().loc[cumulative_returns.index]
cum_tqqq = (1 + asset2.pct_change()).cumprod().loc[cumulative_returns.index]

# インタラクティブグラフ作成
fig = make_subplots(
    rows=2, cols=1, 
    shared_xaxes=True, 
    vertical_spacing=0.08,
    subplot_titles=('Cumulative Returns Comparison', 'Spread with Mean and Standard Deviation')
)

# 上段: リターン
fig.add_trace(
    go.Scatter(x=cumulative_returns.index, y=cumulative_returns, name='Pair Trading', line=dict(color='blue')),
    row=1, col=1
)
fig.add_trace(
    go.Scatter(x=cum_btc.index, y=cum_btc, name='BTC-USD', line=dict(color='orange')),
    row=1, col=1
)
fig.add_trace(
    go.Scatter(x=cum_tqqq.index, y=cum_tqqq, name='TQQQ', line=dict(color='green')),
    row=1, col=1
)

fig.update_yaxes(type='log', row=1, col=1, title_text='Cumulative Returns')

# 下段: スプレッド
fig.add_trace(
    go.Scatter(x=spread.index, y=spread, name='Spread', line=dict(color='red')),
    row=2, col=1
)
fig.add_trace(
    go.Scatter(x=spread_mean.index, y=spread_mean, name='Mean', line=dict(color='black', dash='dash')),
    row=2, col=1
)
fig.add_trace(
    go.Scatter(x=spread_mean.index, y=spread_mean+spread_std, name='+1 SD', line=dict(color='gray', dash='dot')),
    row=2, col=1
)
fig.add_trace(
    go.Scatter(x=spread_mean.index, y=spread_mean-spread_std, name='-1 SD', line=dict(color='gray', dash='dot')),
    row=2, col=1
)

fig.update_yaxes(title_text='Spread', row=2, col=1)
fig.update_xaxes(title_text='Date', row=2, col=1)

fig.update_layout(
    height=900, width=900,
    showlegend=True,
    legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
    hovermode='x unified',
    title_text="Pair Trading: BTC-USD & TQQQ"
)
fig.show()
7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?