mcpField
T
trade-journal

trade-journal

github.com/agiprolabs数据与数据库456524 次安装8 周前更新
代码仓库

关于 trade-journal

面向希望系统复盘表现与行为的交易者的交易日志技能。它以 JSON 或 CSV 记录交易背景和结果,并提供分析及行为模式检测脚本。

主要功能

  1. 01结构化交易记录
  2. 02JSON 存储与 CSV 导出
  3. 03按策略分析表现
  4. 04检测交易行为模式
  5. 05日、周、月度复盘
  6. 06命令行记录与分析脚本

适用场景

  1. 01比较不同交易策略的表现
  2. 02发现报复性交易或 FOMO 模式
  3. 03按时段或代币复盘表现
  4. 04跟踪交易流程调整效果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agiprolabs/claude-trading-skills --skill trade-journal

安装后在 Claude Code 中输入/trade-journal确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
record_format.md
review_framework.md
scripts/
journal_analyzer.py
trade_logger.py

详细介绍

交易日志

通过结构化交易日志实现系统性改进。记录每笔交易及其背景,按多个周期回顾表现,发现损害优势的行为模式,并将收益归因到具体策略。

为什么记录交易日志很重要

大多数交易者失败,不是因为策略不佳,而是因为行为不当。交易日志能将主观的“感觉”转化为客观数据:

  • 策略归因:了解哪些形态真正赚钱,哪些只是感觉有利可图
  • 行为检测:在报复性交易、FOMO 入场和过早离场造成更大影响之前及时发现
  • 模式识别:发现自己周一早上的交易会亏钱,或是过早卖出 SOL 盈利仓位
  • 问责:入场前写下理由,促使自己审慎决策
  • 改进跟踪:衡量流程的改变是否真的改善了结果

没有日志,你只能根据噪声进行优化。有了日志,你才能根据有效信号进行优化。

交易记录结构

每条交易记录都会记录入场时的背景和离场时的结果。完整的 18 个字段结构请参阅 references/record_format.md。

最低必填字段
trade = {
    "id": "T-20250310-001",
    "token": "SOL",
    "direction": "long",
    "entry_date": "2025-03-10T14:30:00Z",
    "entry_price": 142.50,
    "size_sol": 5.0,
    "strategy": "momentum-breakout",
    "rationale": "Breaking above 4h resistance at 141.80 with volume confirmation",
    "exit_date": "2025-03-10T16:45:00Z",
    "exit_price": 146.20,
    "pnl_sol": 0.648,
    "outcome": "win",
    "lessons": "Held through initial pullback to 143.0, rewarded for patience"
}
策略标签

使用统一的标签来进行表现归因:

类别标签
动量momentum-breakout、trend-continuation、pullback-entry
均值回归range-fade、oversold-bounce、deviation-snap
事件驱动listing-play、catalyst-trade、news-reaction
链上whale-follow、wallet-copy、flow-signal
DeFilp-entry、yield-farm、arb-capture
理由模板

入场前先写下理由。以下是按形态类型分类的模板:

Momentum: "[Token] breaking [level] on [timeframe] with [confirmation]. Target [price], stop [price]."
Mean Reversion: "[Token] at [X] std devs from [mean] on [timeframe]. Expecting reversion to [target]."
On-Chain: "[Signal type] detected — [wallet/flow description]. Historical hit rate [X]%."

存储格式

日志使用 JSON 进行结构化查询,并使用 CSV 兼容电子表格。

JSON 格式(主要)
{
  "journal_version": "1.0",
  "trader_id": "anon",
  "trades": [
    {
      "id": "T-20250310-001",
      "token": "SOL",
      "direction": "long",
      "entry_date": "2025-03-10T14:30:00Z",
      "entry_price": 142.50,
      "size_sol": 5.0,
      "size_usd": 712.50,
      "strategy": "momentum-breakout",
      "setup_quality": 8,
      "rationale": "Breaking above 4h resistance with volume",
      "exit_date": "2025-03-10T16:45:00Z",
      "exit_price": 146.20,
      "pnl_sol": 0.648,
      "pnl_pct": 2.60,
      "outcome": "win",
      "hold_time_minutes": 135,
      "emotional_state": "calm",
      "lessons": "Patience through pullback paid off",
      "tags": ["high-conviction", "clean-setup"]
    }
  ]
}
CSV 格式(导出)
id,token,direction,entry_date,entry_price,size_sol,strategy,exit_date,exit_price,pnl_sol,pnl_pct,outcome,lessons
T-20250310-001,SOL,long,2025-03-10T14:30:00Z,142.50,5.0,momentum-breakout,2025-03-10T16:45:00Z,146.20,0.648,2.60,win,"Patience paid off"

交易日志数据分析

按策略统计胜率
from collections import Counter

def win_rate_by_strategy(trades: list[dict]) -> dict[str, float]:
    """Compute win rate grouped by strategy tag."""
    strategy_outcomes: dict[str, list[str]] = {}
    for t in trades:
        strat = t["strategy"]
        strategy_outcomes.setdefault(strat, []).append(t["outcome"])

    return {
        strat: outcomes.count("win") / len(outcomes)
        for strat, outcomes in strategy_outcomes.items()
        if len(outcomes) >= 5  # minimum sample size
    }
按时段统计表现
from datetime import datetime

def pnl_by_hour(trades: list[dict]) -> dict[int, float]:
    """Aggregate P&L by entry hour (UTC)."""
    hourly: dict[int, float] = {}
    for t in trades:
        hour = datetime.fromisoformat(t["entry_date"].rstrip("Z")).hour
        hourly[hour] = hourly.get(hour, 0.0) + t.get("pnl_sol", 0.0)
    return dict(sorted(hourly.items()))
