ビットコインの未来の動きを予測?「線形回帰チャネル」で取引にチャレンジしてみよう!
「線形回帰チャネル」って聞いたことありますか?なんだか難しそうですよね。でも実は、ビットコインみたいに値段が大きく変わるものの、これからの動きを予想するのに役立つ、面白い方法なんです。今回は、この方法を分かりやすく説明しますね!
導入と前提条件
「線形回帰チャネル」って聞いたことありますか?なんだか難しそうですよね。でも実は、ビットコインみたいに値段が大きく変わるものの、これからの動きを予想するのに役立つ、面白い方法なんです。今回は、この方法を分かりやすく説明しますね!
【検証】戦略のバックテスト概要
- 戦略名: Linear Regression Channel を使用したトレンド追従戦略
- 対象銘柄: BTC/USDT
- 時間足: 1h
- 期間: 2025-04-28〜2025-08-26(119日間)
- 初期資金: $10,000
- 手数料・スリッページ: 0.1% / 0.1%
- 取引所: binance
Linear Regression Channel の理論的背景
この作戦は、「値段って、だいたい決まった範囲の中で動くことが多いよね」という考え方が元になっています。これまでの値段の動きを参考にして、未来の値段が通りそうな「真ん中の線」と、その周りの「川幅みたいな線(チャネル)」を引きます。値段が川幅の上の線に近づいたら「ちょっと上がりすぎかな?」、下の線に近づいたら「ちょっと下がりすぎかな?」と考えて、値段の動きすぎをキャッチしようとする方法です。
具体的な売買ルール(今回の検証)
エントリー条件
- 値段が下の線を突き抜けて、そこから値段が上がる向きに変わったら「買い」で取引を始めます。
- 値段が上の線を突き抜けて、そこから値段が下がる向きに変わったら「売り」で取引を始めます。
エグジット条件
- 「買い」で始めていた場合、値段が真ん中の線まで戻ってきたら取引を終えます。もし予想と反対に、もっと下がってしまった時も、大きな損になる前に取引を終えます。
- 「売り」で始めていた場合、値段が真ん中の線まで戻ってきたら取引を終えます。もし予想と反対に、もっと上がってしまった時も、大きな損になる前に取引を終えます。
リスク管理
一度に大きなお金を使わず、少しずつチャレンジすることが大切です。もし予想が外れても、大きな失敗にならないように、あらかじめ「ここまで損したらやめる」というルールを決めておきます。ゲームでライフがゼロになる前に、いったん引いてやり直すのに似ていますね。
再現手順(HowTo)
- Python/依存(ccxt, pandas, ta)をインストール
- ccxtでBTC/USDTのOHLCVを取得して前処理
- 『Linear Regression Channel』に必要な指標を算出(ta 等)
- 閾値・クロス条件から売買シグナルを生成
- 手数料・スリッページを加味して検証・評価
【結果】パフォーマンス
価格の推移
資産の推移
パフォーマンス指標
指標 | 値 |
---|---|
総トレード数 | 10回 |
勝率 | 50% |
平均利益 | 1.92% |
平均損失 | -2.22% |
期待値 | -0.15% |
プロフィットファクター | 0.84 |
最大ドローダウン | 10.7% |
最終リターン | -1.61% |
シャープレシオ | -0.01 |
HODL(Buy&Hold) | 16.58% |
HODL戦略との比較
実装コード(Python)
"""
Linear Regression Channel Trading Signal
線形回帰チャネルを使用した統計的戦略
"""
import pandas as pd
import numpy as np
def calculate_linear_regression_channel_signals(df: pd.DataFrame,
period: int = 100,
deviation: float = 2.0) -> pd.DataFrame:
"""
Linear Regression Channel戦略のシグナル生成
Parameters:
-----------
df : pd.DataFrame
OHLCVデータ
period : int
回帰期間(デフォルト: 100)
deviation : float
標準偏差の倍数(デフォルト: 2.0)
Returns:
--------
pd.DataFrame
シグナルが追加されたDataFrame
"""
df = df.copy()
# 線形回帰の計算
df['lr_line'] = pd.Series(index=df.index, dtype=float)
df['lr_slope'] = pd.Series(index=df.index, dtype=float)
df['lr_upper'] = pd.Series(index=df.index, dtype=float)
df['lr_lower'] = pd.Series(index=df.index, dtype=float)
df['r_squared'] = pd.Series(index=df.index, dtype=float)
for i in range(period - 1, len(df)):
# 期間内のデータ
y = df['close'].iloc[i - period + 1:i + 1].values
x = np.arange(period)
# 線形回帰(numpy使用)
A = np.vstack([x, np.ones(len(x))]).T
m, c = np.linalg.lstsq(A, y, rcond=None)[0]
slope, intercept = m, c
# 相関係数
correlation = np.corrcoef(x, y)[0, 1]
r_value = correlation
# 回帰線の値
regression_line = slope * x + intercept
current_value = slope * (period - 1) + intercept
# 残差の標準偏差
residuals = y - regression_line
std_dev = np.std(residuals)
# 値を保存
df.loc[df.index[i], 'lr_line'] = current_value
df.loc[df.index[i], 'lr_slope'] = slope
df.loc[df.index[i], 'lr_upper'] = current_value + deviation * std_dev
df.loc[df.index[i], 'lr_lower'] = current_value - deviation * std_dev
df.loc[df.index[i], 'r_squared'] = r_value ** 2
# 短期の線形回帰(エントリータイミング用)
short_period = int(period / 4)
df['lr_short'] = pd.Series(index=df.index, dtype=float)
df['lr_short_slope'] = pd.Series(index=df.index, dtype=float)
for i in range(short_period - 1, len(df)):
y = df['close'].iloc[i - short_period + 1:i + 1].values
x = np.arange(short_period)
A = np.vstack([x, np.ones(len(x))]).T
m, c = np.linalg.lstsq(A, y, rcond=None)[0]
slope, intercept = m, c
current_value = slope * (short_period - 1) + intercept
df.loc[df.index[i], 'lr_short'] = current_value
df.loc[df.index[i], 'lr_short_slope'] = slope
# シグナル初期化
df['signal'] = 0
df['is_buy'] = False
df['is_sell'] = False
# 現在のポジション状態を追跡
position = 0
for i in range(period, len(df)):
# 買いシグナル(下部チャネルからの反発)
if position <= 0 and df['close'].iloc[i] <= df['lr_lower'].iloc[i] and df['lr_slope'].iloc[i] > 0:
df.loc[df.index[i], 'is_buy'] = True
df.loc[df.index[i], 'signal'] = 1
position = 1
# 売りシグナル(上部チャネルからの反落)
elif position >= 0 and df['close'].iloc[i] >= df['lr_upper'].iloc[i] and df['lr_slope'].iloc[i] < 0:
df.loc[df.index[i], 'is_sell'] = True
df.loc[df.index[i], 'signal'] = -1
position = -1
else:
# ポジション維持
df.loc[df.index[i], 'signal'] = position
# NaN値を0で埋める
df['signal'] = df['signal'].fillna(0)
# エグジットシグナル
df['exit_signal'] = 0
# 回帰線タッチでエグジット
for i in range(period, len(df)):
# ロングポジションのエグジット
if df['signal'].iloc[i] == 1:
if df['close'].iloc[i] >= df['lr_line'].iloc[i] or df['close'].iloc[i] <= df['lr_lower'].iloc[i] - df['lr_lower'].iloc[i] * 0.02:
df.loc[df.index[i], 'exit_signal'] = -1
# ショートポジションのエグジット
if df['signal'].iloc[i] == -1:
if df['close'].iloc[i] <= df['lr_line'].iloc[i] or df['close'].iloc[i] >= df['lr_upper'].iloc[i] + df['lr_upper'].iloc[i] * 0.02:
df.loc[df.index[i], 'exit_signal'] = 1
return df
def get_strategy_name() -> str:
"""戦略名を返す"""
return "Linear Regression Channel"
def get_strategy_description() -> str:
"""戦略の説明を返す"""
return "線形回帰チャネルの上下限でのリバーサルを狙う統計的戦略"
なぜこの結果になったのか(3つの理由)
- 1結果的に少し損をしてしまったのは、この作戦が、試した期間のビットコインの動き方と、あまり相性が良くなかったからかもしれません。
- 2勝ったり負けたりは半々くらいだったのですが、負けたときのダメージが、勝ったときの嬉しさよりも大きかったのが、全体でマイナスになった大きな原因です。
- 3ただビットコインを持っているだけの方が、結果が良かったんです。これは、この作戦が、ビットコインがぐんぐん値上がりしていく大きな波にうまく乗れなかったことを表しています。
この結果から学べる3つの教訓
- 1どんな時でもうまくいく「完璧な作戦」はないんだ、ということが分かりました。その時々の状況に合わせて、作戦を使い分けることが大事なんですね。
- 2勝つ回数が多いだけではダメで、勝った時に大きく勝ち、負けた時に少しのダメージで済ませることが大切だと学びました。
- 3昔のデータでうまくいくかテストしても、未来も同じ結果になるとは限らないんですね。いつも状況をチェックして、作戦を見直していく必要があります。
リスク管理の具体的手法
取引量の決め方
取引に使うお金は、持っているお小遣いのほんの一部だけにします。もし負けても、全体のお金がガクッと減らないようにするためです。これが一番大事なルールです。
損失が大きくなったときの対処法
もし負けが続いてしまって、お金がちょっと減ってきたら、いったんお休みします。そして、どうして負けたのか冷静に考え直します。ゲームで連敗したら、一度休憩して作戦を立て直すのと同じですね。
資金管理の方法
「取引に使うお金」と「大事にとっておくお金」をしっかり分けます。負けた分を取り返そうと焦って、大きなお金をつぎ込んだりするのは絶対にダメです。計画的にお金を管理しましょう。
改良案の具体的提案
- 作戦で使う「チャネルの線の幅」などの設定を色々変えてみて、もっとうまくいく組み合わせを探してみます。
- 値段がどんどん上がっているような時には、この作戦がうまく働くように、ルールを少し変えたり、新しいルールを加えたりしてみます。
- 取引を「やめるタイミング」のルールをもっと工夫して、損を小さくして、利益を大きく伸ばせるように改善します。
実用性の向上(運用上の注意)
- この作戦は、ビットコイン以外でも、色々なものの値段で試せます。でも、それぞれに合った設定を見つけるのがポイントです。
- 本番で使う前に、まずは昔のデータでたくさん練習(テスト)をして、この作戦が本当にうまくいくか確かめることが大事です。
- この作戦一つだけに頼るのではなく、ニュースを見たり、世の中全体の動きを気にしたり、他の調べ方と組み合わせると、もっと成功しやすくなるかもしれません。
検証の透明性と信頼性
- データの出所: このテストで使ったのは、ビットコインなどを売ったり買ったりできる場所が公開している、昔のビットコインの値段のデータ(1時間ごと)です。
- 検証のやり方: 昔の値段のデータを使って、この作戦で取引したらどれくらいプラスになったりマイナスになったりしたかを計算して、テストしました。
- コード: このテストで使った計算プログラムは、みんなが見られるようになっています。なので、誰でも同じようにテストしたり、もっと良くしたりできます。
- 注意事項: これは、あくまで勉強のための情報です。「こうすれば絶対もうかる」というものではありません。もし実際にお金を使って取引する時は、自分でよく考えて、自分の責任で行ってくださいね。昔うまくいったからといって、未来もうまくいくとは限りません。