😊

バイナリーオプションRSI15分足の1時間区切りの勝率を見る

2023/05/28に公開

当方素人のため、間違ってるかも知れません。

それでもいいならどうぞ!

プロンプト1

一時間区切りの勝率を出したいのです。ヒートマップで可視化して。可視化にsns使ってね。

プロンプト2

BUYとSELLは分けてください。
あとセルが小さいので文字が重なって見えないです。
ヒートマップのサイズを大きくしてください。

このあと何回か回答がパッとせず、
元のコードを修正する方向にします。

プロンプト3

このコードのmerged_dfにhourのカラムを追加して

プロンプト4

ヒートマップのタイトルに英語でprint(5 * i, "分後")の部分を追加して何分後のデータなのかわかるようにしてください。

プロンプト5

pltの部分を修正してください
1.buy_win_rateとsell_win_rate が混ざっている
2.そのため別々でテーブルを管理してください。
3.BUYはbuy_win_rateのみ
4. SELLはsell_win_rate のみ

プロンプト6

コード全文でください

プロンプト7

BUYとSELLを同じ表として可視化して

プロンプト8

色の濃淡を0.2~0.8に固定して

できた!

import pandas as pd
import MetaTrader5 as mt5
import talib
from datetime import timedelta
import seaborn as sns
import matplotlib.pyplot as plt

for i in range(1, 4):
    # MT5への接続
    mt5.initialize()

    # 読み込む通貨ペアと時間枠、データの件数を指定
    symbol = 'USDJPYm'
    timeframe = mt5.TIMEFRAME_M5
    count = 200000

    # データの取得
    rates_5 = mt5.copy_rates_from_pos(symbol, timeframe, 0, count)

    # DataFrameに変換
    df_5 = pd.DataFrame(rates_5)

    # 日時をPandasの日時形式に変換し、GMT+9に変換
    df_5['time'] = pd.to_datetime(df_5['time'], unit='s') + timedelta(hours=9)

    # RSIの計算と列の追加
    rsi_period = 14
    df_5['rsi'] = talib.RSI(df_5['close'], timeperiod=rsi_period)

    # close列の一つ先の値を新しいカラムに追加
    df_5['next_close'] = df_5['close'].shift(-1 * i + 1)

    # open列の一つ先の値を新しいカラムに追加
    df_5['next_open'] = df_5['open'].shift(-1 + 1)

    # 条件に応じて新しいカラムを追加
    df_5.loc[df_5['next_close'] - df_5['next_open'] > 0, 'change'] = 'up'
    df_5.loc[df_5['next_close'] - df_5['next_open'] < 0, 'change'] = 'down'
    df_5.loc[df_5['next_close'] - df_5['next_open'] == 0, 'change'] = 'zero'

    # 15分足のデータを取得
    timeframe_15 = mt5.TIMEFRAME_M15
    count_15 = count  # count * 5分足のデータ数 / 15分足のデータ数
    rates_15 = mt5.copy_rates_from_pos(symbol, timeframe_15, 0, count_15)

    # DataFrameに変換
    df_15 = pd.DataFrame(rates_15)

    # 日時をPandasの日時形式に変換し、GMT+9に変換
    df_15['time'] = pd.to_datetime(df_15['time'], unit='s') + timedelta(hours=9)

    # RSIの計算と列の追加
    rsi_15_period = 14
    df_15['rsi_15'] = talib.RSI(df_15['close'], timeperiod=rsi_15_period)

    # M5とM15のデータをマージ
    merged_df = pd.merge(df_5, df_15[['time', 'rsi_15']], on='time', how='left')

    # 前のRSI_15と現在のRSI_15を比較して条件判定
    merged_df['action'] = None  # 初期値として空の列を追加

    prev_rsi_15 = merged_df['rsi_15'].shift(6)  # 1つ前のRSI_15
    current_rsi_15 = merged_df['rsi_15'].shift(3)  # 現在のRSI_15

    merged_df.loc[(prev_rsi_15 < 70) & (current_rsi_15 >= 70), 'action'] = 'SELL'
    merged_df.loc[(prev_rsi_15 > 30) & (current_rsi_15 <= 30), 'action'] = 'BUY'

    # hourカラムを追加
    merged_df['hour'] = merged_df['time'].dt.hour

    # 条件に合致する行の抽出
    filtered_df = merged_df[(merged_df['action'] == 'BUY') | (merged_df['action'] == 'SELL')]

    # 条件に合致する行の確率を計算
    buy_filtered = filtered_df[filtered_df['action'] == 'BUY']
    sell_filtered = filtered_df[filtered_df['action'] == 'SELL']

    buy_up_probability = len(buy_filtered[buy_filtered['change'] == 'up']) / len(buy_filtered) if len(
        buy_filtered) > 0 else 0
    sell_down_probability = len(sell_filtered[sell_filtered['change'] == 'down']) / len(sell_filtered) if len(
        sell_filtered) > 0 else 0

    print(5 * i, "分後")
    print("全数", len(merged_df))
    print("BUY判定数", len(buy_filtered))
    print("BUY正解数", len(buy_filtered[buy_filtered['change'] == 'up']))
    print("BUY & up probability: {:.2f}%".format(buy_up_probability * 100))
    print("全数:", len(merged_df))
    print("SELL判定数:", len(sell_filtered))
    print("SELL正解数:", len(sell_filtered[sell_filtered['change'] == 'down']))
    print("SELL & down probability: {:.2f}%".format(sell_down_probability * 100))

    # 1時間ごとのデータを抽出
    hourly_data = merged_df.groupby(['hour', 'action']).size().reset_index(name='count')
    
    # 勝率の計算
    win_counts_buy = merged_df[(merged_df['change'] == 'up') & (merged_df['action'] == 'BUY')].groupby('hour').size().reset_index(
            name='buy_win_count')
    win_counts_sell = merged_df[(merged_df['change'] == 'down') & (merged_df['action'] == 'SELL')].groupby('hour').size().reset_index(
            name='sell_win_count')

    hourly_data_buy = hourly_data[hourly_data['action'] == 'BUY'].copy()
    hourly_data_sell = hourly_data[hourly_data['action'] == 'SELL'].copy()

    hourly_data_buy = pd.merge(hourly_data_buy, win_counts_buy, on='hour', how='left')
    hourly_data_sell = pd.merge(hourly_data_sell, win_counts_sell, on='hour', how='left')

    hourly_data_buy['buy_win_rate'] = hourly_data_buy['buy_win_count'] / hourly_data_buy['count']
    hourly_data_sell['sell_win_rate'] = hourly_data_sell['sell_win_count'] / hourly_data_sell['count']

    # ヒートマップの作成
    heatmap_data = pd.merge(hourly_data_buy[['hour', 'buy_win_rate']],
                            hourly_data_sell[['hour', 'sell_win_rate']],
                            on='hour', how='outer')

    heatmap_data.set_index('hour', inplace=True)

    plt.figure(figsize=(12, 8))
    sns.heatmap(heatmap_data, annot=True, fmt=".2%", cmap='YlGnBu', cbar_kws={'label': 'Win Rate'}, vmin=0.2, vmax=0.8)
    title = str(5 * i) + " minutes later"
    plt.title('Win Rate by Hour ' + title)
    plt.xlabel('Action')
    plt.ylabel('Hour')
    plt.show()

