migrate: remove JSON, DB-only — mo_data, server, scripts, prompts (27 files)

This commit is contained in:
知微
2026-07-03 12:12:05 +08:00
parent b1a79d962c
commit b3bedc8024
43 changed files with 8272 additions and 7449 deletions
+193 -186
View File
@@ -1,186 +1,193 @@
"""策略→提示词版本分析引擎
核心功能:将策略评估结果按提示词版本聚合,计算每个版本的准确率。
"""
import json
from pathlib import Path
from datetime import datetime
from typing import Optional
from .tracking import load_associations, get_associations_for_prompt_version
from .registry import get_prompt, get_version_history
PROJECT_DIR = Path("/home/hmo/projects/MoFin")
DECISIONS_PATH = PROJECT_DIR / "data" / "decisions.json"
ACCURACY_PATH = PROJECT_DIR / "data" / "accuracy_stats.json"
EVAL_PATH = PROJECT_DIR / "data" / "evaluation.json"
def _load_json(path, default=None):
try:
with open(path, encoding="utf-8") as f:
return json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
return {} if default is None else default
def analyze_prompt_version_effectiveness() -> dict:
"""按提示词版本聚合策略评估结果
关联 decisions.json 中的 evaluation 字段和 associations.json 中的版本记录,
计算出每个提示词版本的:
- 生成的策略总数
- 达到止盈数(成功)
- 跌破止损数(失败)
- 待验证数
- 盈亏比平均值
"""
# 加载数据
decisions = _load_json(DECISIONS_PATH, {"decisions": []})
associations = load_associations().get("associations", [])
# 建立 code → 最新关联的映射
code_to_pv = {} # code -> {prompt_id, version}
for a in associations:
code = a.get("code")
if code and code not in code_to_pv:
code_to_pv[code] = {
"prompt_id": a.get("prompt_id"),
"version": a.get("prompt_version"),
}
# 按 prompt_id@version 分组统计
version_stats = {}
for d in decisions.get("decisions", []):
code = d.get("code")
if not code:
continue
pv = code_to_pv.get(code)
if not pv:
continue
key = f"{pv['prompt_id']}@{pv['version']}"
if key not in version_stats:
version_stats[key] = {
"prompt_id": pv["prompt_id"],
"version": pv["version"],
"total": 0,
"take_profit_hit": 0,
"stop_loss_hit": 0,
"in_entry_zone": 0,
"pending": 0,
"avg_rr": 0.0,
"rr_sum": 0.0,
"rr_count": 0,
"stocks": [],
}
vs = version_stats[key]
vs["total"] += 1
vs["stocks"].append(code)
# 从 evaluation 中读取状态
evals = d.get("evaluation", [])
for ev in evals:
if isinstance(ev, dict) and ev.get("phase") == 1:
theo = ev.get("theoretical", {})
status = theo.get("status", "")
if status == "take_profit_hit":
vs["take_profit_hit"] += 1
elif status == "stop_loss_hit":
vs["stop_loss_hit"] += 1
elif status == "in_entry_zone":
vs["in_entry_zone"] += 1
else:
vs["pending"] += 1
# 盈亏比
rr = d.get("rr_ratio")
if rr is not None and isinstance(rr, (int, float)):
vs["rr_sum"] += rr
vs["rr_count"] += 1
# 计算平均盈亏比和成功率
for key, vs in version_stats.items():
if vs["rr_count"] > 0:
vs["avg_rr"] = round(vs["rr_sum"] / vs["rr_count"], 2)
total_outcome = vs["take_profit_hit"] + vs["stop_loss_hit"]
if total_outcome > 0:
vs["success_rate"] = round(vs["take_profit_hit"] / total_outcome * 100, 1)
else:
vs["success_rate"] = None
del vs["rr_sum"]
return version_stats
def get_prompt_version_comparison() -> dict:
"""生成版本对比报告"""
version_stats = analyze_prompt_version_effectiveness()
# 补充每个版本的标签信息
for key, vs in version_stats.items():
prompt = get_prompt(vs["prompt_id"])
if prompt:
for v in prompt.versions:
if v.version == vs["version"]:
vs["label"] = v.label
vs["changelog"] = v.changelog
vs["tags"] = v.tags
break
if "label" not in vs:
vs["label"] = vs["version"]
return version_stats
def generate_report() -> str:
"""生成版本有效性报告文本"""
comparison = get_prompt_version_comparison()
lines = []
lines.append("📊 提示词版本有效性分析 | " + datetime.now().strftime("%Y-%m-%d"))
lines.append("")
if not comparison:
lines.append("暂无数据 — 请先运行策略生成和评估后重试")
return "\n".join(lines)
# 按 prompt_id 分组显示
by_prompt = {}
for key, vs in comparison.items():
pid = vs["prompt_id"]
by_prompt.setdefault(pid, []).append(vs)
for pid, versions in sorted(by_prompt.items()):
prompt = get_prompt(pid)
lines.append(f"\n## {prompt.name if prompt else pid}")
lines.append(f" {prompt.description if prompt else ''}")
lines.append("")
# 按版本号排序
versions.sort(key=lambda x: x["version"])
header = f" {'版本':<10} {'标签':<20} {'策略数':<8} {'止盈':<8} {'止损':<8} {'成功率':<10} {'平均R/R':<10}"
lines.append(header)
lines.append(" " + "-" * len(header))
for vs in versions:
sr = f"{vs['success_rate']}%" if vs['success_rate'] is not None else "-"
label = vs.get("label", "")[:18]
lines.append(
f" {vs['version']:<10} {label:<20} "
f"{vs['total']:<8} {vs['take_profit_hit']:<8} "
f"{vs['stop_loss_hit']:<8} {sr:<10} "
f"{vs['avg_rr']:<10}"
)
lines.append("")
lines.append("---")
lines.append("注:数据来自 decisions.json evaluation + associations.json")
return "\n".join(lines)
"""策略→提示词版本分析引擎
核心功能:将策略评估结果按提示词版本聚合,计算每个版本的准确率。
"""
import json
from pathlib import Path
from datetime import datetime
from typing import Optional
from .tracking import load_associations, get_associations_for_prompt_version
from .registry import get_prompt, get_version_history
PROJECT_DIR = Path("/home/hmo/projects/MoFin")
ACCURACY_PATH = PROJECT_DIR / "data" / "accuracy_stats.json"
def _load_json(path, default=None):
try:
with open(path, encoding="utf-8") as f:
return json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
return {} if default is None else default
def _load_decisions():
"""从 DB 读取 decisions 数据"""
try:
from mo_data import read_decisions
return read_decisions()
except Exception:
return {"decisions": []}
def analyze_prompt_version_effectiveness() -> dict:
"""按提示词版本聚合策略评估结果
关联 DB holding_strategies 中的 evaluation 字段和 associations.json 中的版本记录,
计算出每个提示词版本的:
- 生成的策略总数
- 达到止盈数(成功)
- 跌破止损数(失败)
- 待验证数
- 盈亏比平均值
"""
# 加载数据
decisions = _load_decisions()
associations = load_associations().get("associations", [])
# 建立 code → 最新关联的映射
code_to_pv = {} # code -> {prompt_id, version}
for a in associations:
code = a.get("code")
if code and code not in code_to_pv:
code_to_pv[code] = {
"prompt_id": a.get("prompt_id"),
"version": a.get("prompt_version"),
}
# 按 prompt_id@version 分组统计
version_stats = {}
for d in decisions.get("decisions", []):
code = d.get("code")
if not code:
continue
pv = code_to_pv.get(code)
if not pv:
continue
key = f"{pv['prompt_id']}@{pv['version']}"
if key not in version_stats:
version_stats[key] = {
"prompt_id": pv["prompt_id"],
"version": pv["version"],
"total": 0,
"take_profit_hit": 0,
"stop_loss_hit": 0,
"in_entry_zone": 0,
"pending": 0,
"avg_rr": 0.0,
"rr_sum": 0.0,
"rr_count": 0,
"stocks": [],
}
vs = version_stats[key]
vs["total"] += 1
vs["stocks"].append(code)
# 从 evaluation 中读取状态
evals = d.get("evaluation", [])
for ev in evals:
if isinstance(ev, dict) and ev.get("phase") == 1:
theo = ev.get("theoretical", {})
status = theo.get("status", "")
if status == "take_profit_hit":
vs["take_profit_hit"] += 1
elif status == "stop_loss_hit":
vs["stop_loss_hit"] += 1
elif status == "in_entry_zone":
vs["in_entry_zone"] += 1
else:
vs["pending"] += 1
# 盈亏比
rr = d.get("rr_ratio")
if rr is not None and isinstance(rr, (int, float)):
vs["rr_sum"] += rr
vs["rr_count"] += 1
# 计算平均盈亏比和成功率
for key, vs in version_stats.items():
if vs["rr_count"] > 0:
vs["avg_rr"] = round(vs["rr_sum"] / vs["rr_count"], 2)
total_outcome = vs["take_profit_hit"] + vs["stop_loss_hit"]
if total_outcome > 0:
vs["success_rate"] = round(vs["take_profit_hit"] / total_outcome * 100, 1)
else:
vs["success_rate"] = None
del vs["rr_sum"]
return version_stats
def get_prompt_version_comparison() -> dict:
"""生成版本对比报告"""
version_stats = analyze_prompt_version_effectiveness()
# 补充每个版本的标签信息
for key, vs in version_stats.items():
prompt = get_prompt(vs["prompt_id"])
if prompt:
for v in prompt.versions:
if v.version == vs["version"]:
vs["label"] = v.label
vs["changelog"] = v.changelog
vs["tags"] = v.tags
break
if "label" not in vs:
vs["label"] = vs["version"]
return version_stats
def generate_report() -> str:
"""生成版本有效性报告文本"""
comparison = get_prompt_version_comparison()
lines = []
lines.append("📊 提示词版本有效性分析 | " + datetime.now().strftime("%Y-%m-%d"))
lines.append("")
if not comparison:
lines.append("暂无数据 — 请先运行策略生成和评估后重试")
return "\n".join(lines)
# 按 prompt_id 分组显示
by_prompt = {}
for key, vs in comparison.items():
pid = vs["prompt_id"]
by_prompt.setdefault(pid, []).append(vs)
for pid, versions in sorted(by_prompt.items()):
prompt = get_prompt(pid)
lines.append(f"\n## {prompt.name if prompt else pid}")
lines.append(f" {prompt.description if prompt else ''}")
lines.append("")
# 按版本号排序
versions.sort(key=lambda x: x["version"])
header = f" {'版本':<10} {'标签':<20} {'策略数':<8} {'止盈':<8} {'止损':<8} {'成功率':<10} {'平均R/R':<10}"
lines.append(header)
lines.append(" " + "-" * len(header))
for vs in versions:
sr = f"{vs['success_rate']}%" if vs['success_rate'] is not None else "-"
label = vs.get("label", "")[:18]
lines.append(
f" {vs['version']:<10} {label:<20} "
f"{vs['total']:<8} {vs['take_profit_hit']:<8} "
f"{vs['stop_loss_hit']:<8} {sr:<10} "
f"{vs['avg_rr']:<10}"
)
lines.append("")
lines.append("---")
lines.append("注:数据来自 DB holding_strategies evaluation + associations.json")
return "\n".join(lines)
+493 -493
View File
@@ -1,493 +1,493 @@
#!/usr/bin/env python3
"""初始化提示词注册表 — 录入所有现存提示词版本"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from prompt_manager.registry import add_prompt, add_version, list_prompts
from prompt_manager.models import PromptDef, PromptVersion
now = "2026-06-12T16:00:00" # 使用最近修改时间
# ═══════════════════════════════════════════
# 1. 策略生成规则 — 最核心的提示词
# ═══════════════════════════════════════════
strategy_gen = PromptDef(
id="strategy-generation",
name="策略生成规则",
description="用于生成买入区/止损/止盈的技术面策略规则集,嵌入 strategy_lifecycle.py 的 reassess_strategy() 函数",
category="strategy",
locations=[
"/home/hmo/web-dashboard/strategy_lifecycle.py",
"/home/hmo/projects/MoFin/src/strategy_lifecycle.py",
"finance/price-range-monitor SKILL.md",
],
versions=[],
created_at="2026-06-09T08:00:00",
updated_at=now,
current_version="v2.4",
)
add_prompt(strategy_gen)
# v1 — 初始机械百分比
add_version("strategy-generation", PromptVersion(
version="v1",
label="初始机械百分比",
created_at="2026-06-09T08:00:00",
changelog="初始版本,基于固定百分比(±5~10%)计算买入区/止损/止盈,无技术面支撑",
content="""策略生成规则 v1(初始机械百分比)
止损 = 成本 × 0.85-15%
止盈 = 成本 × 1.20+20%
买入区 = 现价 × 0.90 ~ 现价 × 1.05
无技术面分析,纯百分比计算。
""",
status="deprecated",
tags=["机械百分比"],
))
# v2 — 技术面支撑压力位 v1
add_version("strategy-generation", PromptVersion(
version="v2",
label="技术面支撑压力位 v1",
created_at="2026-06-11T10:00:00",
changelog="从机械百分比改为基于 technical_analysis.py 的支撑/压力位计算,止损放强支撑,止盈放强压力",
content="""策略生成规则 v2(技术面支撑压力位 v1)
1. 止损 = 强支撑(strong_support),约5-8%跌幅
2. 止盈 = 强压力(strong_resist
3. 买入区 = 弱支撑(ws) ~ 弱压力(wr)
4. 新买入/已持仓统一策略
5. 无R/R校验
""",
status="deprecated",
tags=["技术面", "支撑压力"],
))
# v2.1 — R/R 校验 + 最小波幅
add_version("strategy-generation", PromptVersion(
version="v2.1",
label="技术面 + R/R 校验",
created_at="2026-06-12T10:00:00",
changelog="新增R/R≥2.0校验+4%最小波幅保护。修复比亚迪A单日振幅±0.5%导致R/R=0.8的问题。R/R不满足时尝试多级阻力位上调止盈",
content="""策略生成规则 v2.1(技术面 + R/R 校验)
1. 止损 = 强支撑(新买入用弱支撑)
2. 止盈 = 强压力(多级阻力位尝试满足R/R)
3. 买入区 = 弱支撑~弱支撑×1.05
4. R/R ≥ 2.0 校验(新买入推荐)
5. 4% 最小波幅保护(单日振幅<2%时)
6. 盈亏比不满足时:弱压→强压 逐级尝试
""",
status="deprecated",
tags=["技术面", "R/R", "最小波幅"],
))
# v2.2 — 止损三级分离 + 移动止损
add_version("strategy-generation", PromptVersion(
version="v2.2",
label="止损三级分离 + 移动止损",
created_at="2026-06-13T10:00:00",
changelog="止损分三级(新买入/已持仓/深套)。新买入用弱支撑,已持仓用强支撑,深套取强撑/85%最低。盈利>5%启用移动止损保护利润",
content="""策略生成规则 v2.2(止损三级分离 + 移动止损)
| 场景 | 止损位置 | 逻辑 |
|------|---------|------|
| 新买入(cost=0) | 弱支撑(weak_support) | 入场失败小亏走人 |
| 已持仓(profit≥-20%) | 强支撑(strong_support) | 趋势坏了才走 |
| 深套(profit<-20%) | min(强支撑, 价×0.85) | 不轻易割 |
盈利>5%:取 max(弱支撑, 成本线, 现价×0.95) 移动止损
买入区 R/R 约束:新买入≥1.5,已持仓≥1.0
买入区宽度收紧:只围绕弱支撑,不扩展到弱压力
""",
status="deprecated",
tags=["技术面", "R/R", "移动止损", "三级止损"],
))
# v2.3 — 买入区 R/R 约束 + 买入时机模型
add_version("strategy-generation", PromptVersion(
version="v2.3",
label="买入区 R/R 约束 + 时机四象限",
created_at="2026-06-13T16:00:00",
changelog="买入区自身增加R/R约束(entry_high满足1:1.5),新增买入时机四象限模型(放量跌不入/缩量回踩入/放量突破追/缩量反弹不追),趋势位置检测扩展有效区间",
content="""策略生成规则 v2.3
买入区 R/R 约束:
- entry_high ≤ (target + min_rr × stop) / (1 + min_rr)
- 新买入 min_rr=1.5,已持仓 min_rr=1.0
- 坍缩保护:R/R约束导致买入区消失时标记"不建议"
买入时机四象限:
| 场景 | 操作 |
|------|------|
| ①放量跌入买入区 | ❌ 不买 |
| ②缩量回踩弱支撑+放量反弹 | ✅ 买入 |
| ③放量突破压力位 | ✅ 追买 |
| ④缩量反弹到压力位 | ❌ 警惕 |
趋势位置检测:股价>80%分位或<20%分位时自动扩展有效区间到价×8%
""",
status="deprecated",
tags=["技术面", "R/R", "买入时机", "趋势位置"],
))
# v2.4 — 当前版本(R/R阈值差异化 + 止损最小距离保护)
add_version("strategy-generation", PromptVersion(
version="v2.4",
label="R/R阈值差异化 + 止损最小距离",
created_at="2026-06-13T18:00:00",
changelog="R/R阈值差异化(新买入≥1.5/2.0/2.0三级,已持仓≥0.5/1.5两级),止损最小距离3%保护(正常持仓不被短线波动触发),买入区坍缩逻辑优化",
content="""策略生成规则 v2.4(当前活跃版本)
R/R阈值差异化:
| 场景 | 阈值 |
|------|------|
| 新买入 <1.5 | ❌ 不建议买入 |
| 新买入 1.5~2.0 | ⚠️ 谨慎买入 |
| 新买入 ≥2.0 | ✅ 正常 |
| 已持仓 <0.5 | ⚠️ 盈亏比极低 |
| 已持仓 0.5~1.5 | ⚠️ 不建议加仓 |
| 已持仓 ≥1.5 | ✅ 无标记 |
止损最小距离:现价到止损≥3%(非深套场景)
买入区坍缩:R/R约束导致entry_high<entry_low时,坍缩到[价×0.99, 价×1.01]
其他规则继承 v2.3。
""",
status="active",
tags=["技术面", "R/R阈值差异化", "止损最小距离"],
))
# ═══════════════════════════════════════════
# 2. 快速盯盘
# ═══════════════════════════════════════════
quick_scan = PromptDef(
id="quick-scan",
name="快速盯盘",
description="交易时段每15分钟跑一次的盘中行情监控报告 prompt",
category="scan",
locations=[
"cron job: 62a2ba59f7ff",
"finance/price-range-monitor SKILL.md",
],
versions=[],
created_at="2026-06-10T09:00:00",
updated_at=now,
current_version="v3",
)
add_prompt(quick_scan)
add_version("quick-scan", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-10T09:00:00",
changelog="初始版本,包含三段式报告格式",
content="快速盯盘 v1:三段式报告格式,每15分钟运行。包含重点推荐操作/风险关注/其余持仓。",
status="deprecated",
tags=["三段式"],
))
add_version("quick-scan", PromptVersion(
version="v2",
label="字数限制+数据纪律",
created_at="2026-06-11T10:00:00",
changelog="新增≤300字严格限制,要求查新闻原因(>±3%),禁止模糊词",
content="快速盯盘 v2:字数≤300字,涨跌>±3%必须查新闻,禁止模糊词(可关注/可考虑/建议观察)。",
status="deprecated",
tags=["字数限制", "数据纪律"],
))
add_version("quick-scan", PromptVersion(
version="v3",
label="买入时机+唯一动词",
created_at="2026-06-12T14:00:00",
changelog="新增买入时机四象限要求,每只推荐必须带唯一动作动词+数量+价格,仓位必写",
content="快速盯盘 v3(当前):三段式≤300字,每只推荐必须带唯一动作动词+数量+价格,仓位%必写,禁止选择题。买入时机四象限:放量跌不入/缩量回踩入/放量突破追/缩量反弹不追。",
status="active",
tags=["唯一动词", "买入时机"],
))
# ═══════════════════════════════════════════
# 3. 策略评估日报
# ═══════════════════════════════════════════
eval_daily = PromptDef(
id="evaluation-daily",
name="策略评估日报",
description="每日21:00自动运行的策略评估+反馈闭环 prompt",
category="evaluation",
locations=[
"cron job: 9d1236d8a07f",
"finance/strategy-evaluation SKILL.md",
],
versions=[],
created_at="2026-06-09T21:00:00",
updated_at=now,
current_version="v2",
)
add_prompt(eval_daily)
add_version("evaluation-daily", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-09T21:00:00",
changelog="初始版本,运行strategy_evaluator.py并输出评估报告",
content="策略评估 v1:运行评估脚本 → 读取 evaluation.json → 输出双维度评估报告。",
status="deprecated",
tags=["双维度评估"],
))
add_version("evaluation-daily", PromptVersion(
version="v2",
label="反馈闭环+信号识别",
created_at="2026-06-11T21:00:00",
changelog="新增反馈闭环机制:识别6种策略信号(买入区从未触发/频繁止损/价格远超止盈/理论实际差距/连续正确/连续错误),自动生成调整建议",
content="""策略评估 v2(当前):
1. 运行 strategy_evaluator.py
2. 读 evaluation.json + accuracy_stats.json
3. 识别6种信号并生成调整建议
4. 固化经验到 knowledge-log
5. 无变化输出 SILENT 抑制推送
""",
status="active",
tags=["反馈闭环", "信号识别"],
))
# ═══════════════════════════════════════════
# 4. 知识萃取
# ═══════════════════════════════════════════
knowledge = PromptDef(
id="knowledge-extraction",
name="知识萃取",
description="每日16:30从当日分析中提炼可复用知识,写入 analyst-knowledge-log.md",
category="knowledge",
locations=[
"cron job: e27e2e92ed80",
"finance/analyst-knowledge SKILL.md",
],
versions=[],
created_at="2026-06-11T16:30:00",
updated_at=now,
current_version="v1",
)
add_prompt(knowledge)
add_version("knowledge-extraction", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-11T16:30:00",
changelog="初始版本,从 decisions.json 和 evaluation.json 中提炼经验写入知识日志",
content="""知识萃取 v1(当前):
1. 读 decisions.json 的 changelog 和 evaluation
2. 读当天分析输出的 anomaly 信号
3. 提炼 1-3 条可复用知识
4. 写入 /home/hmo/Obsidian/knowledge/finance/analyst-knowledge-log.md
5. 长期有效的规律 → memory add
""",
status="active",
tags=["知识沉淀"],
))
# ═══════════════════════════════════════════
# 5. 持仓复查
# ═══════════════════════════════════════════
review = PromptDef(
id="portfolio-review",
name="持仓复查",
description="每周四20:00进行全面持仓基本面+技术面复查",
category="review",
locations=[
"cron job: 5dde4e1a42ce",
"finance/price-range-monitor SKILL.md",
],
versions=[],
created_at="2026-06-11T20:00:00",
updated_at=now,
current_version="v1",
)
add_prompt(review)
add_version("portfolio-review", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-11T20:00:00",
changelog="初始版本,逐个过所有持仓的营收/利润/PE/PB/ROE/技术面/研报/新闻",
content="""持仓复查 v1(当前):
1. 所有持仓个股逐个过:营收趋势、利润、利润率、PE/PB/ROE/负债率
2. 技术面:支撑位、压力位、均线形态
3. 最新研报目标价
4. 近期重大新闻/催化剂
5. 标记异常信号
""",
status="active",
tags=["全面复查"],
))
# ═══════════════════════════════════════════
# 6. 系统健康检查
# ═══════════════════════════════════════════
health = PromptDef(
id="system-health-check",
name="系统健康检查",
description="每日9:00检查MoFin所有核心组件是否正常运行",
category="health",
locations=[
"cron job: 37c02f4d7df9",
"cron job: 88d6753bde11",
"/home/hmo/web-dashboard/system_health_check.py",
],
versions=[],
created_at="2026-06-09T09:00:00",
updated_at=now,
current_version="v2",
)
add_prompt(health)
add_version("system-health-check", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-09T09:00:00",
changelog="初始版本,检查进程/端口/数据文件",
content="健康检查 v1:检查 mofin-dashboard/xmpp-zhiwei/ejabberd 进程,8899/5222/8643端口,数据文件存在性。",
status="deprecated",
tags=["进程", "端口"],
))
add_version("system-health-check", PromptVersion(
version="v2",
label="18项全面检查",
created_at="2026-06-10T09:00:00",
changelog="扩展为18项检查:进程+端口+数据文件+价格事件+策略评估+建议记录+cron jobs+数据新鲜度",
content="""健康检查 v2(当前):18项检查
- 进程:mofin-dashboard, xmpp-zhiwei, ejabberd
- 端口:8899, 5222, 8643
- 数据:portfolio/watchlist/decisions/market/price_events/evaluation/accuracy_stats
- 活动:价格事件数/策略评估数/建议记录数
- Cron: 两个profile
- 数据新鲜度:文件更新时间
""",
status="active",
tags=["18项检查"],
))
# ═══════════════════════════════════════════
# 7. 报告格式规范
# ═══════════════════════════════════════════
format_rules = PromptDef(
id="report-format",
name="报告格式规范",
description="所有分析报告的三段式输出格式规则,嵌入 price-range-monitor SKILL.md 和 cron 提示词",
category="format",
locations=[
"finance/price-range-monitor SKILL.md",
"finance/price-range-monitor/references/report-format-final-2026-06-10.md",
"/home/hmo/Obsidian/knowledge/finance/zhiwei-analysis-rules.md",
],
versions=[],
created_at="2026-06-10T14:00:00",
updated_at=now,
current_version="v3",
)
add_prompt(format_rules)
add_version("report-format", PromptVersion(
version="v1",
label="初始格式",
created_at="2026-06-10T14:00:00",
changelog="初始三段式格式:重点推荐操作(≤3)/风险关注(≤3)/其余持仓",
content="三段式 v1:【重点推荐操作】≤3只 / 【风险关注】≤3只 / 【其余持仓】一行概括",
status="deprecated",
tags=["三段式"],
))
add_version("report-format", PromptVersion(
version="v2",
label="字数限制+仓位必写",
created_at="2026-06-11T16:00:00",
changelog="新增≤800字限制,仓位%必写(现→建议),技术面四个数字必写,禁止模糊词",
content="三段式 v2:≤800字,仓位%必写,技术面四数字(强阻/弱阻/强撑/弱撑)必写,禁止模糊词/选择题。",
status="deprecated",
tags=["字数限制", "仓位"],
))
add_version("report-format", PromptVersion(
version="v3",
label="唯一动词+理由可验证",
created_at="2026-06-12T16:00:00",
changelog="每只推荐必须带唯一动作动词+数量+价格,理由必须可验证(用户原话:我要验证你是不是按我说的逻辑定策略)",
content="""三段式 v3(当前):
1. 【重点推荐操作】≤3只,理由不重复
2. 每只:仓位(现→建议) + 技术面四数字 + 操作(唯一动词+数量+价) + 可验证理由
3. 【风险关注】≤3只,距止损%+原因
4. 【其余持仓】一行带过
5. 全文≤600字
6. 禁止:可关注/可考虑/建议观察/择机/试试
7. A股在前港股在后
""",
status="active",
tags=["唯一动词", "理由可验证"],
))
# ═══════════════════════════════════════════
# 8. 分析规则
# ═══════════════════════════════════════════
analysis_rules = PromptDef(
id="analysis-rules",
name="分析规则",
description="单股/行业分析流程规则:数据源纪律、A+H股处理、异常处理、买入时机四象限",
category="analysis",
locations=[
"finance/price-range-monitor SKILL.md",
"/home/hmo/Obsidian/knowledge/finance/analysis-rules.md",
"/home/hmo/Obsidian/knowledge/finance/zhiwei-analysis-rules.md",
],
versions=[],
created_at="2026-06-09T10:00:00",
updated_at=now,
current_version="v2",
)
add_prompt(analysis_rules)
add_version("analysis-rules", PromptVersion(
version="v1",
label="初始规则",
created_at="2026-06-09T10:00:00",
changelog="初始分析规则:腾讯API数据源、港股字段映射、涨跌>3%查新闻",
content="分析规则 v1:腾讯API港股字段映射,涨跌>±3%必须查新闻,A+H股价差正常。",
status="deprecated",
tags=["数据源"],
))
add_version("analysis-rules", PromptVersion(
version="v2",
label="日期纪律+预检查清单",
created_at="2026-06-12T16:00:00",
changelog="新增日期铁律(分析前先date)、预分析自查清单(时间戳/交易日/策略数据)、A股优先于港股",
content="""分析规则 v2(当前):
1. 日期纪律:分析前先 date 确认日期星期
2. 数据源:腾讯API主(港股),新浪补充(A股昨收)
3. 预检查:时间戳→交易日→策略数据
4. A股优先于港股
5. 涨跌>±3%查新闻
6. A+H价差正常
7. 买入时机四象限
""",
status="active",
tags=["日期纪律", "预检查"],
))
print("✅ 提示词注册表初始化完成!")
print(f" 共注册 {len(list_prompts())} 个提示词")
for p in list_prompts():
print(f" - {p['id']}: {p['name']} ({len(p['versions'])} 个版本)")
#!/usr/bin/env python3
"""初始化提示词注册表 — 录入所有现存提示词版本"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from prompt_manager.registry import add_prompt, add_version, list_prompts
from prompt_manager.models import PromptDef, PromptVersion
now = "2026-06-12T16:00:00" # 使用最近修改时间
# ═══════════════════════════════════════════
# 1. 策略生成规则 — 最核心的提示词
# ═══════════════════════════════════════════
strategy_gen = PromptDef(
id="strategy-generation",
name="策略生成规则",
description="用于生成买入区/止损/止盈的技术面策略规则集,嵌入 strategy_lifecycle.py 的 reassess_strategy() 函数",
category="strategy",
locations=[
"/home/hmo/web-dashboard/strategy_lifecycle.py",
"/home/hmo/projects/MoFin/src/strategy_lifecycle.py",
"finance/price-range-monitor SKILL.md",
],
versions=[],
created_at="2026-06-09T08:00:00",
updated_at=now,
current_version="v2.4",
)
add_prompt(strategy_gen)
# v1 — 初始机械百分比
add_version("strategy-generation", PromptVersion(
version="v1",
label="初始机械百分比",
created_at="2026-06-09T08:00:00",
changelog="初始版本,基于固定百分比(±5~10%)计算买入区/止损/止盈,无技术面支撑",
content="""策略生成规则 v1(初始机械百分比)
止损 = 成本 × 0.85-15%
止盈 = 成本 × 1.20+20%
买入区 = 现价 × 0.90 ~ 现价 × 1.05
无技术面分析,纯百分比计算。
""",
status="deprecated",
tags=["机械百分比"],
))
# v2 — 技术面支撑压力位 v1
add_version("strategy-generation", PromptVersion(
version="v2",
label="技术面支撑压力位 v1",
created_at="2026-06-11T10:00:00",
changelog="从机械百分比改为基于 technical_analysis.py 的支撑/压力位计算,止损放强支撑,止盈放强压力",
content="""策略生成规则 v2(技术面支撑压力位 v1)
1. 止损 = 强支撑(strong_support),约5-8%跌幅
2. 止盈 = 强压力(strong_resist
3. 买入区 = 弱支撑(ws) ~ 弱压力(wr)
4. 新买入/已持仓统一策略
5. 无R/R校验
""",
status="deprecated",
tags=["技术面", "支撑压力"],
))
# v2.1 — R/R 校验 + 最小波幅
add_version("strategy-generation", PromptVersion(
version="v2.1",
label="技术面 + R/R 校验",
created_at="2026-06-12T10:00:00",
changelog="新增R/R≥2.0校验+4%最小波幅保护。修复比亚迪A单日振幅±0.5%导致R/R=0.8的问题。R/R不满足时尝试多级阻力位上调止盈",
content="""策略生成规则 v2.1(技术面 + R/R 校验)
1. 止损 = 强支撑(新买入用弱支撑)
2. 止盈 = 强压力(多级阻力位尝试满足R/R)
3. 买入区 = 弱支撑~弱支撑×1.05
4. R/R ≥ 2.0 校验(新买入推荐)
5. 4% 最小波幅保护(单日振幅<2%时)
6. 盈亏比不满足时:弱压→强压 逐级尝试
""",
status="deprecated",
tags=["技术面", "R/R", "最小波幅"],
))
# v2.2 — 止损三级分离 + 移动止损
add_version("strategy-generation", PromptVersion(
version="v2.2",
label="止损三级分离 + 移动止损",
created_at="2026-06-13T10:00:00",
changelog="止损分三级(新买入/已持仓/深套)。新买入用弱支撑,已持仓用强支撑,深套取强撑/85%最低。盈利>5%启用移动止损保护利润",
content="""策略生成规则 v2.2(止损三级分离 + 移动止损)
| 场景 | 止损位置 | 逻辑 |
|------|---------|------|
| 新买入(cost=0) | 弱支撑(weak_support) | 入场失败小亏走人 |
| 已持仓(profit≥-20%) | 强支撑(strong_support) | 趋势坏了才走 |
| 深套(profit<-20%) | min(强支撑, 价×0.85) | 不轻易割 |
盈利>5%:取 max(弱支撑, 成本线, 现价×0.95) 移动止损
买入区 R/R 约束:新买入≥1.5,已持仓≥1.0
买入区宽度收紧:只围绕弱支撑,不扩展到弱压力
""",
status="deprecated",
tags=["技术面", "R/R", "移动止损", "三级止损"],
))
# v2.3 — 买入区 R/R 约束 + 买入时机模型
add_version("strategy-generation", PromptVersion(
version="v2.3",
label="买入区 R/R 约束 + 时机四象限",
created_at="2026-06-13T16:00:00",
changelog="买入区自身增加R/R约束(entry_high满足1:1.5),新增买入时机四象限模型(放量跌不入/缩量回踩入/放量突破追/缩量反弹不追),趋势位置检测扩展有效区间",
content="""策略生成规则 v2.3
买入区 R/R 约束:
- entry_high ≤ (target + min_rr × stop) / (1 + min_rr)
- 新买入 min_rr=1.5,已持仓 min_rr=1.0
- 坍缩保护:R/R约束导致买入区消失时标记"不建议"
买入时机四象限:
| 场景 | 操作 |
|------|------|
| ①放量跌入买入区 | ❌ 不买 |
| ②缩量回踩弱支撑+放量反弹 | ✅ 买入 |
| ③放量突破压力位 | ✅ 追买 |
| ④缩量反弹到压力位 | ❌ 警惕 |
趋势位置检测:股价>80%分位或<20%分位时自动扩展有效区间到价×8%
""",
status="deprecated",
tags=["技术面", "R/R", "买入时机", "趋势位置"],
))
# v2.4 — 当前版本(R/R阈值差异化 + 止损最小距离保护)
add_version("strategy-generation", PromptVersion(
version="v2.4",
label="R/R阈值差异化 + 止损最小距离",
created_at="2026-06-13T18:00:00",
changelog="R/R阈值差异化(新买入≥1.5/2.0/2.0三级,已持仓≥0.5/1.5两级),止损最小距离3%保护(正常持仓不被短线波动触发),买入区坍缩逻辑优化",
content="""策略生成规则 v2.4(当前活跃版本)
R/R阈值差异化:
| 场景 | 阈值 |
|------|------|
| 新买入 <1.5 | ❌ 不建议买入 |
| 新买入 1.5~2.0 | ⚠️ 谨慎买入 |
| 新买入 ≥2.0 | ✅ 正常 |
| 已持仓 <0.5 | ⚠️ 盈亏比极低 |
| 已持仓 0.5~1.5 | ⚠️ 不建议加仓 |
| 已持仓 ≥1.5 | ✅ 无标记 |
止损最小距离:现价到止损≥3%(非深套场景)
买入区坍缩:R/R约束导致entry_high<entry_low时,坍缩到[价×0.99, 价×1.01]
其他规则继承 v2.3。
""",
status="active",
tags=["技术面", "R/R阈值差异化", "止损最小距离"],
))
# ═══════════════════════════════════════════
# 2. 快速盯盘
# ═══════════════════════════════════════════
quick_scan = PromptDef(
id="quick-scan",
name="快速盯盘",
description="交易时段每15分钟跑一次的盘中行情监控报告 prompt",
category="scan",
locations=[
"cron job: 62a2ba59f7ff",
"finance/price-range-monitor SKILL.md",
],
versions=[],
created_at="2026-06-10T09:00:00",
updated_at=now,
current_version="v3",
)
add_prompt(quick_scan)
add_version("quick-scan", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-10T09:00:00",
changelog="初始版本,包含三段式报告格式",
content="快速盯盘 v1:三段式报告格式,每15分钟运行。包含重点推荐操作/风险关注/其余持仓。",
status="deprecated",
tags=["三段式"],
))
add_version("quick-scan", PromptVersion(
version="v2",
label="字数限制+数据纪律",
created_at="2026-06-11T10:00:00",
changelog="新增≤300字严格限制,要求查新闻原因(>±3%),禁止模糊词",
content="快速盯盘 v2:字数≤300字,涨跌>±3%必须查新闻,禁止模糊词(可关注/可考虑/建议观察)。",
status="deprecated",
tags=["字数限制", "数据纪律"],
))
add_version("quick-scan", PromptVersion(
version="v3",
label="买入时机+唯一动词",
created_at="2026-06-12T14:00:00",
changelog="新增买入时机四象限要求,每只推荐必须带唯一动作动词+数量+价格,仓位必写",
content="快速盯盘 v3(当前):三段式≤300字,每只推荐必须带唯一动作动词+数量+价格,仓位%必写,禁止选择题。买入时机四象限:放量跌不入/缩量回踩入/放量突破追/缩量反弹不追。",
status="active",
tags=["唯一动词", "买入时机"],
))
# ═══════════════════════════════════════════
# 3. 策略评估日报
# ═══════════════════════════════════════════
eval_daily = PromptDef(
id="evaluation-daily",
name="策略评估日报",
description="每日21:00自动运行的策略评估+反馈闭环 prompt",
category="evaluation",
locations=[
"cron job: 9d1236d8a07f",
"finance/strategy-evaluation SKILL.md",
],
versions=[],
created_at="2026-06-09T21:00:00",
updated_at=now,
current_version="v2",
)
add_prompt(eval_daily)
add_version("evaluation-daily", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-09T21:00:00",
changelog="初始版本,运行strategy_evaluator.py并输出评估报告",
content="策略评估 v1:运行评估脚本 → 读取 evaluation.json → 输出双维度评估报告。",
status="deprecated",
tags=["双维度评估"],
))
add_version("evaluation-daily", PromptVersion(
version="v2",
label="反馈闭环+信号识别",
created_at="2026-06-11T21:00:00",
changelog="新增反馈闭环机制:识别6种策略信号(买入区从未触发/频繁止损/价格远超止盈/理论实际差距/连续正确/连续错误),自动生成调整建议",
content="""策略评估 v2(当前):
1. 运行 strategy_evaluator.py
2. 读 evaluation.json + accuracy_stats.json
3. 识别6种信号并生成调整建议
4. 固化经验到 knowledge-log
5. 无变化输出 SILENT 抑制推送
""",
status="active",
tags=["反馈闭环", "信号识别"],
))
# ═══════════════════════════════════════════
# 4. 知识萃取
# ═══════════════════════════════════════════
knowledge = PromptDef(
id="knowledge-extraction",
name="知识萃取",
description="每日16:30从当日分析中提炼可复用知识,写入 analyst-knowledge-log.md",
category="knowledge",
locations=[
"cron job: e27e2e92ed80",
"finance/analyst-knowledge SKILL.md",
],
versions=[],
created_at="2026-06-11T16:30:00",
updated_at=now,
current_version="v1",
)
add_prompt(knowledge)
add_version("knowledge-extraction", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-11T16:30:00",
changelog="初始版本,从 DB holding_strategies 表中提炼经验写入知识日志",
content="""知识萃取 v1(当前):
1. 从 DB holding_strategies 表读取 changelog 和 evaluation 字段
2. 读当天分析输出的 anomaly 信号
3. 提炼 1-3 条可复用知识
4. 写入 /home/hmo/Obsidian/knowledge/finance/analyst-knowledge-log.md
5. 长期有效的规律 → memory add
""",
status="active",
tags=["知识沉淀"],
))
# ═══════════════════════════════════════════
# 5. 持仓复查
# ═══════════════════════════════════════════
review = PromptDef(
id="portfolio-review",
name="持仓复查",
description="每周四20:00进行全面持仓基本面+技术面复查",
category="review",
locations=[
"cron job: 5dde4e1a42ce",
"finance/price-range-monitor SKILL.md",
],
versions=[],
created_at="2026-06-11T20:00:00",
updated_at=now,
current_version="v1",
)
add_prompt(review)
add_version("portfolio-review", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-11T20:00:00",
changelog="初始版本,逐个过所有持仓的营收/利润/PE/PB/ROE/技术面/研报/新闻",
content="""持仓复查 v1(当前):
1. 所有持仓个股逐个过:营收趋势、利润、利润率、PE/PB/ROE/负债率
2. 技术面:支撑位、压力位、均线形态
3. 最新研报目标价
4. 近期重大新闻/催化剂
5. 标记异常信号
""",
status="active",
tags=["全面复查"],
))
# ═══════════════════════════════════════════
# 6. 系统健康检查
# ═══════════════════════════════════════════
health = PromptDef(
id="system-health-check",
name="系统健康检查",
description="每日9:00检查MoFin所有核心组件是否正常运行",
category="health",
locations=[
"cron job: 37c02f4d7df9",
"cron job: 88d6753bde11",
"/home/hmo/web-dashboard/system_health_check.py",
],
versions=[],
created_at="2026-06-09T09:00:00",
updated_at=now,
current_version="v2",
)
add_prompt(health)
add_version("system-health-check", PromptVersion(
version="v1",
label="初始版本",
created_at="2026-06-09T09:00:00",
changelog="初始版本,检查进程/端口/数据文件",
content="健康检查 v1:检查 mofin-dashboard/xmpp-zhiwei/ejabberd 进程,8899/5222/8643端口,数据文件存在性。",
status="deprecated",
tags=["进程", "端口"],
))
add_version("system-health-check", PromptVersion(
version="v2",
label="18项全面检查",
created_at="2026-06-10T09:00:00",
changelog="扩展为18项检查:进程+端口+数据文件+价格事件+策略评估+建议记录+cron jobs+数据新鲜度",
content="""健康检查 v2(当前):18项检查
- 进程:mofin-dashboard, xmpp-zhiwei, ejabberd
- 端口:8899, 5222, 8643
- 数据:holds/strategies/watchlist/market/events (全部DB)
- 活动:价格事件数/策略评估数/建议记录数
- Cron: 两个profile
- 数据新鲜度:文件更新时间
""",
status="active",
tags=["18项检查"],
))
# ═══════════════════════════════════════════
# 7. 报告格式规范
# ═══════════════════════════════════════════
format_rules = PromptDef(
id="report-format",
name="报告格式规范",
description="所有分析报告的三段式输出格式规则,嵌入 price-range-monitor SKILL.md 和 cron 提示词",
category="format",
locations=[
"finance/price-range-monitor SKILL.md",
"finance/price-range-monitor/references/report-format-final-2026-06-10.md",
"/home/hmo/Obsidian/knowledge/finance/zhiwei-analysis-rules.md",
],
versions=[],
created_at="2026-06-10T14:00:00",
updated_at=now,
current_version="v3",
)
add_prompt(format_rules)
add_version("report-format", PromptVersion(
version="v1",
label="初始格式",
created_at="2026-06-10T14:00:00",
changelog="初始三段式格式:重点推荐操作(≤3)/风险关注(≤3)/其余持仓",
content="三段式 v1:【重点推荐操作】≤3只 / 【风险关注】≤3只 / 【其余持仓】一行概括",
status="deprecated",
tags=["三段式"],
))
add_version("report-format", PromptVersion(
version="v2",
label="字数限制+仓位必写",
created_at="2026-06-11T16:00:00",
changelog="新增≤800字限制,仓位%必写(现→建议),技术面四个数字必写,禁止模糊词",
content="三段式 v2:≤800字,仓位%必写,技术面四数字(强阻/弱阻/强撑/弱撑)必写,禁止模糊词/选择题。",
status="deprecated",
tags=["字数限制", "仓位"],
))
add_version("report-format", PromptVersion(
version="v3",
label="唯一动词+理由可验证",
created_at="2026-06-12T16:00:00",
changelog="每只推荐必须带唯一动作动词+数量+价格,理由必须可验证(用户原话:我要验证你是不是按我说的逻辑定策略)",
content="""三段式 v3(当前):
1. 【重点推荐操作】≤3只,理由不重复
2. 每只:仓位(现→建议) + 技术面四数字 + 操作(唯一动词+数量+价) + 可验证理由
3. 【风险关注】≤3只,距止损%+原因
4. 【其余持仓】一行带过
5. 全文≤600字
6. 禁止:可关注/可考虑/建议观察/择机/试试
7. A股在前港股在后
""",
status="active",
tags=["唯一动词", "理由可验证"],
))
# ═══════════════════════════════════════════
# 8. 分析规则
# ═══════════════════════════════════════════
analysis_rules = PromptDef(
id="analysis-rules",
name="分析规则",
description="单股/行业分析流程规则:数据源纪律、A+H股处理、异常处理、买入时机四象限",
category="analysis",
locations=[
"finance/price-range-monitor SKILL.md",
"/home/hmo/Obsidian/knowledge/finance/analysis-rules.md",
"/home/hmo/Obsidian/knowledge/finance/zhiwei-analysis-rules.md",
],
versions=[],
created_at="2026-06-09T10:00:00",
updated_at=now,
current_version="v2",
)
add_prompt(analysis_rules)
add_version("analysis-rules", PromptVersion(
version="v1",
label="初始规则",
created_at="2026-06-09T10:00:00",
changelog="初始分析规则:腾讯API数据源、港股字段映射、涨跌>3%查新闻",
content="分析规则 v1:腾讯API港股字段映射,涨跌>±3%必须查新闻,A+H股价差正常。",
status="deprecated",
tags=["数据源"],
))
add_version("analysis-rules", PromptVersion(
version="v2",
label="日期纪律+预检查清单",
created_at="2026-06-12T16:00:00",
changelog="新增日期铁律(分析前先date)、预分析自查清单(时间戳/交易日/策略数据)、A股优先于港股",
content="""分析规则 v2(当前):
1. 日期纪律:分析前先 date 确认日期星期
2. 数据源:腾讯API主(港股),新浪补充(A股昨收)
3. 预检查:时间戳→交易日→策略数据
4. A股优先于港股
5. 涨跌>±3%查新闻
6. A+H价差正常
7. 买入时机四象限
""",
status="active",
tags=["日期纪律", "预检查"],
))
print("✅ 提示词注册表初始化完成!")
print(f" 共注册 {len(list_prompts())} 个提示词")
for p in list_prompts():
print(f" - {p['id']}: {p['name']} ({len(p['versions'])} 个版本)")