trade-journal
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTrade Journal
交易日志
Structured trade journaling for systematic improvement. Log every trade with context, review performance at multiple cadences, detect behavioral patterns that destroy edge, and attribute returns to specific strategies.
用于系统化提升的结构化交易日志记录。记录每一笔交易的上下文信息,按不同周期复盘绩效,检测会削弱交易优势的行为模式,并将收益归因于特定策略。
Why Journaling Matters
交易日志的重要性
Most traders fail not from bad strategies but from bad behavior. A trade journal transforms subjective "feel" into objective data:
- Strategy Attribution: Know which setups actually make money vs. which feel profitable
- Behavioral Detection: Catch revenge trading, FOMO entries, and premature exits before they compound
- Pattern Recognition: Discover that your Monday morning trades lose money, or that you cut SOL winners too early
- Accountability: Written rationale before entry forces deliberate decision-making
- Improvement Tracking: Measure whether changes to your process actually improve results
Without a journal, you optimize on noise. With one, you optimize on signal.
大多数交易者失败并非因为策略不佳,而是因为不良交易行为。交易日志能将主观的“感觉”转化为客观数据:
- 策略归因:明确哪些交易定式真正盈利,哪些只是看似盈利
- 行为检测:在报复性交易、FOMO入场、过早离场等行为加剧前及时发现
- 模式识别:发现周一早盘交易总是亏损,或是过早止盈SOL交易等规律
- 问责机制:入场前写下交易理由,促使决策更审慎
- 提升追踪:衡量交易流程的调整是否真的改善了结果
没有日志,你只是在噪音中优化;有了日志,你才能在有效信号中优化。
Trade Record Structure
交易记录结构
Every trade record captures context at entry and outcome at exit. See for the complete 18-field schema.
references/record_format.md每一条交易记录都会捕捉入场时的上下文信息和离场时的结果。完整的18字段 schema 请查看 。
references/record_format.mdMinimum Required Fields
必填字段
python
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"
}python
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"
}Strategy Tagging
策略标签
Use consistent tags to enable performance attribution:
| Category | Tags |
|---|---|
| Momentum | |
| Mean Reversion | |
| Event-Driven | |
| On-Chain | |
| DeFi | |
使用统一标签实现绩效归因:
| 分类 | 标签 |
|---|---|
| 动量策略 | |
| 均值回归 | |
| 事件驱动 | |
| 链上数据 | |
| DeFi | |
Rationale Templates
交易理由模板
Write rationale before entering. Templates by setup type:
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]%."入场前撰写交易理由。按定式类型分类的模板:
动量策略: "[Token] 在[时间周期]突破[价位],伴随[确认信号]。目标价[价格],止损价[价格]。"
均值回归: "[Token] 在[时间周期]偏离均值[X]个标准差。预期回归至[目标价]。"
链上数据: "检测到[信号类型] — [钱包/资金流描述]。历史命中率[X]%。"Storage Format
存储格式
The journal uses JSON for structured querying and CSV for spreadsheet compatibility.
日志采用JSON格式支持结构化查询,同时提供CSV格式兼容电子表格。
JSON Format (Primary)
JSON格式(主格式)
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"]
}
]
}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 Format (Export)
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"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"Analytics from Journal Data
日志数据的分析应用
Win Rate by Strategy
按策略统计胜率
python
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
}python
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
}Performance by Time of Day
按时段统计绩效
python
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()))python
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()))Profit Factor by Token Type
按代币类型统计盈利因子
python
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()
}python
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()
}Behavioral Pattern Detection
行为模式检测
The journal enables detection of destructive trading patterns. See for the full framework.
references/review_framework.md交易日志可用于检测破坏性交易模式。完整框架请查看 。
references/review_framework.mdRevenge Trading
报复性交易
Rapid re-entry after a loss, often with larger size:
python
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亏损后快速重新入场,通常仓位更大:
python
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 revengeFOMO Detection
FOMO行为检测
Entering after large moves without proper setup:
- Entry rationale is vague or missing
- Setup quality self-rated below 5/10
- Entry during a move that already exceeded 1 ATR
未按定式操作,在大幅波动后入场:
- 入场理由模糊或缺失
- 自我评定的定式质量低于5/10
- 入场时波动已超过1个ATR
Cutting Winners / Riding Losers
过早止盈/扛单
python
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 loserspython
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,
}
# 危险信号:如果avg_loss_hold > avg_win_hold,说明你在过早止盈、扛单亏损Tilt Detection
情绪失控检测
Size escalation after losses suggests emotional trading:
python
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亏损后仓位加大,表明交易受情绪影响:
python
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_tradesReview Cadence
复盘周期
Daily Review (5 minutes)
每日复盘(5分钟)
- How many trades today? P&L?
- Did I follow my rules on every trade?
- Any emotional decisions?
- One thing I did well, one thing to improve
- 今日交易数量?盈亏情况?
- 每笔交易是否都遵守了规则?
- 是否有情绪化决策?
- 做得好的一点,以及需要改进的一点
Weekly Review (30 minutes)
每周复盘(30分钟)
- Win rate and profit factor by strategy
- Behavioral pattern check (revenge trades, tilt, FOMO)
- Best and worst trade of the week — what made them different?
- Strategy performance vs. expectations
- Adjust position sizing if needed
- 按策略统计胜率和盈利因子
- 检查行为模式(报复性交易、情绪失控、FOMO)
- 本周最佳和最差交易——差异在哪里?
- 策略绩效与预期对比
- 必要时调整仓位大小
Monthly Review (2 hours)
每月复盘(2小时)
- Full strategy attribution analysis
- Equity curve review — drawdown periods and recovery
- Compare actual vs. planned risk per trade
- Performance by token type, time of day, day of week
- Are any strategies consistently losing? Consider dropping them
- Review and update strategy parameters
See for detailed review checklists and questions.
references/review_framework.md- 完整的策略归因分析
- 权益曲线复盘——回撤期和复苏情况
- 对比实际与计划的每笔交易风险
- 按代币类型、时段、星期统计绩效
- 是否有策略持续亏损?考虑放弃
- 复盘并更新策略参数
详细的复盘清单和问题请查看 。
references/review_framework.mdPartial Exits and Scaled Entries
分批离场与分批入场
Real trading involves scaling in and out. The journal handles this with child records:
python
undefined实际交易中会涉及分批入场和离场。日志通过子记录处理此类情况:
python
undefinedParent 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"},
]
}
See `references/record_format.md` for full documentation of partial exit handling.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`。Files
文件说明
References
参考文档
- — Complete 18-field trade record schema, field descriptions, tagging taxonomy, CSV/JSON examples, partial exit handling
references/record_format.md - — Daily/weekly/monthly review checklists, behavioral red flags, performance decay detection
references/review_framework.md
- — 完整的18字段交易记录schema、字段说明、标签分类、CSV/JSON示例、分批离场处理方式
references/record_format.md - — 每日/每周/每月复盘清单、行为危险信号、绩效衰减检测
references/review_framework.md
Scripts
脚本文件
- — CLI trade logger: add, list, update, compute stats, filter, demo mode (stdlib only)
scripts/trade_logger.py - — Journal analysis: strategy performance, behavioral patterns, time-based analysis, demo mode (stdlib only)
scripts/journal_analyzer.py
- — CLI交易日志工具:添加、列出、更新交易,计算统计数据,筛选,演示模式(仅使用标准库)
scripts/trade_logger.py - — 日志分析工具:策略绩效、行为模式、时段分析,演示模式(仅使用标准库)
scripts/journal_analyzer.py
Dependencies
依赖说明
Both scripts use Python standard library only (, , , ). No external packages required.
jsondatetimeargparsecollectionsbash
undefined两个脚本仅使用Python标准库(, , , ),无需外部包。
jsondatetimeargparsecollectionsbash
undefinedNo installation needed — stdlib only
无需安装——仅依赖标准库
python scripts/trade_logger.py --demo
python scripts/journal_analyzer.py --demo
undefinedpython scripts/trade_logger.py --demo
python scripts/journal_analyzer.py --demo
undefinedDisclaimer
免责声明
This skill provides tools for trade record-keeping and performance analysis. It does not provide financial advice, trading recommendations, or guarantee any trading outcomes. All analysis is informational and for personal review purposes only.
本工具仅提供交易记录和绩效分析功能,不提供财务建议、交易推荐,也不保证任何交易结果。所有分析仅作信息参考,供个人复盘使用。