Files
xiaobaifupan/next/backend/features/review/views.py
T

55 lines
1.7 KiB
Python

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