用30行Python自动挖出你的交易漏洞:胜率、时段弱点、连亏警报全搞定

👉 工具网址:https://propfirmkey.com

你是不是也记交易日记?
但翻来翻去,只看到“今天又亏了”、“这单不该做”……
真正的问题藏在数据里:
– 哪个小时段你总在送钱?
– 哪个品种表面热闹,实则拖垮账户?
– 连亏5单后,第6单你还敢开吗?

别再靠感觉复盘了。我们用一段真实可用的Python脚本,把你的CSV交易记录(比如从Tradovate、NinjaTrader导出的)变成一张「交易健康报告」——不用部署、不装服务器,复制粘贴就能跑,5秒出结果。

下面就是完整可运行的代码,已加满中文注释,新手照着抄也不会错👇

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

def generate_sample_trades(n=200):
    np.random.seed(42)
    symbols = ["ES", "NQ", "MES", "CL", "GC"]
    sides = ["LONG", "SHORT"]

    trades = []
    for i in range(n):
        # 模拟入场时间:2025年1月1日起90天内,工作日早9点到下午4点之间
        entry_time = datetime(2025, 1, 1) + timedelta(
            days=np.random.randint(0, 90),
            hours=np.random.randint(9, 16),
            minutes=np.random.randint(0, 60)
        )
        # 按概率选合约:ES最常交易(35%),NQ次之(25%)……
        symbol = np.random.choice(symbols, p=[0.35, 0.25, 0.20, 0.12, 0.08])
        side = np.random.choice(sides)
        # 盈亏模拟:均值25美元,标准差300(含滑点和运气成分)
        pnl = np.random.normal(25, 300)
        # 持仓时长模拟:指数分布,平均约45分钟
        duration = np.random.exponential(45)

        trades.append({
            "trade_id": i + 1,
            "entry_time": entry_time,
            "exit_time": entry_time + timedelta(minutes=duration),
            "symbol": symbol,
            "side": side,
            "quantity": np.random.choice([1, 2, 3, 5]),  # 手数随机
            "pnl": round(pnl, 2),
            "commission": round(np.random.uniform(2, 8), 2),  # 手续费2–8美元
        })

    return pd.DataFrame(trades)

# ✅ 第一步:生成或加载你的真实交易CSV(替换这行即可!)
df = generate_sample_trades()  # ← 把这行换成:df = pd.read_csv("my_trades.csv")
df["net_pnl"] = df["pnl"] - df["commission"]  # 扣掉手续费才是真盈亏
df["entry_hour"] = df["entry_time"].dt.hour  # 提取入场小时(方便分析“黄金时段”)
df["day_of_week"] = df["entry_time"].dt.day_name()  # 提取星期几
df["duration_min"] = (df["exit_time"] - df["entry_time"]).dt.total_seconds() / 60  # 持仓分钟数