按代币类型统计盈利因子
def profit_factor(trades: list[dict], group_key: str = "token") -> dict[str, float]:
    """Compute profit factor (gross wins / gross losses) by grouping key."""
    groups: dict[str, dict[str, float]] = {}
    for t in trades:
        key = t.get(group_key, "unknown")
        groups.setdefault(key, {"wins": 0.0, "losses": 0.0})
        pnl = t.get("pnl_sol", 0.0)
        if pnl > 0:
            groups[key]["wins"] += pnl
        else:
            groups[key]["losses"] += abs(pnl)

    return {
        k: v["wins"] / v["losses"] if v["losses"] > 0 else float("inf")
        for k, v in groups.items()
    }

行为模式检测

交易日志有助于发现破坏性的交易模式。完整框架请参阅 references/review_framework.md。

报复性交易

亏损后迅速重新入场,通常仓位更大:

def detect_revenge_trades(trades: list[dict], max_gap_minutes: int = 15) -> list[dict]:
    """Find trades entered within max_gap_minutes of a losing exit."""
    sorted_trades = sorted(trades, key=lambda t: t["entry_date"])
    revenge = []
    for i in range(1, len(sorted_trades)):
        prev, curr = sorted_trades[i - 1], sorted_trades[i]
        if prev["outcome"] == "loss":
            prev_exit = datetime.fromisoformat(prev["exit_date"].rstrip("Z"))
            curr_entry = datetime.fromisoformat(curr["entry_date"].rstrip("Z"))
            gap = (curr_entry - prev_exit).total_seconds() / 60
            if gap <= max_gap_minutes:
                revenge.append(curr)
    return revenge
FOMO 检测

在价格大幅波动后入场,却没有合适的形态:

  • 入场理由含糊不清或缺失
  • 形态质量自评低于 5/10
  • 入场时的波动幅度已超过 1 ATR
过早止盈/持有亏损仓位
def winner_loser_hold_times(trades: list[dict]) -> dict[str, float]:
    """Compare average hold time for wins vs losses."""
    win_times = [t["hold_time_minutes"] for t in trades if t["outcome"] == "win"]
    loss_times = [t["hold_time_minutes"] for t in trades if t["outcome"] == "loss"]
    return {
        "avg_win_hold_min": sum(win_times) / len(win_times) if win_times else 0,
        "avg_loss_hold_min": sum(loss_times) / len(loss_times) if loss_times else 0,
    }
    # RED FLAG: if avg_loss_hold > avg_win_hold, you're cutting winners and riding losers
情绪失控检测

亏损后加大仓位表明交易受到情绪影响:

def detect_tilt(trades: list[dict], threshold: float = 1.5) -> list[dict]:
    """Flag trades where size increased >threshold after a loss."""
    tilt_trades = []
    for i in range(1, len(trades)):
        prev, curr = trades[i - 1], trades[i]
        if prev["outcome"] == "loss" and curr["size_sol"] > prev["size_sol"] * threshold:
            tilt_trades.append(curr)
    return tilt_trades

回顾频率

每日回顾(5 分钟)
  • 今天进行了多少笔交易?盈亏如何?
  • 每笔交易是否都遵守了规则?
  • 是否做出了受情绪影响的决策?
  • 一件做得好的事,以及一件需要改进的事
每周回顾(30 分钟)
  • 按策略统计胜率和盈利因子
  • 检查行为模式(报复性交易、情绪失控、FOMO)
  • 本周最佳和最差的交易——它们有何不同?
  • 策略表现与预期是否相符
  • 如有需要,调整仓位规模
每月回顾(2 小时)
  • 全面分析策略归因
  • 回顾权益曲线——回撤阶段及恢复情况
  • 比较每笔交易的实际风险与计划风险
  • 按代币类型、时段和星期几分析表现
  • 是否有策略持续亏损?考虑弃用
  • 回顾并更新策略参数

详细的回顾清单和问题请参阅 references/review_framework.md。

部分离场和分批入场

实际交易涉及分批建仓和平仓。日志通过子记录处理这些情况:

# Parent trade with two scale-out exits
parent = {
    "id": "T-20250310-001",
    "token": "BONK",
    "direction": "long",
    "entry_date": "2025-03-10T14:30:00Z",
    "entry_price": 0.000023,
    "size_sol": 10.0,
    "strategy": "momentum-breakout",
    "exits": [
        {"date": "2025-03-10T15:00:00Z", "price": 0.000025, "size_pct": 50, "reason": "first-target"},
        {"date": "2025-03-10T16:30:00Z", "price": 0.000028, "size_pct": 50, "reason": "trailing-stop"},
    ]
}

部分离场处理的完整说明请参阅 references/record_format.md。

文件

参考资料
  • references/record_format.md — 完整的 18 字段交易记录架构、字段说明、标签分类、CSV/JSON 示例、部分平仓处理
  • references/review_framework.md — 每日/每周/每月复盘清单、行为预警信号、绩效衰退检测
脚本
  • scripts/trade_logger.py — CLI 交易记录工具:添加、列出、更新、计算统计数据、筛选、演示模式(仅使用标准库)
  • scripts/journal_analyzer.py — 交易日志分析:策略表现、行为模式、基于时间的分析、演示模式(仅使用标准库)

依赖项

两个脚本仅使用 Python 标准库(json、datetime、argparse、collections)。无需安装外部包。

# No installation needed — stdlib only
python scripts/trade_logger.py --demo
python scripts/journal_analyzer.py --demo

免责声明

此技能提供交易记录和绩效分析工具,不提供财务建议或交易推荐,也不保证任何交易结果。所有分析仅供参考,仅用于个人复盘。

评论

支持 Markdown