見出し画像

仮想通貨トレード テクニカル分析を利用したBOTで勝てるのか

ニューヨーク時間で価格上昇が多いのかを検証

%load_ext autoreload
%autoreload 2
!pip install japanize-matplotlib
import japanize_matplotlib
import requests
import pandas as pd
import matplotlib.pyplot as plt
from pytz import timezone

# ニューヨーク時間を設定
ny_tz = timezone('America/New_York')

# APIリクエストの設定
url = 'https://api.coingecko.com/api/v3/coins/bitcoin/market_chart'
params = {
    'vs_currency': 'usd',
    'days': '365',  # 過去1年
    'interval': 'daily'
}

# データの取得
response = requests.get(url, params=params)
data = response.json()

# データの変換
prices = data['prices']
volumes = data['total_volumes']

# DataFrameに変換
df_prices = pd.DataFrame(prices, columns=['timestamp', 'price'])
df_volumes = pd.DataFrame(volumes, columns=['timestamp', 'volume'])

# タイムスタンプを日時に変換
df_prices['date'] = pd.to_datetime(df_prices['timestamp'], unit='ms').dt.tz_localize('UTC').dt.tz_convert(ny_tz)
df_volumes['date'] = pd.to_datetime(df_volumes['timestamp'], unit='ms').dt.tz_localize('UTC').dt.tz_convert(ny_tz)

# 不要な列を削除
df_prices = df_prices.drop(columns=['timestamp'])
df_volumes = df_volumes.drop(columns=['timestamp'])

# データの統合
df = pd.merge(df_prices, df_volumes, on='date')

# 日次リターンの計算
df['return'] = df['price'].pct_change() * 100  # パーセンテージリターン

# グラフの描画
plt.figure(figsize=(14, 7))

# 価格のプロット
plt.subplot(3, 1, 1)
plt.plot(df['date'], df['price'], label='BTC Price (USD)', color='blue')
plt.title('Bitcoin Price (USD)')
plt.xlabel('Date')
plt.ylabel('Price (USD)')
plt.legend()
plt.grid(True)

# 出来高のプロット
plt.subplot(3, 1, 2)
plt.bar(df['date'], df['volume'], label='BTC Volume', color='orange')
plt.title('Bitcoin Trading Volume')
plt.xlabel('Date')
plt.ylabel('Volume')
plt.legend()
plt.grid(True)

# 日次リターンのプロット
plt.subplot(3, 1, 3)
plt.plot(df['date'], df['return'], label='Daily Return (%)', color='green')
plt.title('Bitcoin Daily Return (%)')
plt.xlabel('Date')
plt.ylabel('Return (%)')
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.show()

結果 アメリカ時間で価格が上昇した確率 53%

テクニカル分析で有名なMACDで勝てるのか検証

「ビットコインの価格」と「MACD」という指標を使って、過去1年分のデータを分析し、価格の動きをグラフに描くものです。
MACDを利用 エントリーから1日後のリターンを計測

import requests
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from pytz import timezone

# ニューヨーク時間を設定
ny_tz = timezone('America/New_York')

# APIリクエストの設定
url = 'https://api.coingecko.com/api/v3/coins/bitcoin/market_chart'
params = {
    'vs_currency': 'usd',
    'days': '365',  # 過去1年
    'interval': 'daily'
}

# データの取得
response = requests.get(url, params=params)
data = response.json()

# データの変換
prices = data['prices']

# DataFrameに変換
df = pd.DataFrame(prices, columns=['timestamp', 'price'])
df['date'] = pd.to_datetime(df['timestamp'], unit='ms').dt.tz_localize('UTC').dt.tz_convert(ny_tz)
df.set_index('date', inplace=True)
df = df.drop(columns=['timestamp'])

