市場の『気分』を読んでみよう!BNB/USDTの売り買い作戦をわかりやすく解説します
ここでは、ネット上のお金の一種「BNB/USDT」というセットを、5分ごとの短い時間で売り買いする作戦を紹介します。市場の『気分』がおだやかなのか、それとも荒れているのかを見分けて、もうけを出すことを目指します。この作戦がうまくいったのか、過去のデータで試してみた結果をお話ししますね。
導入と前提条件
ここでは、ネット上のお金の一種「BNB/USDT」というセットを、5分ごとの短い時間で売り買いする作戦を紹介します。市場の『気分』がおだやかなのか、それとも荒れているのかを見分けて、もうけを出すことを目指します。この作戦がうまくいったのか、過去のデータで試してみた結果をお話ししますね。
【検証】戦略のバックテスト概要
- 戦略名: Market Meanness Index を使用したトレンド追従戦略
- 対象銘柄: BNB/USDT
- 時間足: 5m
- 期間: 2025-02-16〜2025-08-25(189日間)
- 初期資金: $10,000
- 手数料・スリッページ: 0.1% / 0.1%
- 取引所: okx
Market Meanness Index の理論的背景
物の値段って、上がったり下がったりしますよね。でも、だいたいいつもの値段に戻ろうとすることがあります。これを「元の値段に戻る力」と呼びます。逆に、一度上がり始めるとどんどん上がり続けたり、下がり始めるとどんどん下がり続けたりする勢いのことを「トレンド」と呼びます。この作戦で使うものさしは、今が「元の値段に戻る力」が強い時なのか、「トレンド」が強い時なのかを数字で教えてくれます。数字が大きい時は、「元の値段に戻る力」が強いので、値段が動きすぎてもすぐに戻ってくるだろうと考えます。数字が小さい時は、「トレンド」が強いので、今の勢いのまま動き続けるかもしれないと考えます。この市場の気分に合わせて、いつ売り買いするかを決めるのが、この作戦のポイントです。
具体的な売買ルール(今回の検証)
エントリー条件
- 「元の値段に戻る力」が強い時:値段がすごく下がって、「これは売られすぎだな」と思ったら買います。
- 「トレンド」が強い時:値段が、今までの平均の値段を表す線を下から上に突き抜けたら買います。
エグジット条件
- 「元の値段に戻る力」が強い時:値段がすごく上がって、「これは買われすぎだな」と思ったら売って、取引を終わりにします。
- 「トレンド」が強い時:値段が、今までの平均の値段を表す線を上から下に突き抜けたら売って、取引を終わりにします。
リスク管理
もし予想と反対に値段が動いてしまったら、損が大きくならないように、すぐに売って取引をやめます。これを「損切り」と言います。また、一度の取引に大きなお金を使いすぎないように気をつけることも大切です。
再現手順(HowTo)
- Python/依存(ccxt, pandas, ta)をインストール
- ccxtでBNB/USDTのOHLCVを取得して前処理
- 『Market Meanness Index』に必要な指標を算出(ta 等)
- 閾値・クロス条件から売買シグナルを生成
- 手数料・スリッページを加味して検証・評価
【結果】パフォーマンス
価格の推移
資産の推移
パフォーマンス指標
指標 | 値 |
---|---|
総トレード数 | 83回 |
勝率 | 33.73% |
平均利益 | 2.07% |
平均損失 | -1.56% |
期待値 | -0.33% |
プロフィットファクター | 0.63 |
最大ドローダウン | 30.59% |
最終リターン | -26.15% |
シャープレシオ | -0.06 |
HODL(Buy&Hold) | 31.86% |
HODL戦略との比較
実装コード(Python)
"""
Market Meanness Index Trading Signal Generator
市場の平均回帰性を測定する指標
"""
import pandas as pd
import numpy as np
def calculate_mmi_signals(df: pd.DataFrame,
period: int = 200,
lookback: int = 20) -> pd.DataFrame:
"""
Market Meanness Index戦略のシグナル生成
Parameters:
-----------
df : pd.DataFrame
OHLCVデータ
period : int
MMI計算期間(デフォルト: 200)
lookback : int
中央値計算期間(デフォルト: 20)
Returns:
--------
pd.DataFrame
シグナルが追加されたDataFrame
"""
df = df.copy()
# 中央値計算
df['median'] = df['close'].rolling(window=lookback).median()
# 価格が中央値より上か下か
df['above_median'] = (df['close'] > df['median']).astype(int)
df['below_median'] = (df['close'] < df['median']).astype(int)
# 連続性のカウント
df['consecutive'] = 0
current_streak = 0
prev_above = None
for i in range(len(df)):
if df.iloc[i]['above_median'] == 1:
if prev_above == True:
current_streak += 1
else:
current_streak = 1
prev_above = True
elif df.iloc[i]['below_median'] == 1:
if prev_above == False:
current_streak += 1
else:
current_streak = 1
prev_above = False
df.loc[df.index[i], 'consecutive'] = current_streak
# MMI計算(平均回帰の度合い)
df['moves'] = (df['close'] > df['close'].shift(1)).astype(int)
df['nl'] = df['moves'].rolling(window=period).sum()
df['mmi'] = 100 * (period - df['nl']) / period
df['mmi'] = df['mmi'].fillna(50) # 初期値を50に設定
# MMIのレベル(閾値を緩和)
df['mmi_high'] = df['mmi'] > 60 # 高い平均回帰性
df['mmi_low'] = df['mmi'] < 40 # トレンド性が強い
# 価格のボリンジャーバンド
df['price_ma'] = df['close'].rolling(window=lookback).mean()
df['price_std'] = df['close'].rolling(window=lookback).std()
df['bb_upper'] = df['price_ma'] + 2 * df['price_std']
df['bb_lower'] = df['price_ma'] - 2 * df['price_std']
# シグナル生成
df['is_buy'] = (
(df['mmi_high'] & (df['close'] < df['bb_lower'])) | # 平均回帰環境で売られ過ぎ
(df['mmi_low'] & (df['close'] > df['price_ma']) & (df['close'].shift(1) <= df['price_ma'].shift(1))) # トレンド環境でMAクロス
) & df['mmi'].notna()
df['is_sell'] = (
(df['mmi_high'] & (df['close'] > df['bb_upper'])) | # 平均回帰環境で買われ過ぎ
(df['mmi_low'] & (df['close'] < df['price_ma']) & (df['close'].shift(1) >= df['price_ma'].shift(1))) # トレンド環境でMAクロス
) & df['mmi'].notna()
# 不要カラム削除
df.drop(['median', 'above_median', 'below_median', 'consecutive', 'moves', 'nl',
'mmi_high', 'mmi_low', 'price_ma', 'price_std', 'bb_upper', 'bb_lower'],
axis=1, inplace=True, errors='ignore')
return df
なぜこの結果になったのか(3つの理由)
- 1この作戦では、「元の値段に戻る力」が強い時に「売られすぎ」のタイミングで買っていましたが、勝てる確率が低く、あまりもうかりませんでした。
- 2「トレンド」が強い時に、平均の線を突き抜けたのを合図にしていましたが、これもなかなかもうけにつながりませんでした。
- 3結局、この作戦でBNB/USDTを売り買いしてみたら、トータルでは損をしてしまうという結果になりました。
この結果から学べる3つの教訓
- 1市場の「気分」が「元の値段に戻りやすい」のか「トレンドが出やすい」のかを考えるのは、売り買いでとても大事だということがわかりました。
- 2勝つ回数が少なくても、一回に勝つ金額が大きければ、トータルでプラスになることもある、ということを学びました。
- 3昔のデータでうまくいかなかったように、どんな作戦も必ずもうかるとは限りません。だから、実際にお金を使う時は、とても慎重になるべきだという教訓になりました。
リスク管理の具体的手法
取引量の決め方
1回の売り買いで使うお金は、持っているお金全部の、ほんの少しだけにしましょう。例えば100分の1とかです。そうすれば、もし負けても、ダメージは小さくてすみます。
損失が大きくなったときの対処法
もし損が思ったより大きくなってきたら、それ以上ひどくならないように、すぐに取引をやめましょう。「いくら損したらやめる」と、前もって決めておくのがとても大事です。
資金管理の方法
売り買いに使うお金は、普段の生活に使うお金とは分けて、もしなくなっても大丈夫な「余裕のあるお金」だけにしましょう。そして、一度に使うお金の量をしっかり守ることが大切です。
改良案の具体的提案
- 「トレンド」が強い時の売り買いのルールを、もっと細かく見直す必要がありそうです。
- 「元の値段に戻る力」が強い時に、「売られすぎ」や「買われすぎ」と判断する基準を、もっと厳しくしたり、逆にゆるくしたりして、一番良い設定を探す必要があります。
- この作戦だけでなく、他のものさしも一緒に使って、もっと確実な「売り買いの合図」を見つけられるように工夫すると良いかもしれません。
実用性の向上(運用上の注意)
- この作戦は5分ごとの値動きを見ますが、もし実際に試してみるなら、まずはとても少ない金額から始めるのがおすすめです。
- 取引をするたびに「手数料」という費用がかかります。これも計算に入れないと、思ったよりもうけが少なくなるので注意しましょう。
- 市場の様子はいつも変わります。だから、この作戦がいつもうまくいくとは限りません。定期的に成績をチェックして、必要ならルールを変えていくことが大切です。
検証の透明性と信頼性
- データの出所: このテストの結果は、みんなが見られるように公開されている、過去の値段の動きの記録を使って計算しました。
- 検証のやり方: 昔のBNB/USDTの5分ごとの値動きのデータ(2025年2月16日〜8月25日の期間)を使って、この作戦で売り買いしたら、どれくらいもうかったり損したりしたかを計算しました。
- コード: このテストの計算に使ったコンピューターのプログラムは、誰でも見られるように公開されています。
- 注意事項: この記事は、「こうすればもうかるよ」とおすすめするものではありません。もし実際にお金を使って取引をするなら、必ず自分でよく考えて、自分の責任で行ってください。昔のテストで良い結果が出たとしても、将来も同じようにうまくいくとは限りません。