class TradeAnalyzer:
    def __init__(self, df: pd.DataFrame):
        self.df = df.copy()
        self.df["is_winner"] = self.df["net_pnl"] > 0  # 自动标记盈利单(True/False)

    def summary_stats(self) -> dict:
        d = self.df
        winners = d[d["is_winner"]]
        losers = d[~d["is_winner"]]
        return {
            "total_trades": len(d),
            "win_rate": f"{len(winners) / len(d) * 100:.1f}%",  # 胜率保留1位小数
            "total_pnl": f"${d['net_pnl'].sum():,.2f}",  # 总盈亏带千分位和$符号
            "avg_winner": f"${winners['net_pnl'].mean():,.2f}" if len(winners) else "N/A",
            "avg_loser": f"${losers['net_pnl'].mean():,.2f}" if len(losers) else "N/A",
            # 盈利总额 ÷ 亏损总额 = 利润因子(>1才健康)
            "profit_factor": f"{abs(winners['net_pnl'].sum() / losers['net_pnl'].sum()):.2f}" if losers['net_pnl'].sum() != 0 else "inf",
            "largest_winner": f"${d['net_pnl'].max():,.2f}",
            "largest_loser": f"${d['net_pnl'].min():,.2f}",
            "avg_duration_min": f"{d['duration_min'].mean():.1f}",  # 平均持仓分钟
            # 粗略夏普比率(年化):收益均值 ÷ 收益标准差 × √252
            "sharpe_approx": f"{d['net_pnl'].mean() / d['net_pnl'].std() * np.sqrt(252):.2f}",
        }

    def by_symbol(self) -> pd.DataFrame:
        # 按品种统计:交易次数、总盈亏、胜率、平均盈亏
        return self.df.groupby("symbol").agg(
            trades=("net_pnl", "count"),
            total_pnl=("net_pnl", "sum"),
            win_rate=("is_winner", "mean"),
            avg_pnl=("net_pnl", "mean"),
        ).round(2).sort_values("total_pnl", ascending=False)

    def by_hour(self) -> pd.DataFrame:
        # 按入场小时统计:哪个整点最赚钱?哪个点最容易翻车?
        return self.df.groupby("entry_hour").agg(
            trades=("net_pnl", "count"),
            total_pnl=("net_pnl", "sum"),
            win_rate=("is_winner", "mean"),
        ).round(2)

    def by_day(self) -> pd.DataFrame:
        # 按星期统计(按周一到周五顺序排),避免乱序干扰判断
        day_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
        result = self.df.groupby("day_of_week").agg(
            trades=("net_pnl", "count"),
            total_pnl=("net_pnl", "sum"),
            win_rate=("is_winner", "mean"),
        ).round(2)
        return result.reindex(day_order)

    def streak_analysis(self) -> dict:
        # 连胜/连亏分析:+1,+2,+3… 或 -1,-2,-3…,最后看极值
        streaks = []
        current = 0
        for win in self.df["is_winner"]:
            if win:
                current = max(0, current) + 1  # 赢就累加连胜
            else:
                current = min(0, current) - 1  # 输就累加连亏(负数)
            streaks.append(current)
        return {
            "max_win_streak": max(streaks),
            "max_loss_streak": abs(min(streaks)),
            "current_streak": streaks[-1] if streaks else 0,
        }

# ✅ 第二步:运行分析器(只需这一行)
analyzer = TradeAnalyzer(df)

# ✅ 第三步:看一眼核心指标(5秒出结果!)
print("📊 核心统计:")
stats = analyzer.summary_stats()
for k, v in stats.items():
    print(f"  {k}: {v}")

print("\n📈 各品种表现(按总盈亏排序):")
print(analyzer.by_symbol().to_string())

print("\n⏰ 入场小时表现(哪一小时最稳?):")
print(analyzer.by_hour().to_string())

print("\n📅 星期表现(避开你的‘黑色星期X’):")
print(analyzer.by_day().to_string())

print("\n🔥 连胜连亏追踪:")
streaks = analyzer.streak_analysis()
for k, v in streaks.items():
    print(f"  {k}: {v}")

# ✅ Bonus:一键生成简洁报告(可直接发给导师/队友)
def generate_report(analyzer: TradeAnalyzer) -> str:
    stats = analyzer.summary_stats()
    streaks = analyzer.streak_analysis()
    by_sym = analyzer.by_symbol()
    best_symbol = by_sym.index[0]  # 盈利最多的品种
    worst_symbol = by_sym.index[-1]  # 盈利最少的品种

    report = f'''
# 📄 你的交易健康报告
生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M')}

## 🧾 整体表现
- 总交易数:{stats['total_trades']}
- 胜率:{stats['win_rate']}
- 净盈亏:{stats['total_pnl']}
- 利润因子:{stats['profit_factor']}(>1.5算优秀)

## 🔍 关键发现
- 最佳品种:{best_symbol}
- 最差品种:{worst_symbol}
- 最长连胜:{streaks['max_win_streak']} 单
- 最长连亏:{streaks['max_loss_streak']} 单
'''
    return report

print(generate_report(analyzer))

💡 怎么用到你自己的交易数据?
只需两步:
1. 把你券商导出的 CSV 文件(如 trades_2024.csv)放在同一文件夹;
2. 把代码里 df = generate_sample_trades() 这一行,替换成:
df = pd.read_csv("trades_2024.csv")
→ 确保CSV里有 entry_time, exit_time, pnl, symbol 等列名(列名不同?我帮你改,留言就行 👇)

这套分析不是“炫技”,而是帮你守住本金的最小可行系统:
– 发现「每天14:00之后胜率暴跌30%」→ 主动避开这个时段;
– 看到「MES连亏7单」→ 暂停该品种,检查策略是否失效;
– 知道「周五总盈亏为负」→ 下周直接休市一天。

真正的专业,不是每单都对,而是让错误变得可见、可停、可修正。

直达网址:https://propfirmkey.com

作加

类似文章