ビットコインの値動きの「勢い」をつかまえる!ASI作戦のやさしい解説
この作戦は、ビットコイン(BTC/USDT)が1時間ごとにどう動くかを「勢い」で見て、買うか売るかのタイミングを見つける方法です。2025年のある期間でこの作戦を試してみたらどうなったか、その結果とわかったことをわかりやすく説明しますね。
導入と前提条件
この作戦は、ビットコイン(BTC/USDT)が1時間ごとにどう動くかを「勢い」で見て、買うか売るかのタイミングを見つける方法です。2025年のある期間でこの作戦を試してみたらどうなったか、その結果とわかったことをわかりやすく説明しますね。
【検証】戦略のバックテスト概要
- 戦略名: Accumulated Swing Index を使用したトレンド追従戦略
- 対象銘柄: BTC/USDT
- 時間足: 1h
- 期間: 2025-04-28〜2025-08-26(119日間)
- 初期資金: $10,000
- 手数料・スリッページ: 0.1% / 0.1%
- 取引所: binance
Accumulated Swing Index の理論的背景
この作戦の基本的な考え方は、「値段の勢いが続くなら、その流れに乗ればもうかるかも」というものです。ASIは、その日の値動きの大きさや、前の時間との値段の差などを合わせて、「今の勢い」を数字で表してくれます。さらに、そのASIの数字の「平均的な流れ」を見るために、平均線というものを使います。ASIが平均線を上向きにこえたら「お、勢いがついてきた!これから上がるかも?」と考えて買いの合図にします。逆に、下向きにこえたら「あれ、勢いがなくなってきた。これから下がるかも?」と考えて売りの合図にします。
具体的な売買ルール(今回の検証)
エントリー条件
- ASIが平均線より上で、しかも前の時間よりASIの数字が大きくなったとき(勢いが強くなってきた!)。これは「買う」タイミングです。
- すでに「売り」の状態で、ASIが平均線より下で、しかも前の時間よりASIの数字が小さくなったとき(勢いが弱まってきた!)。これは「さらに売る」か、新しく「売る」タイミングです。
エグジット条件
- 「買い」の状態で、ASIが平均線より下になり、しかも前の時間よりASIの数字が小さくなったとき(勢いが弱まってきた!)。これは「売り買いを終えて、もうけを自分のものにする」タイミングです。
- 「売り」の状態で、ASIが平均線より上になり、しかも前の時間よりASIの数字が大きくなったとき(勢いが強くなってきた!)。これは「売り買いを終えて、損を確定するか、もうけを自分のものにする」タイミングです。
リスク管理
この作戦では、取引した回数が226回と多く、勝ったのは18.14%と低めでした。つまり、5回に1回も勝てなかったということです。だから、1回の取引で大負けしないように、損する可能性を考えて、一度に取引する量を慎重に決めることがとっても大事になります。
再現手順(HowTo)
- Python/依存(ccxt, pandas, ta)をインストール
- ccxtでBTC/USDTのOHLCVを取得して前処理
- 『Accumulated Swing Index』に必要な指標を算出(ta 等)
- 閾値・クロス条件から売買シグナルを生成
- 手数料・スリッページを加味して検証・評価
【結果】パフォーマンス
価格の推移
資産の推移
パフォーマンス指標
指標 | 値 |
---|---|
総トレード数 | 226回 |
勝率 | 18.14% |
平均利益 | 1.08% |
平均損失 | -0.7% |
期待値 | -0.38% |
プロフィットファクター | 0.35 |
最大ドローダウン | 57.73% |
最終リターン | -57.73% |
シャープレシオ | -1.74 |
HODL(Buy&Hold) | 16.7% |
HODL戦略との比較
実装コード(Python)
"""
Accumulated Swing Index Trading Signal
ASIを使用したトレンド追従戦略
"""
import pandas as pd
import numpy as np
def calculate_accumulated_swing_index_signals(df: pd.DataFrame,
limit_move: float = 0.5) -> pd.DataFrame:
"""
Accumulated Swing Index戦略のシグナル生成
Parameters:
-----------
df : pd.DataFrame
OHLCVデータ
limit_move : float
制限価格動き(デフォルト: 0.5)
Returns:
--------
pd.DataFrame
シグナルが追加されたDataFrame
"""
df = df.copy()
# Swing Index計算
df['c1'] = df['close'].shift(1)
df['o1'] = df['open'].shift(1)
df['h1'] = df['high'].shift(1)
df['l1'] = df['low'].shift(1)
df['k'] = np.maximum(df['high'] - df['c1'], df['c1'] - df['low'])
# R計算
df['r'] = 0.0
df['hl'] = np.abs(df['high'] - df['c1'])
df['lc'] = np.abs(df['low'] - df['c1'])
df['hc'] = np.abs(df['high'] - df['low'])
# 条件分岐
mask1 = (df['hl'] >= df['lc']) & (df['hl'] >= df['hc'])
mask2 = (df['lc'] >= df['hl']) & (df['lc'] >= df['hc'])
mask3 = (df['hc'] >= df['hl']) & (df['hc'] >= df['lc'])
df.loc[mask1, 'r'] = df.loc[mask1, 'hl'] - 0.5 * df.loc[mask1, 'lc'] + 0.25 * (df.loc[mask1, 'c1'] - df.loc[mask1, 'o1'])
df.loc[mask2, 'r'] = df.loc[mask2, 'lc'] - 0.5 * df.loc[mask2, 'hl'] + 0.25 * (df.loc[mask2, 'c1'] - df.loc[mask2, 'o1'])
df.loc[mask3, 'r'] = df.loc[mask3, 'hc'] + 0.25 * (df.loc[mask3, 'c1'] - df.loc[mask3, 'o1'])
# Swing Index
df['si'] = 50 * ((df['close'] - df['c1']) + 0.5 * (df['close'] - df['open']) + 0.25 * (df['c1'] - df['o1'])) / (df['r'] + 0.0001) * (df['k'] / limit_move)
df['asi'] = df['si'].cumsum()
# ASIトレンド
df['asi_ma'] = df['asi'].rolling(window=10).mean()
# シグナル初期化
df['signal'] = 0
df['is_buy'] = False
df['is_sell'] = False
position = 0
for i in range(10, len(df)):
# 買いシグナル
if position <= 0 and df['asi'].iloc[i] > df['asi_ma'].iloc[i] and df['asi'].iloc[i] > df['asi'].iloc[i-1]:
df.loc[df.index[i], 'is_buy'] = True
df.loc[df.index[i], 'signal'] = 1
position = 1
# 売りシグナル
elif position >= 0 and df['asi'].iloc[i] < df['asi_ma'].iloc[i] and df['asi'].iloc[i] < df['asi'].iloc[i-1]:
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
df['signal'] = df['signal'].fillna(0)
return df
def get_strategy_name() -> str:
"""戦略名を返す"""
return "Accumulated Swing Index"
def get_strategy_description() -> str:
"""戦略の説明を返す"""
return "ASIを使用したトレンド追従戦略"
なぜこの結果になったのか(3つの理由)
- 1勝った割合が低くて、最終的に損してしまったのは、この作戦がビットコインの急な値動きにうまくついていけなかったからかもしれません。
- 2いちばん大きく損した割合(最大DD)が57.73%と大きかったのは、たった1回の取引で大負けしてしまったか、負けが続いてしまった時期があったということです。
- 3もしこの作戦を使わずに、ただビットコインをずっと持っていた場合(HODL)、16.7%のもうけが出ていました。それよりも成績が悪かったということは、この作戦で取引したことで、逆に損が大きくなってしまったということです。
この結果から学べる3つの教訓
- 1値上がりの流れに乗る作戦でも、いつでもうまくいくわけじゃないんだ、ということがわかりました。
- 2勝つ回数が少ない分、1回で失うお金をできるだけ小さくする工夫が必要だと学びました。
- 3過去のデータでうまくいったように見えても、それが未来でもうまくいくとは限りません。本当に使えるか、もっと試してみることが大事だとわかりました。
リスク管理の具体的手法
取引量の決め方
1回の取引で失ってもいい金額(たとえば、持っているお金の1%とか2%)を先に決めます。そして、その金額から「じゃあ、1回にどれくらいの量のビットコインを取引しようかな」と決めます。勝つ回数が少ないので、1回の負けを小さくすることが特に大事です。
損失が大きくなったときの対処法
もし損した金額が、持っているお金の10%みたいに、決めた額を超えてしまったら、一度全部の取引をやめて作戦を考え直す、というルールを作るのもいいでしょう。今回は大きく損したので、こういうルールは絶対に必要です。
資金管理の方法
投資に使うお金全体のうち、実際に取引に使うお金の割合を決めます。また、1回の取引で失うかもしれない最大の金額を、持っているお金全体の数パーセントまでにするように管理します。
改良案の具体的提案
- ASIを計算するときの設定の数字を変えてみて、値動きの捉え方を変えてみる方法があります。
- 「買おう!」「売ろう!」という合図が出てもすぐには動かず、もう一つ別の条件(たとえば、値段がもう少し動くまで待つとか)を加えて、もっと確実なときだけ取引するようにしてみる。
- この作戦だけじゃなくて、他の作戦と組み合わせたり、「これ以上損したらやめる」という損切りのルールを厳しく決めたりする。
実用性の向上(運用上の注意)
- この結果は、あくまで過去のものです。未来も同じ結果になるとは限りません。もし試すなら、必ず少ない金額から始めてみましょう。
- 「買う」「やめる」のタイミングを決めるとき、ASIと平均線だけじゃなく、他の道具も一緒に見て判断すると、もっと安全になるかもしれません。
- 取引する時間の区切り(今回は1時間ごと)や、通貨の種類(今回はビットコイン)を変えると、作戦の成績も変わることがあります。色々なパターンで試してみると良いかもしれません。
検証の透明性と信頼性
- データの出所: この説明は、もらった過去のデータをもとに作っています。
- 検証のやり方: もらったプログラムと設定を使って、決められた期間(2025-04-28〜2025-08-26)のビットコイン(BTC/USDT)の1時間ごとのデータで、本当にこの結果になるか試しました。
- コード: この作戦を動かすためのプログラムはあります。
- 注意事項: これは「投資したほうがいいよ」とおすすめする情報ではありません。投資には、お金が減ってしまう危険があります。投資をするかどうかは、ご自身の判断と責任でお願いします。