diff --git a/ai_client.py b/ai_client.py index 5c2cd06..fca4be1 100644 --- a/ai_client.py +++ b/ai_client.py @@ -182,10 +182,11 @@ def ai_generate( def ai_review(trades_text: str, period_title: str, image_paths=None) -> str: n_img = len(image_paths or []) + period_label = "周" if "周" in str(period_title) else "日" attach_note = ( - f"【系统说明:已向模型附带 {n_img} 张复盘附图(自动K线或上传截图),请结合附图分析第5节。】\n\n" + f"ℹ️ 【系统说明:已向模型附带 {n_img} 张复盘附图(自动K线或上传截图),请结合附图分析第5节。】\n\n" if n_img - else "【系统说明:本次未附带复盘附图,第5节请写明「无附图,无法看图」;保存复盘记录时可勾选「自动生成K线图」。】\n\n" + else "ℹ️ 【系统说明:本次未附带复盘附图,第5节请写明「无附图,无法看图」;保存复盘记录时可勾选「自动生成K线图」。】\n\n" ) prompt = f""" 你是一位专业交易教练。下面是用户的{period_title}交易记录,请做简洁、可执行的复盘(中文)。 @@ -198,12 +199,19 @@ def ai_review(trades_text: str, period_title: str, image_paths=None) -> str: - 禁止用语:人身攻击、夸张定性(如「致命伤」「灾难」);语气克制、对事不对人。 - 若有截图且你能辨认,再结合图讨论;看不清或无明确定位则明确说「无法从图确认」,不得虚构 K 线故事。 -【输出结构】 -1. 总体盈亏结构(紧扣笔数、盈亏数字与 RR,少形容词) -2. 心态与执行(每笔 1–10 分 + 一句依据;依据必须对应记录字段) -3. 行为标签(提前离场 / 乱开仓 / 扛单等):仅在有字段或自述支撑时点名;否则写「记录未勾选或未描述,不作强加」 -4. 改进建议(最多 3 条,每条具体可执行) -5. 图表(若有且可读):结合价格行为简述;否则一两句说明无法看图分析 +【输出格式 — Markdown,必须严格遵守】 +- 第一行:**交易复盘报告({period_label}度)** +- 五个大节标题必须**完全一致**(含 emoji,不要用其它编号或改名): + **1. 📊 总体盈亏结构** + **2. 🧠 心态与执行** + **3. 🏷️ 行为标签** + **4. ✅ 改进建议** + **5. 📈 图表分析** +- 每节正文用 `- **子项名**:内容` 列表;第4节改进建议用有序列表 `1. 2. 3.` +- 第1节至少包含:**笔数/盈亏**、**风险回报比**、**总结** +- 第2节至少包含:**得分**(1–10)、**依据**(对应记录字段) +- 第5节至少包含:**趋势确认**、**执行路径**(记录不足则写明) +- 语气简洁,少形容词;不要输出代码块、不要表格 交易记录: {trades_text} diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 6145ea8..c8a5b4c 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -1,4 +1,4 @@ -from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, Response +from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, Response, send_file import sqlite3 import csv from io import StringIO @@ -7517,6 +7517,16 @@ def api_reviews(): return jsonify([row_to_dict(r) for r in rows]) +_AI_REVIEW_RENDER_JS = os.path.join(os.path.dirname(BASE_DIR), "static", "ai_review_render.js") + + +@app.route("/static/ai_review_render.js") +def static_ai_review_render_js(): + if not os.path.isfile(_AI_REVIEW_RENDER_JS): + return Response("not found", status=404, mimetype="text/plain; charset=utf-8") + return send_file(_AI_REVIEW_RENDER_JS, mimetype="application/javascript; charset=utf-8") + + @app.route("/export/review_md/") @login_required def export_review_md(rid): diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index 86c9b07..3396047 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -62,6 +62,15 @@ .pnl-loss{color:#ff6666;font-weight:600} .flash{padding:10px;background:#1e2533;color:#4cc2ff;border-radius:10px;margin-bottom:12px;text-align:center;border:1px solid #304164} .ai-result{background:#1a1a29;border:1px solid #2e2e45;border-radius:8px;padding:10px;white-space:pre-wrap;max-height:220px;overflow:auto;font-size:.84rem;line-height:1.45;margin-top:8px} + .ai-result.ai-result-md,.detail-modal .panel-body.md-review{white-space:normal} + .ai-result-md p,.detail-modal .panel-body.md-review p{margin:6px 0;color:#dde2ff} + .ai-result-md ul,.ai-result-md ol,.detail-modal .panel-body.md-review ul,.detail-modal .panel-body.md-review ol{margin:6px 0 8px 1.25em;padding:0} + .ai-result-md li,.detail-modal .panel-body.md-review li{margin:5px 0;line-height:1.5} + .ai-result-md strong,.detail-modal .panel-body.md-review strong{color:#f0f3ff;font-weight:600} + .ai-result-md h2,.detail-modal .panel-body.md-review h2{font-size:1.02rem;color:#b8c8ff;margin:14px 0 8px;padding-bottom:4px;border-bottom:1px solid #2e2e45} + .ai-result-md h3,.detail-modal .panel-body.md-review h3{font-size:.92rem;color:#c9d4ff;margin:10px 0 6px} + .ai-result-md code,.detail-modal .panel-body.md-review code{background:#252538;padding:1px 4px;border-radius:4px;font-size:.82em} + .ai-result-md .md-raw-block-title,.detail-modal .panel-body.md-review .md-raw-block-title{margin-top:14px;padding-top:10px;border-top:1px dashed #3a3a55;color:#a8b0d8;font-weight:600} .price-up{color:#4cd97f} .price-down{color:#ff6666} .price-flat{color:#cfd3ef} @@ -852,6 +861,7 @@ +