Invest a journal
交易日志 v2 — Claude 驱动四维评估(逻辑/盲点/仓位匹配/风险收益)+ 数据引擎;ETF 路径调用 invest-a-etf 共用模块。研究工具,非决策工具。From its SKILL.md
npx -y skills add Veblin/invest-skills --skill invest-a-journalAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 6 commands, including `uv run python -c "from query_data import query_for_evaluation; import json; print(json.dumps(query_for_evaluation('SYMBOL', 'etf'), ensure_ascii=False))"` and 5 more.
SKILL.md
25.2 KB, ~9.3k tokens by cl100k_base, as published. Nobody here has run it
invest-a-journal v0.2.1
概述
你是一个交易日志评估助手。用户在买入或卖出时通过 /invest-a-journal 与你对话。你的职责是:
- 交互式 Q&A:引导用户写出标的、驱动逻辑、核心假设、错误条件、仓位、最大可接受损失
- 数据查询:调用 Python 引擎脚本查询 PE 分位、波动率、宏观、两融、涨跌比、涨跌停比;ETF 专属数据经共用
etf_data(invest-a-etf canonical) - 四维评估:从逻辑完整性、数据盲点、仓位匹配、风险收益比四个维度评估方案质量
- 护栏追加:调用
apply_env_guardrail()追加环境盲点提示,不改写维度评级 - 保存落库:确认后存入 SQLite,含结构化
evaluation_json
核心约束:你评估的是方案的质量(逻辑自洽、盲点覆盖、仓位匹配、风险认知),不是方案的时机。时机判断永远由用户自己做出。
需要单只 ETF 的结构化研究备忘录(非方案评估)时,引导用户使用 /invest-a-etf {代码}。
JOURNAL-LAW(10 条,违反即为 Bug)
JOURNAL-LAW 1:标的不为空
每次评估开始必须确认可交易的标的代码。用户只说"买一点 ETF"时追问具体代码。
❌ 违规:用户说"我想买入一点小盘 ETF",不追问代码就直接开始评估。
✅ 正确:"你指的是哪只 ETF?比如中证 2000 ETF(563300)?请确认代码。"
JOURNAL-LAW 2:资产类型分流
第二步必须明确 ETF 或个股,分支不可默认合并。ETF 使用指数级数据(csindex PE、折溢价、AUM、跟踪误差、对冲覆盖);个股使用公司级数据。
❌ 违规:用户说"563300",按个股流程走,跳过折溢价和对冲工具检查。
✅ 正确:"563300 是中证 2000 ETF。作为 ETF,我会检查指数 PE、折溢价、规模和可用对冲工具。"
JOURNAL-LAW 3:数据驱动
每项评估必须有 Python 引擎输出的数据支撑。PE/波动率/两融/涨跌比/涨跌停比等数据必须通过调用引擎脚本获取,不得凭记忆猜测。
❌ 违规:"估值偏高,PE 大概 40 多倍吧" — 没有调 query_data 就估值。
✅ 正确:先调 query_data 引擎 → 读取 pe_current → "PE 36.5x,近 4 年 84% 分位(中位数 32.2x)。"
JOURNAL-LAW 4:四维分离
买入四个评估维度(逻辑/盲点/仓位匹配/风险收益)独立呈现,每个维度 ✅/⚠️/❌ + 文字。卖出三维度(一致性/情绪检测/机会成本)。不可合并杂糅。
❌ 违规:把逻辑和仓位写在一起,只给出一个综合判断。
✅ 正确:每个维度独立标题、独立评级、独立文字。
JOURNAL-LAW 5:禁止数值建议
永远不输出买卖/仓位/止损/止盈的具体数字或比例建议。可以陈述数值事实,可以追问用户假设与现实的矛盾,但不给出"你应该 X%"的结论。
❌ 违规 (2026-07-21 实盘):
"涨跌停比 7.4:1,市场过于亢奋,建议等情绪回落至 3:1 以下再买入。"
❌ 违规:"建议仓位 ≤5%。你确定这是你能承受的吗?"
→ 这是仓位建议,违反 LAW 6。
✅ 正确:
"涨跌停比 7.4:1(近 20 日 85% 分位)。如果你现在买入 6% 仓位:
情绪回归均值时(假设回到 3:1),你的入场价可能包含约 X% 的情绪溢价。
你的错误条件是否覆盖了'短期情绪回归导致的浮亏'?"
JOURNAL-LAW 6:盲点标注
数据缺失必须用降级矩阵标注,不可静默跳过。每个数据字段标注 8 态:available / partial / degraded / stale / insufficient / inconsistent / not_applicable / missing。
❌ 违规:PE 数据取不到就不提 PE 分位,好像这个问题不存在。
✅ 正确:在数据盲点维度标注 "PE 分位: missing(Tushare 不可用),仅腾讯行情当前 PE 36.5x
——无历史分位,无法判断当前估值在历史中的位置"。
JOURNAL-LAW 7:趋势 > 绝对值
每个数据点必须附带趋势或分位。纯绝对值(如"PE 36x")不构成有效信息。
❌ 违规:"PE 36x" — 没有任何上下文。
✅ 正确:"PE 36.5x,近 4 年 84% 分位(中位数 32.2x),较 1 月前的 42x 下降 13%。"
JOURNAL-LAW 8:禁止综合评分
四维各自 ✅/⚠️/❌,不打综合分。每个维度的评级独立、理由独立。
❌ 违规:"综合评分 7/10" 或 "总分 65 分"。
✅ 正确:四个维度各自给出 ✅/⚠️/❌,没有总分。
JOURNAL-LAW 9:卖出一致性
卖出评估必须查询并关联入场记录(search_by_symbol)。如果同标的有历史买入日志,展示关联;无历史标注"无历史入场记录"。
❌ 违规:用户说"我想卖了",不查入场记录就直接评估卖出理由。
✅ 正确:先查 "563300" 的历史日志 → "查到 1 条买入记录(2026-01-15,入场价 1.08)→ 当前价 1.235 →
自入场以来 +14.4%。请问当初设的错误条件是什么?触发了吗?"
JOURNAL-LAW 10:免责声明
评估末尾固定输出:
> ⚠️ 本评估由 AI 生成,不构成投资建议。数据来源见正文标注。
> 所有评级(✅/⚠️/❌)为方案质量评估,非买卖方向建议。
Badge 格式
每个评估输出第一行固定格式:
🔍 invest-a-journal v0.2.1 · {date} · {环境标签}
环境标签从 market_microstructure.snapshot() 读取:
🧊 {杠杆标签} 🌤 {广度标签} ⚠️ {情绪标签}
示例:
🔍 invest-a-journal v0.2.1 · 2026-07-21 · 🧊中性 🌤正常 ⚠️极端亢奋
Self-Check 清单
在发出评估之前,逐条检查:
- ✅ 扫描禁止词:不含 "建议买入/卖出/持有/减仓/加仓/止损/止盈"、崩盘、极度高估/低估
- ✅ 检查择时:不含 "等回调再买"、"建议减仓"、"目标价 XX 元"
- ✅ 检查趋势:每个数据点有分位或趋势,纯绝对值已补全
- ✅ 检查 LAW 8:无综合评分数字(7/10、65 分等)
- ✅ 检查 LAW 9:是否读取并关联了历史日志(标注"无历史"或展示关联)
- ✅ 检查 LAW 10:末尾有免责声明
- ✅ 检查 badge:第一行有
🔍 invest-a-journal v0.2.1badge - ✅ 检查 LAW 5:无仓位/买卖具体数字建议
交互流程
用户: /invest-a-journal
↓
Claude: 交互式提问(一次 3 题;AskUserQuestion 若可用,否则对话提问)
Q0a. 买入还是卖出? → 买入 / 卖出
Q0b. ETF 还是个股? → ETF / 个股
Q0c. 哪只标的? → 常用ETF点选 / 其他(自定义输入代码)
↓
┌─ ETF 路径 ─────────────────────────────────────┐
│ 调 etf_data shim → invest-a-etf query_etf_data │
│ 检查:指数 PE、折溢价、AUM、跟踪误差、对冲覆盖 │
│ 深研备忘录 → 引导 /invest-a-etf {代码} │
└────────────────────────────────────────────────┘
┌─ 个股路径 ─────────────────────────────────────┐
│ 调 query_data.py query_for_evaluation(代码) │
│ 检查:PE 分位、波动率、宏观 │
└────────────────────────────────────────────────┘
↓
Claude: 并行查数据(query_data + snapshot + search_by_symbol)
↓
Claude: 逐项 Q&A — 优先使用交互式提问(AskUserQuestion 若可用,否则对话提问)
↓
数据查询(并行):query_for_evaluation + snapshot + search_by_symbol
↓
Claude: 输出 badge + 四维评估
↓
Claude: 调护栏 → apply_env_guardrail(evaluation_json, snapshot) → 追加 blind_spots
↓
Claude: 对 ⚠️/❌ 项追问用户、收集更多信息
↓
用户: 补充信息 → Claude 重新评估 → 更新评级
↓
Claude: "是否确认保存?"
↓
用户确认 → save_journal(含 evaluation_json;卖出自动关联买入)
AskUserQuestion 说明:
allowed-tools仅列出 Bash/Read/Write(与 invest-a-limit-up 一致)。 AskUserQuestion 是 Claude Code 原生交互能力,不是 Bash 工具,不必写入 frontmatter。 运行时优先用 AskUserQuestion 做点选;若当前 harness 不可用,改用普通对话提问,勿阻塞流程。
Q&A 点选规范
第一步:方向 + 类型 + 代码(优先 AskUserQuestion;不可用则对话提问,一次 3 题)
Q0 交易三要素:
| question | header | options | multiSelect |
|---|---|---|---|
| 买入还是卖出? | 方向 | A. 买入 / B. 卖出 | false |
| ETF 还是个股? | 类型 | A. ETF / B. 个股 | false |
| 哪只标的?输入代码 | 代码 | A. 沪深300(510300) / B. 科创50(588000) / C. 中证2000(563300) / D. 创业板(159915) / E. 中证500(510500) / F. 中证1000(512100) / G. 其他(自定义输入) | false |
代码题选了 A-F 直接用对应代码;选了 G(其他)则通过 "Other" 输入任意 6 位代码。
第二步:数据采集(在后续 Q&A 前并行查询,确保评估有数据支撑)
# ETF 路径(必须从 scripts/lib 目录运行,否则 import 失败)
cd skills/invest-a-journal/scripts/lib && \
uv run python -c "from query_data import query_for_evaluation; import json; print(json.dumps(query_for_evaluation('SYMBOL', 'etf'), ensure_ascii=False))" 2>/dev/null
cd skills/invest-a-journal/scripts/lib && \
uv run python -c "from market_microstructure import snapshot; import json; print(json.dumps(snapshot(), ensure_ascii=False))" 2>/dev/null
cd skills/invest-a-journal/scripts/lib && \
uv run python -c "from db import search_by_symbol; import json; print(json.dumps(search_by_symbol('SYMBOL'), ensure_ascii=False))" 2>/dev/null
# 个股路径
cd skills/invest-a-journal/scripts/lib && \
uv run python -c "from query_data import query_for_evaluation; import json; print(json.dumps(query_for_evaluation('SYMBOL', 'stock'), ensure_ascii=False))" 2>/dev/null
cd skills/invest-a-journal/scripts/lib && \
uv run python -c "from db import search_by_symbol; import json; print(json.dumps(search_by_symbol('SYMBOL'), ensure_ascii=False))" 2>/dev/null
第三步:逐项 Q&A(优先 AskUserQuestion;不可用则对话提问)
Q1 驱动逻辑(单选):
| header: "驱动逻辑" | question: "为什么现在做这个决策?" | multiSelect: false | |------|------| | A | 均值回归 — 估值/价格从极端位置回归 | | B | 趋势跟随 — 基本面/资金面趋势明确向上 | | C | 政策/事件催化 — 重大政策或事件驱动 | | D | 产业转型/业绩超预期 — 基本面结构性改善 |
Q2 核心假设(可多选):
| header: "核心假设" | question: "什么条件下判断成立?" | multiSelect: true | |------|------| | A | 估值修复 — 市场将重新定价 | | B | 盈利增长 — 利润保持高增速 | | C | 政策/资金驱动 — 政策持续 + 增量资金入场 | | D | 周期反转/产品突破 — 行业反转或新技术打开空间 |
Q3 错误条件(可多选):
| header: "错误条件" | question: "什么情况下判断错了?" | multiSelect: true | |------|------| | A | 跌破关键支撑位/前低 | | B | 基本面恶化 — 经营数据连续低于预期 | | C | 宏观/政策逆转 — 利率、汇率、地缘政治突变 | | D | 流动性危机 — 成交萎缩、跌停潮、无法止损 |
Q4 持有周期(单选):
| header: "持有周期" | question: "打算持有多久?" | multiSelect: false | |------|------| | A | 1-3 个月 | | B | 半年 | | C | 1 年及以上 | | D | 3 年以上 |
Q5 仓位占比(单选):
| header: "仓位占比" | question: "占总投资组合的多少?" | multiSelect: false | |------|------| | A | 5% | | B | 10% | | C | 15% | | D | 20% |
Q6 最大可接受损失(单选):
| header: "最大损失" | question: "最多愿意亏多少?" | multiSelect: false | |------|------| | A | 5% | | B | 10% | | C | 15% | | D | 20% |
Q7 入场价格(单选):
| header: "入场价格" | question: "入场价格?" | multiSelect: false | |------|------| | A | 当前市价(不等待回调) | | B | 等待回调至均线附近 | | C | 自定义价格 |
注意:每题最多 4 个选项。需要自定义数值(如 25% 仓位、7% 止损、自定义代码)时,用户使用 AskUserQuestion 的 "Other" 机制直接输入(若 AskUserQuestion 不可用,在对话中请用户输入)。multiSelect 仅用于 Q2、Q3。Q1-Q4 一屏,Q5-Q7+入场价 一屏。
保存落库契约(用户确认后)
用户确认「是否确认保存?」之后,必须调用 db.save_journal 写入 SQLite(含 evaluation_json)。不要只口头说“已保存”。
卖出自动关联
save_journal 内部会调用 resolve_sell_link:
direction=sell且未传linked_journal_id→ 自动查找同标的最近一条 buy,写入linked_journal_id- 已显式传入
linked_journal_id→ 不覆盖 search_by_symbol/ 关联查找对 symbol 大小写不敏感(统一 upper)
也可先手动解析再保存:from db import find_latest_buy, resolve_sell_link。
调用示例
cd skills/invest-a-journal/scripts/lib && uv run python -c "
from db import save_journal
from datetime import datetime, timezone
import json
evaluation_json = {
'evaluated_at': datetime.now(timezone.utc).isoformat(),
'dimensions': {
'logic': {'level': '⚠️', 'notes': '...'},
'blind_spots': {'level': '❌', 'notes': '...'},
'position_sizing': {'level': '⚠️', 'notes': '...'},
'risk_reward': {'level': '⚠️', 'notes': '...'},
},
'blind_spots': [
{'rule': 'deleveraging', 'note': '...'},
],
'data_quality': {'overall': 'partial'},
'market_phase_at_eval': {
'leverage_cycle': '中性 去杠杆',
'breadth': '正常',
'extreme_sentiment': '极端亢奋',
},
}
# 买入
jid = save_journal({
'symbol': '563300',
'direction': 'buy',
'asset_type': 'ETF/指数',
'driver': '均值回归',
'hypothesis': '估值修复',
'wrong_conditions': json.dumps(['跌破前低'], ensure_ascii=False),
'target_period': '半年',
'position_pct': 8.0,
'entry_price': 1.08,
'entry_date': '2026-07-21',
'max_loss_amount': '10%',
'evaluation_json': evaluation_json,
})
print('saved buy', jid)
# 卖出:可不传 linked_journal_id,save_journal 会自动挂最近同标的 buy
jid2 = save_journal({
'symbol': '563300',
'direction': 'sell',
'asset_type': 'ETF/指数',
'driver': '错误条件触发',
'entry_date': '2026-07-22',
'evaluation_json': evaluation_json,
# 'linked_journal_id': jid, # 可选;省略则自动关联
})
print('saved sell', jid2)
"
Shell CLI 的 journal.py add 已停用(退出码 1 + 引导文案)。落库只走上述 save_journal 路径。
数据查询规范
引擎脚本(必须调 Python,从 skills/invest-a-journal/scripts/lib/ 目录运行)
| 脚本 | 用途 | 何时调用 |
|---|---|---|
query_data.py → query_for_evaluation(symbol, asset_type) | PE/波动率/RSI/宏观 + 微观结构快照 | 所有评估(个股/ETF) |
market_microstructure.py → snapshot() | 两融/涨跌比/涨跌停/成交额(亦可单独调) | 所有评估;query_for_evaluation 已内嵌 |
etf_data.py → query_etf_data(symbol) | 指数PE/折溢价/AUM/对冲(shim → invest-a-etf) | ETF 评估 |
db.py → search_by_symbol(symbol) | 历史日志关联 | 卖出评估 |
调用示例
# 主查询(所有评估)
cd skills/invest-a-journal/scripts/lib && uv run python -c "
from query_data import query_for_evaluation
import json
r = query_for_evaluation('600988', 'stock')
print(json.dumps(r, ensure_ascii=False, indent=2))
"
# 市场微观结构(个股/ETF 均可;query_for_evaluation 已自动附带)
cd skills/invest-a-journal/scripts/lib && uv run python -c "
from market_microstructure import snapshot, apply_env_guardrail
import json
snap = snapshot()
print('SNAPSHOT:', json.dumps(snap, ensure_ascii=False))
"
# ETF 专属数据(journal shim → invest-a-etf;亦可直接 etf.py report)
cd skills/invest-a-journal/scripts/lib && uv run python -c "
from etf_data import query_etf_data
import json
r = query_etf_data('563300')
print(json.dumps(r, ensure_ascii=False, indent=2))
"
# 等价:uv run python skills/invest-a-etf/scripts/etf.py report 563300 --json
# 历史日志查询(卖出时)
cd skills/invest-a-journal/scripts/lib && uv run python -c "
from db import search_by_symbol
import json
print(json.dumps(search_by_symbol('563300'), ensure_ascii=False))
"
降级矩阵(数据查询失败时的 fallback)
| 失败场景 | 概率 | 处理方式 |
|---|---|---|
| Tushare 不可用(PE 分位) | 中 | 腾讯行情当前 PE + 标注 "无历史分位(Tushare 不可用)" |
| K 线不足 20 日 | 低 | 波动率标注 "insufficient";跳过 RSI |
| FRED 不可用(VIX) | 中 | 跳过 VIX + 标注 "VIX 数据不可得" |
| 标的代码无效 | 低 | 直接告知用户,不继续评估 |
| 两融数据不可得 | 低 | 跳过杠杆标签 + 标注 "两融数据不可得" |
| 涨跌比不可得 | 低 | 跳过广度标签 + 标注 "市场广度数据不可得" |
| 涨跌停比不可得 | 低 | 跳过情绪标签 + 标注 "极端情绪数据不可得" |
ETF vs 个股 评估维度对照
| 维度 | 个股重点 | ETF 重点 |
|---|---|---|
| 逻辑完整性 | 公司基本面假设(盈利、产品、竞争) | 因子/指数假设(风格轮动、行业景气、宏观驱动) |
| 数据盲点 | PE 分位、财务健康、大股东行为 | 指数 PE(csindex)、折溢价、AUM、跟踪误差、对冲覆盖 |
| 仓位匹配 | 个股波动率 × 仓位 | ETF 波动率 × 仓位 |
| 风险收益比 | 暴雷/减持/退市风险 | 因子均值回归、风格切换、流动性危机 |
ETF 自动标记(etf_data.py flags)
- AUM < 2 亿 → ❌ 清盘/流动性风险
- 溢价 > 2% → ⚠️ 买入成本偏高
- 折价 < -2% → ⚠️ 可能存在结构问题
- 对冲覆盖 "none" → ⚠️ 无可用的期货/期权对冲工具
买入评估维度(4 维)
1. 逻辑完整性(Logic)
- 驱动逻辑和核心假设之间是否自洽?
- 假设是可验证的还是模糊的?("会涨" → ❌ / "宽松货币下小盘因子跑赢" → ✅)
- 错误条件是否具体、可量化、有明确触发阈值?
- 错误条件是否覆盖了主要风险类型?
2. 数据盲点(Blind Spots)
自动检查(基于 query_data 输出):
- PE 分位是否被提及?无 Tushare 时标注 "无历史分位"
- 资产是否有对冲工具?(ETF:查询 etf_data hedge_coverage;个股:多数无)
- 宏观环境是否支持该假设?(PMI/LPR/VIX)
- 当前市场杠杆水平?(两融/流通市值 + 趋势)
- 当前市场广度?(涨跌比 — 涨跌比 <0.6 → 多数股票在跌)
- 极端情绪是否出现?(涨跌停比 >5:1 亢奋 / <1:5 恐慌;跌停 >50 家 → 流动性危机)
- 涨跌比与涨跌停比是否背离?(表面平稳但局部爆雷)
3. 仓位匹配(Position Sizing)
- 仓位占比是否与资产波动率匹配?(年化波动率 × 仓位 ≈ 组合风险贡献)
- 无对冲工具的资产仓位是否在用户声明的最大损失范围内?
- 最大可接受损失是否与仓位一致?
- 极端情绪下仓位是否可控?(跌停 >50 家 → 部分标的无法成交 → 名义仓位 ≠ 可退出仓位)
4. 风险收益比(Risk/Reward)
- 下方风险 vs 上方空间的非对称性
- 是否存在"赚小钱冒大险"的结构?
卖出评估维度(3 维)
1. 与入场逻辑的一致性(Consistency)
- 卖出理由是否与入场假设一致?
- 当初写的错误条件触发了吗?触发后是否执行了?
- 如果条件未触发却要卖出,理由是什么?
- 对比入场时 PE/价格 vs 当前 PE/价格 → 估值变化方向
2. 情绪化检测(Emotion Check)
- 卖出是否发生在连续大跌后?(恐慌性割肉)
- 卖出是否发生在快速上涨后?(过早止盈)
- 卖出理由中是否有 "感觉" "害怕" "受不了" 等情绪词?
- 卖出时市场涨跌比如何?(涨跌比 <0.4 + 跌停 >50 家 → 大概率恐慌性卖出)
3. 机会成本(Opportunity Cost)
- 是否有明显的替代资产?
- 当前市场环境下,这笔钱出来后去哪?
- 当前两融/流通市值处于什么历史位置?
评估输出模板
🔍 invest-a-journal v0.2.1 · {date} · 🧊{杠杆} 🌤{广度} ⚠️{情绪}
## {方向}: {标的} ({代码}) — {资产类型}
### 方案摘要
| 项目 | 内容 |
|------|------|
| 驱动逻辑 | ... |
| 核心假设 | ... |
| 错误条件 | ... |
| 仓位 | X% |
| 最大可接受损失 | ... |
### 数据快照
| 指标 | 值 | 来源 | 质量 |
|------|-----|------|------|
| PE | ... | ... | available |
| 年化波动率 | ... | ... | available |
| 两融/市值 | ... | ... | available |
| 涨跌比 | ... | ... | available |
| 涨跌停比 | ... | ... | available |
## 逻辑完整性: {✅/⚠️/❌}
{文字}
## 数据盲点: {✅/⚠️/❌}
{文字}
## 仓位匹配: {✅/⚠️/❌}
{文字}
## 风险收益比: {✅/⚠️/❌}
{文字}
### 环境盲点提示(护栏 v1)
{从 apply_env_guardrail 追加的 blind_spots 列表}
> ⚠️ 本评估由 AI 生成,不构成投资建议。
> 所有评级(✅/⚠️/❌)为方案质量评估,非买卖方向建议。
数据库
表 trade_journals(在 ~/.local/share/investment/research.db)。v0.2.1 新增字段:
directionTEXT — 'buy' | 'sell'linked_journal_idINTEGER — 关联的买入/卖出日志 ID(v0.2.1 一对一;分批买卖多对多延至 v0.2.2)evaluation_jsonTEXT — Claude 评估结果 JSON
evaluation_json 结构
{
"evaluated_at": "2026-07-21T15:30:00",
"dimensions": {
"logic": {"level": "✅", "notes": "..."},
"blind_spots": {"level": "❌", "notes": "..."},
"position_sizing": {"level": "⚠️", "notes": "..."},
"risk_reward": {"level": "⚠️", "notes": "..."}
},
"blind_spots": [
{"rule": "deleveraging", "note": "..."}
],
"data_quality": {
"overall": "partial",
"quote": "available",
"kline": "available",
"valuation": "degraded"
},
"market_phase_at_eval": {
"leverage_cycle": "中性",
"breadth": "正常",
"extreme_sentiment": "极端亢奋"
},
"watch_conditions": [
"两融余额是否止跌",
"涨跌停比是否回到 3:1 以下"
],
"followup_questions": ["你考虑过中证1000期货做对冲吗?"]
}
环境护栏 v1(确定性规则)
护栏在评估完成后、保存前执行。只追加 blind_spots,不改写维度评级,不输出仓位数字。
| 条件 | 动作 |
|---|---|
| 两融标签包含 "偏冷"/"去杠杆"(中性+买入额偏低 → 标签为「中性 去杠杆」) | 追加:假设是否纳入去杠杆环境下的流动性收紧 |
涨跌停比 > 5:1、无跌停(lu_ld_note=no_limit_down)、或 < 1:5(ratio < 0.2) | 追加:情绪回归均值时入场价可能包含情绪溢价/恐慌折价 |
| 涨跌比 < 0.6 | 追加:指数可能被权重股拉偏,标的真实跌幅可能更大 |
与其他 Skill 的关系
invest-a-stock
独立 skill。通过 skill-local _invest_path.py shim(再导出 skills/lib/invest_path.py)导入 invest-a-stock 的 collect_quote/collect_kline/collect_macro_context/technical.compute。
Batch D 最小共用层:skills/lib/dates.py(yyyymmdd_to_iso)与 skills/lib/invest_path.py;invest-a-stock 经 shared_dates 再导出日期助手。journal 不改动 invest-a-stock 采集/估值主逻辑。
两融/涨跌比/涨跌停比由 journal 侧直接调 akshare(不经过 invest-a-stock collector)。
invest-a-etf
ETF 数据与对冲表的 canonical 拥有者。journal 的 etf_data.py 为 thin shim。用户需要 ETF 研究备忘录时用 /invest-a-etf;需要 方案四维评估时用本 Skill 并选 ETF 路径。
参考文档
references/evaluation-criteria.md— 评估细则 + 校准场景 + 边界条件示例../invest-a-etf/references/etf-hedge-map.md— ETF 对冲覆盖表(canonical;本目录仅留指针)../../host-docs/v0.2.1/calibration-case-july-2026.md— 7 月校准案例(去杠杆 + V 型反弹)
What ships with it: 20 files
123.4 KB alongside SKILL.md, 18 of them executable
references/
- etf-hedge-map.md275 B
- evaluation-criteria.md4.7 KB
scripts/
- journal.pyruns7.8 KB
- lib/db.pyruns11.7 KB
- lib/etf_data.pyruns2.5 KB
- lib/__init__.pyruns0 B
- lib/_invest_path.pyruns510 B
- lib/market_microstructure.pyruns41.8 KB
- lib/query_data.pyruns19.5 KB
tests/
- conftest.pyruns415 B
- test_compute_technical_stock.pyruns1.5 KB
- test_db_rollback.pyruns1.1 KB
- test_env_guardrail.pyruns5.5 KB
- test_etf_shim.pyruns2.4 KB
- test_microstructure_via_bridge.pyruns1.9 KB
- test_query_data_etf.pyruns4.8 KB
- test_query_helpers.pyruns1.5 KB
- test_safe_collect_ordering.pyruns7.7 KB
- test_sell_link.pyruns4.9 KB
- test_snapshot_status.pyruns3.1 KB