# MACD指標の計算
def calculate_macd(df, short_window=12, long_window=26, signal_window=9):
    df['ema_short'] = df['price'].ewm(span=short_window, adjust=False).mean()
    df['ema_long'] = df['price'].ewm(span=long_window, adjust=False).mean()
    df['macd'] = df['ema_short'] - df['ema_long']
    df['macd_signal'] = df['macd'].ewm(span=signal_window, adjust=False).mean()
    return df

df = calculate_macd(df)

# MACDエントリーシグナルの生成
df['signal'] = np.where(df['macd'] > df['macd_signal'], 1, 0)  # MACDがシグナルラインを上回ると1、下回ると0

# 勝敗計算のためのラベルを生成
df['return'] = df['price'].pct_change().shift(-1) * 100  # 翌日のリターン
df['win'] = np.where(df['signal'].shift(1) == 1, np.where(df['return'] > 0, 1, 0), np.nan)  # エントリーシグナルと翌日のリターンを比較
df['win'] = df['win'].fillna(0)  # NaNを0に置き換え

# 勝率の計算
total_entries = df['signal'].shift(1).sum()
total_wins = df['win'].sum()
winning_rate = (total_wins / total_entries) * 100 if total_entries > 0 else 0

# グラフの描画
plt.figure(figsize=(14, 7))

# 価格の折れ線グラフ
plt.plot(df.index, df['price'], label='BTC Price', color='blue', alpha=0.5)

# エントリーポイントのプロット
buy_signals = df[df['signal'].shift(1) == 1]  # MACDがシグナルラインを上回ったポイント
plt.scatter(buy_signals.index, buy_signals['price'], marker='^', color='black', label='Entry Points')

# 勝敗の色分け
colors = np.where(df['win'] == 1, 'green', 'red')
plt.scatter(df.index, df['price'], color=colors, alpha=0.6, label='Win/Loss')

plt.title(f'Bitcoin Price and MACD Entry Points with Win/Loss (Winning Rate: {winning_rate:.2f}%)')
plt.xlabel('Date')
plt.ylabel('Price (USD)')
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.show()

結果 勝率 50.64%
MACDを利用したトレードでは勝率は半々なので、ほかの指標との組み合わせを行う必要があります


複数のテクニカルを組合せると勝率が上がるのか検証しましょう

戦略

1. RSI(Relative Strength Index)を使った戦略 RSIで売られ過ぎが出たら買う 2. MACD(Moving Average Convergence/Divergence)を使った戦略 MACDがマイナス圏でゴールデンクロスが発生したら買い いずれの戦略も エントリーから2%の下落で損切り、 1%の上昇で半分利確とエントリー価格に撤退指値、 2%上昇したら全利確

  • 勝率の計算:

    • calculate_win_rate(df)関数で、利益がプラスのトレード数をカウントし、総トレード数で割って勝率を算出します。

    • 勝ちトレードの数、総トレード数、そして勝率が表示されます。

  • バックテスト結果:

    • 終了時に、勝率、勝ちトレード数、総取引数がコンソールに表示されます。

    • 例: 勝率: 60.00% (勝ち: 6, 総取引数: 10) のように出力されます。

  • グラフ描画:

    • 価格推移と累積利益率のグラフを描画します。

import pandas as pd
import yfinance as yf
import ta
import matplotlib.pyplot as plt

# テクニカル指標の設定
def apply_technical_indicators(df):
    # RSIを計算 (14日間)
    df['RSI'] = ta.momentum.RSIIndicator(df['Close'], window=14).rsi()

    # MACDを計算 (デフォルトの設定)
    macd = ta.trend.MACD(df['Close'])
    df['MACD'] = macd.macd()
    df['MACD_signal'] = macd.macd_signal()
    
    return df

