from __future__ import annotations import json from typing import Any ACTIONS = {"buy": "买入", "sell": "卖出", "add": "加仓", "trim": "减仓", "watch": "观察"} EMOTIONS = { "calm": "平静", "confident": "笃定", "hesitant": "犹豫", "anxious": "焦虑", "impulsive": "冲动", } def note(row) -> dict[str, Any] | None: return dict(row) if row is not None else None def trades(rows) -> list[dict[str, Any]]: result = [] for row in rows: item = dict(row) item["tags"] = json.loads(str(item.pop("tags_json"))) item["action_label"] = ACTIONS[str(item["action"])] item["emotion_label"] = EMOTIONS[str(item["emotion"])] result.append(item) return result def trade_summary(items: list[dict[str, Any]]) -> dict[str, Any]: realized = [ item for item in items if item["pnl_amount"] is not None or item["pnl_pct"] is not None ] wins = sum( float(item["pnl_pct"] if item["pnl_pct"] is not None else item["pnl_amount"]) > 0 for item in realized ) amounts = [float(item["pnl_amount"]) for item in items if item["pnl_amount"] is not None] positions = [float(item["position_pct"]) for item in items if item["position_pct"] is not None] return { "total": len(items), "realized": len(realized), "win_rate": round(wins / len(realized) * 100, 1) if realized else None, "pnl_amount": round(sum(amounts), 2) if amounts else None, "average_position": round(sum(positions) / len(positions), 1) if positions else None, } def alert(row, today: str) -> dict[str, Any]: item = dict(row) item["is_read"] = bool(item["is_read"]) item["due"] = str(item["available_date"]) <= today return item