「零号機」の基本分析 | ランダムウォークへの挑戦④2026/6/11

最近は、新しい仕事が忙しく、また、仕事後に毎日プールで泳いでいるのでなかなか作業が進みません。
また、新年度になってから飲み会も増えました。職場で気の合う独身兄貴たちと4人で定期飲みしています♨

ということで、今日は少し進めます。

前回は環境設定をしました。

今回は、読みこんだcsvから基本成績を出すところまで進めたいと思います。

分析用コードの修正

まず、前回作成したPythonファイル「analyze.py」を次のように修正します。

import pandas as pd

# CSV読み込み 文字コード設定
df = pd.read_csv("/mnt/c/Users/****/MT4/report.csv", encoding="utf-8-sig")

# 決済済み取引(close)だけ抽出
trades = df[df["取引種別"] == "close"].copy()

# 日時を変換
trades["時間"] = pd.to_datetime(trades["時間"], format="%Y.%m.%d %H:%M")

# 基本集計
total_trades = len(trades)
wins = trades[trades["損益"] > 0]
losses = trades[trades["損益"] < 0]

#勝ち数・負け数
win_count = len(wins)
loss_count = len(losses)

#勝率
win_rate = win_count / total_trades * 100

#利益合計・損失合計
gross_profit = wins["損益"].sum()
gross_loss = losses["損益"].sum()

#プロフィットファクタ(absは絶対値)
profit_factor = gross_profit / abs(gross_loss)

#損益・平均利益・平均損失
total_profit = trades["損益"].sum()
average_profit = wins["損益"].mean()
average_loss = losses["損益"].mean()

# 最大ドローダウン
trades["過去最高残高"] = trades["残高"].cummax()
trades["ドローダウン"] = trades["残高"] - trades["過去最高残高"]
max_drawdown = trades["ドローダウン"].min()

# 表示
print("===== EA分析結果 =====")
print(f"総取引数: {total_trades}")
print(f"勝ち取引: {win_count}")
print(f"負け取引: {loss_count}")
print(f"勝率: {win_rate:.2f}%")
print(f"総損益: {total_profit:.2f}")
print(f"総利益: {gross_profit:.2f}")
print(f"総損失: {gross_loss:.2f}")
print(f"PF: {profit_factor:.2f}")
print(f"平均利益: {average_profit:.2f}")
print(f"平均損失: {average_loss:.2f}")
print(f"最大ドローダウン: {max_drawdown:.2f}")
print(f"最終残高: {trades['残高'].iloc[-1]:.2f}")

実行すると結果が出力されました。

月別の成績も追加したいので次のコードを最下行に追加します。

# 年月列を作成
trades["年月"] = trades["時間"].dt.strftime("%Y-%m")

# 月別損益
monthly_profit = (
    trades
    .groupby("年月")["損益"]
    .sum()
    .reset_index()
)

print("\n===== 月別損益 =====")
print(monthly_profit)

追加した後の全体のソースは以下の通りです。

import pandas as pd

# CSV読み込み 文字コード設定
df = pd.read_csv("/mnt/c/MT4/report.csv", encoding="utf-8-sig")

# 決済済み取引(close)だけ抽出
trades = df[df["取引種別"] == "close"].copy()

# 日時を変換
trades["時間"] = pd.to_datetime(trades["時間"], format="%Y.%m.%d %H:%M")

# 年月列を作成
trades["年月"] = trades["時間"].dt.strftime("%Y-%m")

# 基本集計
total_trades = len(trades)
wins = trades[trades["損益"] > 0]
losses = trades[trades["損益"] < 0]

#勝ち数・負け数
win_count = len(wins)
loss_count = len(losses)

#勝率
win_rate = win_count / total_trades * 100

#利益合計・損失合計
gross_profit = wins["損益"].sum()
gross_loss = losses["損益"].sum()

#プロフィットファクタ(absは絶対値)
profit_factor = gross_profit / abs(gross_loss)

#損益・平均利益・平均損失
total_profit = trades["損益"].sum()
average_profit = wins["損益"].mean()
average_loss = losses["損益"].mean()

# 最大ドローダウン
trades["過去最高残高"] = trades["残高"].cummax()
trades["ドローダウン"] = trades["残高"] - trades["過去最高残高"]
max_drawdown = trades["ドローダウン"].min()

# 表示
print("===== EA分析結果 =====")
print(f"総取引数: {total_trades}")
print(f"勝ち取引: {win_count}")
print(f"負け取引: {loss_count}")
print(f"勝率: {win_rate:.2f}%")
print(f"総損益: {total_profit:.2f}")
print(f"総利益: {gross_profit:.2f}")
print(f"総損失: {gross_loss:.2f}")
print(f"PF: {profit_factor:.2f}")
print(f"平均利益: {average_profit:.2f}")
print(f"平均損失: {average_loss:.2f}")
print(f"最大ドローダウン: {max_drawdown:.2f}")
print(f"最終残高: {trades['残高'].iloc[-1]:.2f}")

# 月別損益
monthly_profit = (
    trades
    .groupby("年月")["損益"]
    .sum()
    .reset_index()
)

print("\n===== 月別損益 =====")
print(monthly_profit)

実行し、結果が出ました。

結果分析

まず、「零号機」(私の試作)のバックテスト期間は2015年1月1日から2026年5月までで、総取引回数は1,645回でした。

勝率は62.25%でした。
勝率だけでは、「零号機」の評価をすることはできません。

PF(Profit Factor:プロフィットファクター)を見てみます。
PFとは、「利益総額」が「損失総額」の何倍あるかを表す指標です。

PF は「1.35」でした。

一般的には、

  • 1.0以下:負けるEA
  • 1.2:ギリギリ
  • 1.3~1.5:改善余地あり
  • 1.5以上:優秀
  • 2.0以上:かなり優秀

らしいので、これからパワーアップさせていきたいです。

平均利益は829円、平均損失は-1,010円でした。つまり、負け1回が勝ち1回より大きい設計です。そのため、勝率が少し落ちると、一気に利益が減る可能性があります。

月別の損益は次の通りです。

2015-01 : +14940
2015-02 :   -404
2015-03 :  -1192
2015-04 :  -2635
2015-05 :  +6610
・・・
2025-03 :  -534
2025-04 :  +6119
2025-10 : +18517
2025-11 :  +1196
2025-12 :  +2033

極端に大きなマイナス月が続いているわけではなく、利益月と損失月を繰り返しながら右肩上がりといった感じです。

ひとまず出力したcsvから簡単な分析を行うところまでできました。
次回はグラフ化してみたいと思います。

今日はここまで。

最近この本を読みました。

ユクスキュルの「生物から見た世界」を優しくかみ砕いた本です。
生物たちによって、必要な情報しか見る必要がなく、ゆえに「必要な情報だけが表示された世界」を見ている。

つまり、世界をそのまま感知できていない。

例えば、ダニなんかは、二酸化炭素と体温だけが見えているようです。

そう思うと、「世界をちゃんと認知できていなくて可哀そう」なんて思いがちですが、
人間も同じ生物ですから、世界をそのまま認知できていないことになります。

例えば赤外線や紫外線を見ることはできません。

我々もひょっとすると恐ろしく狭い認知世界の中で生きているのかもしれません。

面白い一冊でした。

(ちなみにこの本の後に「生物から見た世界」を詠みましたが、書いてあることが難しく途中で挫折しました)

次の記事

関連記事

コメント

タイトルとURLをコピーしました