import pandas as pd
import MetaTrader5 as mt5
import talib
from datetime import timedelta
import seaborn as sns
import matplotlib.pyplot as plt

for i in range(1, 4):
    # MT5への接続
    mt5.initialize()

    # 読み込む通貨ペアと時間枠、データの件数を指定
    symbol = 'USDJPYm'
    timeframe = mt5.TIMEFRAME_M5
    count = 200000

    # データの取得
    rates_5 = mt5.copy_rates_from_pos(symbol, timeframe, 0, count)

    # DataFrameに変換
    df_5 = pd.DataFrame(rates_5)

    # 日時をPandasの日時形式に変換し、GMT+9に変換
    df_5['time'] = pd.to_datetime(df_5['time'], unit='s') + timedelta(hours=9)

    # RSIの計算と列の追加
    rsi_period = 14
    df_5['rsi'] = talib.RSI(df_5['close'], timeperiod=rsi_period)

    # close列の一つ先の値を新しいカラムに追加
    df_5['next_close'] = df_5['close'].shift(-1 * i + 1)

    # open列の一つ先の値を新しいカラムに追加
    df_5['next_open'] = df_5['open'].shift(-1 + 1)

    # 条件に応じて新しいカラムを追加
    df_5.loc[df_5['next_close'] - df_5['next_open'] > 0, 'change'] = 'up'
    df_5.loc[df_5['next_close'] - df_5['next_open'] < 0, 'change'] = 'down'
    df_5.loc[df_5['next_close'] - df_5['next_open'] == 0, 'change'] = 'zero'

    # 15分足のデータを取得
    timeframe_15 = mt5.TIMEFRAME_M15
    count_15 = count  # count * 5分足のデータ数 / 15分足のデータ数
    rates_15 = mt5.copy_rates_from_pos(symbol, timeframe_15, 0, count_15)

    # DataFrameに変換
    df_15 = pd.DataFrame(rates_15)

    # 日時をPandasの日時形式に変換し、GMT+9に変換
    df_15['time'] = pd.to_datetime(df_15['time'], unit='s') + timedelta(hours=9)

    # RSIの計算と列の追加
    rsi_15_period = 14
    df_15['rsi_15'] = talib.RSI(df_15['close'], timeperiod=rsi_15_period)

    # M5とM15のデータをマージ
    merged_df = pd.merge(df_5, df_15[['time', 'rsi_15']], on='time', how='left')

    # 前のRSI_15と現在のRSI_15を比較して条件判定
    merged_df['action'] = None  # 初期値として空の列を追加

    prev_rsi_15 = merged_df['rsi_15'].shift(6)  # 1つ前のRSI_15
    current_rsi_15 = merged_df['rsi_15'].shift(3)  # 現在のRSI_15

    merged_df.loc[(prev_rsi_15 < 70) & (current_rsi_15 >= 70), 'action'] = 'SELL'
    merged_df.loc[(prev_rsi_15 > 30) & (current_rsi_15 <= 30), 'action'] = 'BUY'

    # hourカラムを追加
    merged_df['hour'] = merged_df['time'].dt.hour

    # 条件に合致する行の抽出
    filtered_df = merged_df[(merged_df['action'] == 'BUY') | (merged_df['action'] == 'SELL')]

    # 条件に合致する行の確率を計算
    buy_filtered = filtered_df[filtered_df['action'] == 'BUY']
    sell_filtered = filtered_df[filtered_df['action'] == 'SELL']

    buy_up_probability = len(buy_filtered[buy_filtered['change'] == 'up']) / len(buy_filtered) if len(
        buy_filtered) > 0 else 0
    sell_down_probability = len(sell_filtered[sell_filtered['change'] == 'down']) / len(sell_filtered) if len(
        sell_filtered) > 0 else 0

    print(5 * i, "分後")
    print("全数", len(merged_df))
    print("BUY判定数", len(buy_filtered))
    print("BUY正解数", len(buy_filtered[buy_filtered['change'] == 'up']))
    print("BUY & up probability: {:.2f}%".format(buy_up_probability * 100))
    print("全数:", len(merged_df))
    print("SELL判定数:", len(sell_filtered))
    print("SELL正解数:", len(sell_filtered[sell_filtered['change'] == 'down']))
    print("SELL & down probability: {:.2f}%".format(sell_down_probability * 100))

    # 'time'カラムを分に変換
    merged_df['minutes'] = merged_df['time'].dt.hour * 60 + merged_df['time'].dt.minute

    # 15分毎にラベルを生成
    bins = range(0, 24*60, 15)
    labels = [f'{i//60:02d}:{(i%60):02d}' for i in bins][:-1]  # '00:00', '00:15', '00:30', ..., '23:45' の形式
    merged_df['15min'] = pd.cut(merged_df['minutes'], bins=bins, labels=labels)

    # 15分ごとのデータを抽出
    grouped_15min_data = merged_df.groupby(['15min', 'action']).size().reset_index(name='count')

    # 勝率の計算
    win_counts_buy = merged_df[(merged_df['change'] == 'up') & (merged_df['action'] == 'BUY')].groupby('15min').size().reset_index(
                name='buy_win_count')
    win_counts_sell = merged_df[(merged_df['change'] == 'down') & (merged_df['action'] == 'SELL')].groupby('15min').size().reset_index(
                name='sell_win_count')

    grouped_15min_data_buy = grouped_15min_data[grouped_15min_data['action'] == 'BUY'].copy()
    grouped_15min_data_sell = grouped_15min_data[grouped_15min_data['action'] == 'SELL'].copy()

    grouped_15min_data_buy = pd.merge(grouped_15min_data_buy, win_counts_buy, on='15min', how='left')
    grouped_15min_data_sell = pd.merge(grouped_15min_data_sell, win_counts_sell, on='15min', how='left')

    grouped_15min_data_buy['buy_win_rate'] = grouped_15min_data_buy['buy_win_count'] / grouped_15min_data_buy['count']
    grouped_15min_data_sell['sell_win_rate'] = grouped_15min_data_sell['sell_win_count'] / grouped_15min_data_sell['count']

    # ヒートマップの作成
    heatmap_data = pd.merge(grouped_15min_data_buy[['15min', 'buy_win_rate']],
                            grouped_15min_data_sell[['15min', 'sell_win_rate']],
                            on='15min', how='outer')

    heatmap_data.set_index('15min', inplace=True)

    fig, ax = plt.subplots(figsize=(12, 20))  # 高さを20に設定

    sns.heatmap(heatmap_data, annot=True, fmt=".2%", cmap='YlGnBu', cbar_kws={'label': 'Win Rate'}, vmin=0.2, vmax=0.8,
                annot_kws={"size": 10}, ax=ax)  # フォントサイズを調整

    title = str(5 * i) + " minutes later"
    ax.set_title('Win Rate by 15 Minutes ' + title, fontsize=20)
    ax.set_xlabel('Action', fontsize=15)
    ax.set_ylabel('Time (HH:MM)', fontsize=15)
    plt.xticks(fontsize=12)
    plt.yticks(fontsize=12)

    plt.show()




Discussion