# シンプルなトレード戦略
def trading_strategy(df):
    df['position'] = 0  # トレードのポジション:1は買い、-1は売り、0はなし
    df['buy_price'] = None
    df['profit_pct'] = 0  # 利益率
    entry_price = 0     # エントリーポジションの価格

    for i in range(1, len(df)):
        # RSI 戦略: RSIが30以下の場合に買い(売られ過ぎ)
        if df['RSI'][i] < 30 and df['position'][i-1] == 0:
            df['position'][i] = 1  # 買いエントリー
            df['buy_price'] = df['Close'][i]
            entry_price = df['Close'][i]
        
        # MACD 戦略: MACDがマイナス圏でゴールデンクロスの場合に買い
        elif df['MACD'][i-1] < 0 and df['MACD'][i] > df['MACD_signal'][i] and df['position'][i-1] == 0:
            df['position'][i] = 1  # 買いエントリー
            df['buy_price'] = df['Close'][i]
            entry_price = df['Close'][i]

        # 利確・損切り条件
        elif df['position'][i-1] == 1:
            # 損切り: 2% 下落
            if df['Close'][i] < entry_price * 0.98:
                df['profit_pct'][i] = (df['Close'][i] - entry_price) / entry_price  # 損切りの利益率
                df['position'][i] = 0  # ポジションを閉じる
                entry_price = 0
            # 利確: 1% 上昇で全利確
            elif df['Close'][i] > entry_price * 1.01:
                df['profit_pct'][i] = (df['Close'][i] - entry_price) / entry_price  # 利確の利益率
                df['position'][i] = 0  # 全利確
                entry_price = 0
        else:
            df['position'][i] = df['position'][i-1]  # 前回のポジションを保持
            df['profit_pct'][i] = 0  # 利益は発生していない
    
    return df

# 勝率計算
def calculate_win_rate(df):
    # 勝ちトレード(利益がプラス)と全トレードをカウント
    winning_trades = df[df['profit_pct'] > 0]['profit_pct'].count()
    total_trades = df[df['profit_pct'] != 0]['profit_pct'].count()
    
    # 勝率を計算
    win_rate = (winning_trades / total_trades) * 100 if total_trades > 0 else 0
    return win_rate, winning_trades, total_trades

# データ取得とバックテスト
def backtest_strategy(ticker):
    # 過去データを取得(過去1年分)
    df = yf.download(ticker, period="1y")
    
    # テクニカル指標を追加
    df = apply_technical_indicators(df)

    # トレード戦略を適用
    df = trading_strategy(df)
    
    # ポジションの履歴と利益率
    print(df[['Close', 'RSI', 'MACD', 'MACD_signal', 'position', 'profit_pct']].tail(20))
    
    return df

# 利益率とパフォーマンスをプロット
def plot_performance(df):
    # 累積利益率の計算
    df['cumulative_return'] = (1 + df['profit_pct']).cumprod() - 1
    
    plt.figure(figsize=(14, 7))
    
    # 価格チャート
    plt.subplot(2, 1, 1)
    plt.plot(df.index, df['Close'], label='Close Price', color='blue', alpha=0.5)
    plt.title('Price and Performance Over Last 1 Year')
    plt.xlabel('Date')
    plt.ylabel('Close Price')
    plt.grid(True)
    
    # 利益率チャート
    plt.subplot(2, 1, 2)
    plt.plot(df.index, df['cumulative_return'], label='Cumulative Return', color='green', alpha=0.7)
    plt.title('Cumulative Return Over Last 1 Year')
    plt.xlabel('Date')
    plt.ylabel('Cumulative Return (%)')
    plt.grid(True)
    
    plt.tight_layout()
    plt.show()

# 実行
df = backtest_strategy('AAPL')

# 勝率計算
win_rate, winning_trades, total_trades = calculate_win_rate(df)
print(f"勝率: {win_rate:.2f}% (勝ち: {winning_trades}, 総取引数: {total_trades})")

# パフォーマンスと利益率をプロット
plot_performance(df)

バックテスト結果 勝率: 70.00% (勝ち: 7, 総取引数: 10)


まとめ

テクニカル分析の有名な指標でも単体で利用しても勝率は50%前後
複数の指標を組合せてトレードすると勝率は上昇することがわかりました
BOTでトレードする場合は、結果の検証を行いながら利用してみましょう

いいなと思ったら応援しよう!