値段の勢いを見てチャレンジ!SOL/USDTで試す「VMA作戦」のしくみ
この作戦は、「SOL」と「USDT」という2つのインターネット上のお金の値段が、どれくらい元気よく動いているかを見て、いつ買って、いつ売るかを決める方法です。4時間ごとに値段をチェックして、2024年11月10日から2025年8月25日までのデータで試してみました。
導入と前提条件
この作戦は、「SOL」と「USDT」という2つのインターネット上のお金の値段が、どれくらい元気よく動いているかを見て、いつ買って、いつ売るかを決める方法です。4時間ごとに値段をチェックして、2024年11月10日から2025年8月25日までのデータで試してみました。
【検証】戦略のバックテスト概要
- 戦略名: Variable Moving Average を使用したトレンド追従戦略
- 対象銘柄: SOL/USDT
- 時間足: 4h
- 期間: 2024-11-10〜2025-08-25(287日間)
- 初期資金: $10,000
- 手数料・スリッページ: 0.1% / 0.1%
- 取引所: kucoin
Variable Moving Average の理論的背景
この作戦は、値段が「どれだけ元気に動いているか」を一番大切にしています。値段がグングン上がろうとしている時は、VMAの線も一緒に上がっていきます。そして、値段がVMAの線を上に突き抜けた時が、「買ってみようかな?」と考えるチャンスです。逆に、値段がどんどん下がっている時は、VMAの線も下がっていきます。そして、値段がVMAの線を下に突き抜けた時が、「売ってみようかな?」と考えるチャンスです。値段とVMAの線の関係を見ながら、より良いタイミングを探すんです。
具体的な売買ルール(今回の検証)
エントリー条件
- 値段がVMAの線を下から上に追い越して、そのVMAの線自体も上を向いているとき。
- 値段がVMAの線よりも上にあって、そのVMAの線が上を向いているとき。
エグジット条件
- 値段がVMAの線を上から下に割り込んで、そのVMAの線自体も下を向いているとき。
- 値段がVMAの線よりも下にあって、そのVMAの線が下を向いているとき。
リスク管理
この作戦では、損が大きくなりすぎないように、あらかじめ「これ以上損したらストップする」というルールを決めておきます。もし思ったよりも損が出そうになったら、無理に続けずに、一旦お休みして作戦を考え直すことがとても大事です。
再現手順(HowTo)
- Python/依存(ccxt, pandas, ta)をインストール
- ccxtでSOL/USDTのOHLCVを取得して前処理
- 『Variable Moving Average』に必要な指標を算出(ta 等)
- 閾値・クロス条件から売買シグナルを生成
- 手数料・スリッページを加味して検証・評価
【結果】パフォーマンス
価格の推移
資産の推移
パフォーマンス指標
指標 | 値 |
---|---|
総トレード数 | 81回 |
勝率 | 33.33% |
平均利益 | 5.45% |
平均損失 | -3.01% |
期待値 | -0.19% |
プロフィットファクター | 0.81 |
最大ドローダウン | 57.86% |
最終リターン | -25.83% |
シャープレシオ | -0.13 |
HODL(Buy&Hold) | -1.52% |
HODL戦略との比較
実装コード(Python)
"""
Variable Moving Average Trading Signal Generator
ボラティリティに応じて動的に調整される移動平均
"""
import pandas as pd
import numpy as np
def calculate_vma_signals(df: pd.DataFrame,
period: int = 20,
sensitivity: float = 0.5) -> pd.DataFrame:
"""
Variable Moving Average戦略のシグナル生成
Parameters:
-----------
df : pd.DataFrame
OHLCVデータ
period : int
基本期間(デフォルト: 20)
sensitivity : float
感度係数(デフォルト: 0.5)
Returns:
--------
pd.DataFrame
シグナルが追加されたDataFrame
"""
df = df.copy()
# 変動率(ボラティリティ)計算
df['price_change'] = np.abs(df['close'] - df['close'].shift(1))
# 方向性指標
df['direction'] = df['close'] - df['close'].shift(1)
df['positive_change'] = np.where(df['direction'] > 0, df['price_change'], 0)
df['negative_change'] = np.where(df['direction'] < 0, df['price_change'], 0)
# Volatility Index(VI)
df['pos_sum'] = df['positive_change'].rolling(window=period).sum()
df['neg_sum'] = df['negative_change'].rolling(window=period).sum()
df['vi'] = df['pos_sum'] / (df['pos_sum'] + df['neg_sum'] + 0.0001)
# Variable Ratio(VR)
df['vr'] = 2 * np.abs(df['vi'] - 0.5) * sensitivity
# Alpha(平滑化係数)
df['alpha'] = 2 / (period * df['vr'] + 1)
# Variable Moving Average
df['vma'] = df['close'].copy()
for i in range(1, len(df)):
if i >= period:
alpha = df.iloc[i]['alpha']
if not np.isnan(alpha):
df.loc[df.index[i], 'vma'] = alpha * df.iloc[i]['close'] + (1 - alpha) * df.iloc[i-1]['vma']
# VMA傾き(トレンド方向)
df['vma_slope'] = df['vma'] - df['vma'].shift(1)
df['vma_trend'] = df['vma_slope'].rolling(window=3).mean()
# 価格とVMAの位置関係
df['price_above_vma'] = df['close'] > df['vma']
df['price_below_vma'] = df['close'] < df['vma']
# シグナル生成
df['price_above_prev'] = df['price_above_vma'].shift(1)
df['price_below_prev'] = df['price_below_vma'].shift(1)
df['is_buy'] = (
(df['price_above_vma'] & (df['price_above_prev'] == False)) & # VMAを上抜け
(df['vma_trend'] > 0) # VMAが上昇トレンド
) & df['vma'].notna()
df['is_sell'] = (
(df['price_below_vma'] & (df['price_below_prev'] == False)) & # VMAを下抜け
(df['vma_trend'] < 0) # VMAが下降トレンド
) & df['vma'].notna()
# 不要カラム削除
df.drop(['price_change', 'direction', 'positive_change', 'negative_change',
'pos_sum', 'neg_sum', 'vi', 'vr', 'alpha', 'vma_slope', 'vma_trend',
'price_above_vma', 'price_below_vma', 'price_above_prev', 'price_below_prev'],
axis=1, inplace=True, errors='ignore')
return df
なぜこの結果になったのか(3つの理由)
- 1勝てたのが3回に1回くらいと少なかったのは、ちょっとした値段の動きにすぐ反応しすぎて、本当はチャンスじゃないのに「行けるかも!」と勘違いしてしまう「ニセモノのサイン」に、だまされちゃったからかもしれません。
- 2トータルで損をしてしまったのは、勝ったときの「もうけ」が小さくて、負けたときの「損」が大きかったからだと考えられます。だから、全部合わせるとマイナスになってしまったんですね。
- 3一番お金が減ってしまった時に、もっていたお金の半分以上がなくなってしまうくらい大きな損が出たのは、「損が大きくなりすぎないようにする」という守りのルールが、うまく働いていなかったからかもしれません。
この結果から学べる3つの教訓
- 1値段の勢いも大事だけど、その勢いが本物で、ちゃんと続くかどうかをしっかり見極めることが大切だとわかりました。
- 2たとえ勝つ回数が少なくても、一回勝ったときに大きな「もうけ」を出せれば、全部合わせるとプラスにできる可能性がある、ということも学びました。
- 3どんなにすごい作戦でも、「損を小さくする工夫」をちゃんとしておかないと、一度の失敗で大損してしまうことがある、ということがよくわかりました。
リスク管理の具体的手法
取引量の決め方
1回のチャレンジで使うお金は、持っているお金全体の2%まで、と決めておきます。こうすれば、もし負けてしまっても、全体へのダメージを小さくできます。
損失が大きくなったときの対処法
もしお金が一番増えた時から10%以上減ってしまったら、一度全部の取引をお休みします。そして、作戦をもう一度見直す、というルールです。これで、これ以上損が広がるのを防ぎます。
資金管理の方法
もうかったお金の一部は、安全な場所に移しておくなど、お金を上手に管理します。負けたからといって、次で取り返そうと焦って大金を使わないようにすることも大事です。
改良案の具体的提案
- VMAの線の反応の速さを変えてみて、ちょっとした動きに反応しすぎないように調整し、「ニセモノのサイン」を減らせるか試してみます。
- この作戦に加えて、別の道具(例えば、他の種類の線が交差するのを見る、など)も一緒に使って、もっと確かなタイミングで売ったり買ったりできるようにします。
- 「この金額まで損したら、潔くあきらめる」という損切りのルールを、もっとハッキリ決めて、大きな損をしないように工夫します。
実用性の向上(運用上の注意)
- 今回は「SOL/USDT」という組み合わせと「4時間ごと」というルールで試しましたが、他のインターネット上のお金の組み合わせや、もっと短い時間(例えば1時間ごと)で試してみるのも面白いかもしれません。
- 作戦の中の細かい設定(線の動きの速さなど)を色々と変えてみて、どれが一番良い成績になるか、自分で試してみることが上達の近道です。
- この作戦は、あくまで昔のデータで試した結果です。未来も同じようになるとは限りません。試すときは、必ず自分の判断と責任で、なくなっても困らない少額から始めましょう。
検証の透明性と信頼性
- データの出所: 使った値段のデータ(始めの値段、高い値段、安い値段、終わりの値段など)は、Binanceのような、みんなが見られる取引所のサイトから持ってきました。
- 検証のやり方: Pythonというプログラミング言語を使って、「もしこの作戦を昔からやっていたら、どれくらいうまくいったかな?」というシミュレーション(バックテスト)をして、結果を確かめました。
- コード: この作戦を動かすためのコンピュータープログラムは、インターネット上で見られるようになっています。
- 注意事項: このお話は、投資をおすすめするものではありません。インターネット上のお金の取引は、値段が大きく変わることがあり、大きな損をしてしまう可能性もあります。投資をする時は、必ず自分の判断と責任で行ってください。