😸

# PythonでFXのユロドルアノマリーを検証

2023/10/21に公開

## 値動きの特徴

``````import pandas as pd
from datetime import timedelta
import seaborn as sns
import matplotlib.pyplot as plt

# MT5への接続
mt5.initialize()

def fetch_and_prepare(symbol, timeframe, count, timezone_hours, ratio_calculation):
# データの取得
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, count)

# DataFrameに変換
df = pd.DataFrame(rates)

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

df[ratio_calculation.name] = ratio_calculation(df)

return df

def high_low_ratio(df):
return (df['high'] - df['low']) / df['low']

def close_open_ratio(df):
return (df['close'] - df['open']) / df['open']

def plot_avg_return(df, column_name):
# インデックスを日付に変換
df.set_index('time', inplace=True)

# 5分ごとの平均リターンを計算
df['5min_avg_return'] = df[column_name].rolling(window=5).mean()

# 時刻をグループ化して平均を計算
grouped_df = df.groupby(df.index.time).mean()

# 時刻を文字列に変換
grouped_df.index = grouped_df.index.astype(str)

# グラフの作成
plt.figure(figsize=(50, 10))
sns.barplot(x=grouped_df.index, y=grouped_df['5min_avg_return'])
plt.xlabel('Time')
plt.ylabel('5min Average Return')
plt.title('5-minute Average Return (Grouped by Time)')

# X軸のラベルを斜めに表示
plt.xticks(rotation=90)

plt.show()

def fetch_and_prepare(symbol, timeframe, count, timezone_hours, ratio_calculation, column_name):
# データの取得
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, count)

# DataFrameに変換
df = pd.DataFrame(rates)

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

df[column_name] = ratio_calculation(df)

return df

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

df = fetch_and_prepare(symbol, timeframe, count, timezone_hours, high_low_ratio, 'high_low_ratio')
plot_avg_return(df, 'high_low_ratio')

df = fetch_and_prepare(symbol, timeframe, count, timezone_hours, close_open_ratio, 'close_open_ratio')
plot_avg_return(df, 'close_open_ratio')
``````

## ストラテジーテスターの解析

``````import pandas as pd
import matplotlib.pyplot as plt

def extract_deals_from_html(file_path):
index = df.index[df.iloc[:, 0] == '約定'].tolist()[0]
deals = df.iloc[index+1:-2].reset_index(drop=True)
deals.columns = deals.iloc[0]
return deals.iloc[2:].reset_index(drop=True)

def preprocess_deals(deals):
deals['時間'] = pd.to_datetime(deals['時間'])
columns_to_convert = {
'約定': int,
'注文': int,
'数量': float,
'価格': float,
'損益': lambda x: float(x.replace(' ', '')),
'残高': lambda x: float(x.replace(' ', ''))
}
for col, dtype in columns_to_convert.items():
deals[col] = deals[col].apply(dtype)
return deals

def rename_columns(deals):
column_mapping = {
'時間': 'Time',
'約定': 'Transaction',
'銘柄': 'Stock',
'タイプ': 'Type',
'新規・決済': 'EntryOrExit',
'数量': 'Quantity',
'価格': 'Price',
'注文': 'Order',
'手数料': 'Fee',
'スワップ': 'Swap',
'損益': 'ProfitOrLoss',
'残高': 'Balance',
'コメント': 'Comment'
}
return deals.rename(columns=column_mapping)

def plot_daily_profit_or_loss(deals, start_date=None, end_date=None):
if start_date:
deals = deals[deals['Time'] >= start_date]
if end_date:
deals = deals[deals['Time'] <= end_date]

deals['day'] = deals['Time'].dt.day
daily_profit_loss = deals.groupby('day')['ProfitOrLoss'].sum()
plt.figure(figsize=(10,6))
daily_profit_loss.plot(kind='bar')
plt.title('Daily Profit or Loss')
plt.xlabel('Day')
plt.ylabel('Profit or Loss')
plt.grid(axis='y')
plt.tight_layout()
plt.show()

# Main execution
file_path = "ReportTester-76433893.html"
deals = extract_deals_from_html(file_path)
deals = preprocess_deals(deals)
deals = rename_columns(deals)

# グラフの表示
plot_daily_profit_or_loss(deals) # 期間指定なしの場合
plot_daily_profit_or_loss(deals, start_date="2023-07-01", end_date="2023-10-21")  # 期間を指定する場合
``````