请添加图片描述

🌈你好呀!我是 是Yu欸

🚀 感谢你的陪伴与支持~ 欢迎添加文末好友​​

🌌 在所有感兴趣的领域扩展知识,不定期掉落福利资讯(*^▽^*)


写在最前面

 版权声明:本文为原创,遵循 CC 4.0 BY-SA 协议。转载请注明出处。

图 1:TradeLoop 把交易事实、原始计划、规则执行和用户确认放进同一条复盘链。

一、赚了 5%,后来却涨到 355.55,问题到底出在哪?

1.1 容易写的复盘,往往没用

有一笔交易,我在 232 元附近买入,持仓期间最高到了 273.22 元。后来股价转弱,我以约 5% 的收益离场。再往后看,它一度涨到 355.55 元。

如果只看结果,这笔交易很容易被总结成一句话:

卖早了。

但这种结论几乎没有行动价值。因为下一次遇到类似走势时,我仍然不知道应该怎么做。

真正值得复盘的不是“为什么没有卖在最高点”,而是下面这些问题:

我当初为什么买?

这套买入逻辑属于什么时间尺度?

卖出时,原始失效条件真的触发了吗?

我是不是临时换了一套判断标准?

原计划是减仓,为什么最后变成了全部清仓?

这次经验应该更新成长期规则,还是只算一次例外?

这才是 TradeLoop 想解决的问题。

图 2:结果只告诉我们赚了还是亏了,过程复盘才解释规则是否被执行。

1.2 盈利不等于过程正确,亏损也不等于规则错误

交易复盘容易出现两个误区。

第一个误区是:赚钱了,就认为当时所有判断都正确。

一笔交易可能因为运气、市场整体上涨或临时消息获得利润,但买入前没有明确理由,仓位也超出计划。这样的结果虽然是正的,过程并不值得复制。

第二个误区是:亏钱了,就马上修改规则。

一套长期有效的策略,本来就可能出现正常亏损。如果每次亏损后都临时增加一个条件,规则会越来越复杂,最后变成只解释历史、无法指导行动的“事后系统”。

因此,TradeLoop 会把交易拆成两个维度:

过程 结果 复盘含义
符合规则 盈利 规则得到一次正向验证
符合规则 亏损 可能只是正常概率结果
违反规则 盈利 不能因为赚钱就强化坏习惯
违反规则 亏损 优先检查执行与规则缺口

系统不因为卖出后上涨就自动判定卖出错误,也不因为卖出后下跌就认定当时的过程正确。

1.3 产品定位:不是选股 Agent

最开始,这个方向很容易做成一个大而全的股票 Agent:接行情、读公告、分析板块、讨论估值,最后给出买卖意见。

但这种产品已经很多,而且越往后做,越容易离开最初的问题。

TradeLoop 第一版暂时不做:

  • 自动选股;

  • 预测未来价格;

  • 给出买卖建议;

  • 自动下单;

  • 多个金融 Agent 自由辩论;

  • 用几百个技术指标堆出一个综合分数。

它只做一件事:

用户写下一段交易经历,系统自动还原事实、检查规则执行、发现逻辑漂移,并在用户确认后更新个人交易规则。

二、从八篇交易笔记,收敛成一个简单入口

2.1 原始材料里真正有价值的不是“观点”,而是方法

TradeLoop 的设计来自我之前整理的一组交易复盘笔记。里面涉及资金参与者、筹码迁移、板块强弱、K 线、特殊价格锚和仓位管理。

但在做系统时,我没有把八篇文章直接接成一个需要用户导入的知识库。

因为这些文章对产品真正有价值的,不是每一段原文,而是其中已经形成的方法:

  • 能给价格,就不只写“高位”“低位”;

  • 能给日期,就不只写“后来”“不久后”;

  • 事实、解释和未知必须分开;

  • 买入逻辑与卖出逻辑应使用一致的时间尺度;

  • 短期转弱不自动等于中长期逻辑失效;

  • 减仓、清仓和保留核心仓需要不同触发条件;

  • 一笔交易的结果不足以直接升级为长期规则;

  • 板块、价格、量能、基本面和执行记录应相互验证。

所以,最终系统把这些内容整理成了内置框架:

15 条默认交易规则

  • 6 个证据维度

  • 8 个复盘问题

  • 4 类核心逻辑漂移

用户不需要准备文件,也不需要点击“导入知识库”。

2.2 为什么最后只保留一个文本框?

第一版页面曾经要求用户分别填写:

  • 股票代码;

  • 买入日期;

  • 买入价格;

  • 卖出日期;

  • 卖出价格;

  • 买入理由;

  • 持有周期;

  • 失效条件;

  • 仓位计划;

  • 卖出理由。

字段很完整,但演示起来很重。用户每复盘一笔交易,都要像填表一样逐项录入。

后来入口被压缩成一个文本框:

我在 2025 年 1 月 27 日以 232 元买入 100 股,

计划按中长期产业逻辑持有。

买入理由是产业需求改善、板块预期扩散和个股趋势增强。

失效条件是订单或业绩逻辑失效,止损价 218 元。

短期转弱时先减仓 50% 并保留核心仓。

2025 年 3 月 17 日因为低开和短线转弱,

在 243.60 元全部卖出,原始失效条件没有触发。

持仓期间最高到 273.22 元。

2025 年 6 月 25 日收盘 340 元,最高 355.55 元。

剩下的事情全部交给系统。

图 3:用户只提供自然语言,系统自动完成结构化、计算、判断、回放与规则确认。

2.3 简单入口不等于把不确定性藏起来

自然语言里经常缺字段。

例如用户可能没有写数量,没有明确股票代码,也没有说明使用前复权还是后复权。

TradeLoop 不会悄悄补全这些信息,而是保留两类状态:

assumptions

系统为了继续计算采用了什么假设

missing_fields

哪些重要字段仍然缺失

例如:

{

"assumptions": [

"未提供数量,按 1 份计算比例指标"

],

"missing_fields": [

"symbol"

]

}

这样页面看起来仍然简单,但用户能知道结果建立在哪些前提上。

三、模型负责理解,代码负责计算

3.1 这类系统不能把所有事情都交给大模型

交易复盘同时包含两种任务。

第一种是确定性任务:

  • 计算平均买入价和卖出价;

  • 计算已实现收益;

  • 判断卖出数量是否等于全部持仓;

  • 计算持有天数;

  • 计算 MFE、MAE、最大回撤和 R 倍数;

  • 比较计划减仓比例与实际卖出比例;

  • 根据历史价格回放另一条规则路径。

这些任务适合由代码完成。

第二种是语言理解任务:

  • 用户说的“打算拿一段时间”属于什么周期;

  • 哪些句子是买入理由;

  • 哪些内容属于失效条件;

  • 卖出理由主要来自短期技术信号,还是原始逻辑变化;

  • 这笔交易留下了什么候选经验;

  • 哪些结论仍然缺乏证据。

这些任务适合交给 Seed Evolving。

最终的职责边界是:

Seed Evolving

提取语义、整理理由、解释冲突

确定性代码

计算指标、匹配规则、生成回放

Human Gate

由用户确认是否修改长期规则

图 4:模型处理语义,代码处理可重复计算,用户保留规则修改权。

3.2 两条 Seed 路径:快速提取与深度复盘

这次仍然使用火山引擎的 Agent Plan。

项目配置为:

ARK_MODEL=ark-code-latest

ARK_EXTRACT_MODEL=doubao-seed-2.0-lite

ARK_BASE_URL=https://ark.cn-beijing.volces.com/api/plan/v3

当前有两条调用路径。

第一条是自然语言快速复盘:

doubao-seed-2.0-lite

→ 从一段文字提取交易结构

→ 同时生成第一轮过程评价

这个路径使用低推理强度和 JSON 输出约束,重点是让文本入口足够快、结构化结果足够稳定。

第二条是已经结构化的案例复盘:

ark-code-latest

→ 读取完整证据包

→ 做更完整的过程与结果评价

两条路径都保留确定性降级。当模型输出不完整、超时或结构不符合 Schema 时,系统会转入本地解析和规则判断,并在结果里明确标记运行模式,而不是假装实时模型调用成功。

3.3 Agent Plan 在这个项目里解决了什么?

我这次还是直接使用火山引擎 Agent Plan。订阅包里除了 Seed 系列,也能切换其他国内常用模型,适合用同一套接口反复测试结构化提取和复盘效果。

TradeLoop 当前没有为了节省一次调用,把所有逻辑都塞进 Prompt。相反,Prompt 只负责模型擅长的部分,计算、规则匹配和版本更新仍然由本地代码执行。

API Key 只保存在 .env 中,不写入数据库、报告和前端代码。

四、一段自然语言是怎么变成交易案例的?

4.1 先抽取最小事实结构

自然语言入口会先整理成 TradeCaseCreate:

{

"symbol": "TEXT-CASE",

"market": "CN",

"fills": [

{

  "side": "buy",

  "executed_at": "2025-01-27T00:00:00",

  "price": 232,

  "quantity": 100

},

{

  "side": "sell",

  "executed_at": "2025-03-17T00:00:00",

  "price": 243.60,

  "quantity": 100

}

]

}

然后再恢复 Thesis:

{

"time_horizon": "long",

"entry_reasons": [

"产业需求改善",

"板块预期扩散",

"个股趋势增强"

],

"invalidation_conditions": [

"订单或业绩逻辑失效"

],

"position_plan": "短期转弱时减仓 50%,保留核心仓",

"planned_stop_price": 218,

"planned_exit_fraction": 0.5

}

4.2 模型输出不能直接进入计算

模型有时会把“50%”返回为 50,也可能把单个失效条件返回为字符串,而不是字符串数组。

因此,进入领域模型前还要经过一层归一化:

“中长期” → long

50 → 0.5

单个字符串 → 单元素数组

false → 空数组

中文日期 → YYYY-MM-DD

列表形式的卖出理由 → 合并为一句文本

如果模型没有正确构造价格路径,系统还会用本地正则解析补齐买入日、卖出日和后续价格节点。

这一步很重要。自然语言 Agent 最常见的问题并不是“完全答错”,而是字段形状偶尔不稳定。与其要求模型永远一次输出完美 JSON,不如在代码里明确吸收这些小偏差。

4.3 数据源只作为补充,不阻塞主流程

用户可以直接在文本里写明价格路径。这样演示不依赖任何外部数据源。

当文本没有后续行情时,系统才尝试调用免费 Provider:

BaoStock

→ AKShare

→ Yahoo / yfinance

→ 无数据时明确标记 unavailable

当前免费 A 股主链使用 BaoStock,已实际返回 600519 的历史日线数据。AKShare 和 Yahoo 保留为补充,但外部站点限流或断开连接时不会影响本地复盘。

图 5:用户文本是主输入,模型和免费行情只负责补充,不会覆盖用户已明确提供的事实。

五、结果页不只显示收益,还要显示交易路径

5.1 七类确定性指标

TradeLoop 当前计算以下指标:

指标 含义
已实现收益 实际卖出相对平均买入成本的收益
MFE 持仓期间最大有利变动
MAE 持仓期间最大不利变动
最大回撤 持仓路径从阶段高点向下的最大跌幅
卖出后最高涨幅 卖出后历史价格相对卖出价的最大上涨
退出效率 实际收益占持仓期最大浮盈的比例
R 倍数 实际盈亏相对初始止损风险的倍数
仓位执行偏差 实际卖出比例减去计划卖出比例

以系统内置案例为例:

买入价 232.00

卖出价 243.60

已实现收益 +5.00%

持仓期 MFE +17.77%

持仓期 MAE -1.72%

持仓期最大回撤 -6.31%

卖出后最高涨幅 +45.96%

退出效率 28.14%

仓位执行偏差 +50 个百分点

这里的 MFE 只统计买入到卖出之间的价格,不会把卖出后的 355.55 错算成“持仓期最大浮盈”。卖出后的走势单独进入 post_exit_return。

图 6:持仓期指标与卖出后行情分开计算,避免用未来价格改写当时的持仓体验。

5.2 退出效率不是要求卖在最高点

退出效率的计算是:

退出效率 = 已实现收益 / 持仓期 MFE

在示例里:

5.00% / 17.77% ≈ 28.14%

这个数字不是为了要求每次卖在最高点,而是提醒我们:这笔交易曾经积累的利润,最后保留了多少。

它需要和原始计划一起看。

如果原本就是短线交易,达到目标后离场,即使后续继续上涨,较低的退出效率也不一定代表问题。

但如果买入理由是中长期产业逻辑,计划中又写着“短期转弱只减仓”,最后却全部卖出,退出效率就成为一个值得继续追问的结果,而不是独立结论。

5.3 R 倍数把不同价格的交易放到同一尺度

当用户写下止损价时,系统可以计算:

初始风险 R = 买入价 - 计划止损价

实际 R 倍数 = 实际每股盈亏 / 初始风险

例如:

买入价 232

止损价 218

卖出价 243.60

初始风险 14

实际盈利 11.60

R 倍数 0.83R

这样,不同股票、不同价格和不同仓位的交易就能用统一风险尺度比较。

六、用过程评分卡代替一个模糊的“好交易”标签

6.1 五个维度分别回答不同问题

TradeLoop 的过程评分卡包含五个维度:

维度 检查内容
计划完整度 周期、理由、失效条件、仓位和退出计划是否齐全
逻辑一致性 买入与卖出是否使用相同时间尺度和证据门槛
证据质量 是否有多维、可核验的信息支撑
仓位纪律 实际减仓比例是否符合计划
退出纪律 卖出是否映射到预设退出条件

每个维度单独给分,最后取平均值。

内置案例当前得到:

过程总分:56 / 100

主要扣分来自:

  • 中长期买入逻辑被短期信号替换;

  • 原始失效条件没有记录为已触发;

  • 原计划是减仓并保留核心仓,实际却全部卖出;

  • 买入时使用多维证据,卖出时主要依赖单一短期信号。

这个分数只用于定位过程缺口,不代表股票质量,也不代表下一笔交易应该买还是卖。

图 7:总分不是目的,真正有用的是知道具体哪一项规则发生了偏移。

6.2 当前稳定识别四类逻辑漂移

第一版主链重点识别四类漂移。

时间尺度切换

买入:中长期产业逻辑

卖出:单日低开、均线或短线转弱

这不代表卖出一定错误,但意味着判断标准已经变化,需要显式说明。

失效条件未触发

原计划:订单或业绩逻辑失效时退出

实际:没有记录失效条件,却已经卖出

这类情况要么属于一次例外,要么说明旧退出规则已经不再适用。

仓位规则违背

原计划:减仓 50%,保留核心仓

实际:卖出 100%

系统会计算出 +50% 的仓位执行偏差。

证据门槛下降

买入时:产业、板块、个股趋势共同验证

卖出时:只看一个短期信号

这说明退出时使用的证据标准比买入时更弱。

图 8:TradeLoop 检查的不是涨跌方向,而是决策规则是否在交易中途发生变化。

6.3 事实、推断和未知仍然必须分开

系统会把证据分为:

FACT

来自用户记录、成交和确定性计算

INFERENCE

模型对过程和规则关系的解释

UNKNOWN

当前信息无法确认的内容

例如:

FACT:2025 年 3 月 17 日以 243.60 元卖出。

FACT:原计划为短期转弱时减仓 50%。

INFERENCE:实际动作强于原始仓位计划。

UNKNOWN:当时市场中具体哪类资金在卖出。

系统不会因为 K 线下跌就写出“主力出货”,也不会根据一段复盘文字推断某家机构的精确行为。

七、规则路径回放:比较“实际做法”和“原计划”

7.1 Shadow Path 不等于预测

TradeLoop 增加了一条规则路径回放。

示例中的实际动作是:

3 月 17 日卖出 100%

最终实现收益 5.00%

原计划是:

短期转弱先卖出 50%

剩余 50% 作为核心仓继续持有

系统用已经发生的历史价格构造另一条路径:

50% 仓位在 243.60 元卖出

50% 仓位按 6 月 25 日收盘价 340 元结算

得到:

实际路径历史收益 5.00%

规则路径历史回放收益 25.78%

这个结果不能说明“原规则一定更优”。因为 6 月 25 日的价格在 3 月 17 日并不可知。

它只回答一个问题:

如果当时严格执行已经写下的仓位规则,历史路径会有什么不同?

图 9:规则回放用于检查执行差异,不把未来行情包装成当时可用的信息。

7.2 为什么不做完整回测?

完整回测通常需要:

  • 明确入场和退出信号;

  • 可重复执行的策略代码;

  • 全量历史行情;

  • 交易成本和滑点;

  • 多标的和多周期评估。

TradeLoop 面对的是个人自然语言复盘,很多规则并没有精确到可自动交易的程度。

所以第一版只回放用户已经明确写下的仓位动作,例如“减仓一半”“保留核心仓”,不把模糊的主观判断强行编译成完整策略。

八、Human Gate:规则变化必须交还给用户

8.1 模型不能直接修改长期规则

当系统检测到冲突时,不会自动把新经验写成正式规则。

它会提出一个最小问题:

这笔交易原本按中长期逻辑建立,但卖出使用了短期信号。你希望正式切换为短线,还是保留中长期逻辑,并把短期转弱改为减仓条件?

当前支持几种处理方式:

保留原规则

本次作为例外

更新长期规则

自定义说明

只有用户确认“更新规则”后,系统才会创建新规则。

8.2 旧规则不删除,只标记为 Superseded

规则更新采用版本链:

旧规则 ACTIVE

用户确认新决定

旧规则 SUPERSEDED

新规则 ACTIVE

保留来源、时间和证据

例如:

old_rule:

statement: 跌破短期均线时全部清仓

status: superseded

new_rule:

statement: 中长期逻辑未失效时,短期转弱只触发分批减仓

status: active

evidence:

- 当前交易复盘

- 用户确认

这样做的目的不是让规则越来越多,而是让系统能解释:今天的规则为什么和过去不同。

图 10:模型提出冲突,用户确认选择,系统再进行版本化更新。

8.3 一笔交易不足以证明一条规则

当前系统允许用户直接把一条经验更新为正式规则,这是为了让演示闭环完整。

但从长期产品设计看,更合理的规则成熟过程应该是:

单次经验

→ 候选规则

→ 多笔交易重复出现

→ 用户确认

→ 正式生效

这是后续最值得继续完善的部分。否则系统可能因为一次卖飞,就不断修改自己的交易体系。

九、从单笔复盘,扩展到多笔交易行为画像

9.1 一笔交易只能发现局部问题

时间尺度切换和仓位规则违背可以从一笔交易中识别。

但下面这些行为需要多笔样本:

  • 盈利时很快卖出,亏损时长期持有;

  • 经常围绕成本价和历史最高价做决定;

  • 买入理由反复出现“怕踏空”“大涨后追入”;

  • 计划经常不完整;

  • 高严重度逻辑漂移反复出现。

因此,TradeLoop 会对所有已复盘案例生成行为画像。

9.2 当前多笔指标

系统会汇总:

交易数

胜率

平均盈利

平均亏损

Profit Factor

Expectancy

平均持有天数

规则遵守率

计划完整率

同时检测三类行为信号:

处置效应

当亏损交易平均持有时间明显长于盈利交易时,系统提示可能存在“过早兑现盈利、延迟确认亏损”的倾向。

价格锚定

当多笔退出理由反复出现“回本”“成本价”“历史最高价”“整数关口”时,系统会指出价格锚的使用频率。

追涨倾向

当买入理由反复出现“追涨”“涨停”“大涨”“怕踏空”等表达时,系统会列出对应交易案例。

少于四笔交易时,系统不会强行判断长期行为,只输出“证据不足”。

图 11:单笔交易检查规则,多笔交易才有资格讨论稳定的行为倾向。

十、项目是怎么实现的?

10.1 代码结构保持轻量

项目没有引入复杂的多 Agent 框架,当前核心结构如下:

TradeLoop/

├── app/

│ ├── builtin.py # 15 条规则、6 个证据维度、8 个复盘问题

│ ├── analytics.py # 指标、评分卡、漂移、回放和行为画像

│ ├── seed.py # Seed Evolving 提取与复盘

│ ├── service.py # 主流程编排

│ ├── storage.py # SQLite、规则版本和事件记录

│ ├── providers/

│ │ └── market.py # BaoStock、AKShare、Yahoo、OpenBB 适配

│ ├── domain/

│ │ └── models.py # Pydantic 数据模型

│ ├── web/

│ │ └── index.html # 单文本框 Web 页面

│ └── main.py # FastAPI 接口

├── skills/

│ └── trade-review-memory-gate/

├── tests/

├── scripts/

│ └── smoke_test_all.py

├── README.md

└── pyproject.toml

主链没有隐藏在多个 Agent 的对话里,而是一个可测试的服务流程:

extract_trade_case

→ create_case

→ review_case

→ calculate_metrics

→ detect_logic_drifts

→ calculate_process_scorecard

→ calculate_rule_replay

→ build_behavior_profile

→ resolve_conflict

图 12:自然语言、确定性计算、Seed 推理、记忆更新和报告生成保持分层。

10.2 主要接口

GET /health

GET /api/v1/framework

GET /api/v1/providers

GET /api/v1/seed/health

POST /api/v1/review-text

POST /api/v1/demo/run

GET /api/v1/cases

GET /api/v1/cases/{case_id}

GET /api/v1/cases/{case_id}/report.md

GET /api/v1/profile

GET /api/v1/rules

GET /api/v1/rules/{rule_id}/history

POST /api/v1/conflicts/{conflict_id}/resolve

用户真正需要使用的只有一个:

POST /api/v1/review-text

其余接口用于页面展示、测试和规则管理。

10.3 当前测试结果

本地检查结果:

Pytest:10 passed

Ruff:All checks passed

Python compileall:通过

全流程 Smoke Test 包括:

应用健康检查

OpenAPI 文档

Provider 注册表

Seed Evolving 连通性

内置复盘框架

单文本自动复盘

行为画像

Markdown 报告

案例查询

规则查询

Human Gate 冲突处理

自然语言实时链路实测:

结构化模型:doubao-seed-2.0-lite

提取模式:live

复盘模式:live_single_pass

平均响应时间:约数秒到十几秒,受模型服务状态影响

结构化案例深度复盘实测:

模型:ark-code-latest

模式:live

外部免费行情会受到网络和上游站点影响,因此 Smoke Test 默认区分“本地接口通过”和“外部数据源实时可用”。

十一、这个系统现在能解决什么?

11.1 当前已经能完成的闭环

用户输入一段交易经历后,TradeLoop 可以自动完成:

提取买卖事实

→ 恢复原始 Thesis

→ 计算收益与路径指标

→ 生成五维过程评分

→ 发现逻辑漂移

→ 回放原计划路径

→ 更新多笔行为画像

→ 提出 Human Gate 问题

→ 用户确认后更新规则

→ 输出 Markdown 报告

这个闭环已经足够用于本地演示和持续复盘。

11.2 当前边界

系统仍然有明确限制:

  1. 自然语言越模糊,模型采用的假设越多;

  2. 没有后续价格时,部分路径指标无法计算;

  3. 行为画像需要多笔交易,单笔样本不能证明长期偏差;

  4. 规则回放使用已经发生的历史价格,不是策略回测;

  5. 当前规则更新可以直接生效,候选规则成熟机制还没有完整实现;

  6. 系统不会验证用户写下的基本面观点是否真实;

  7. 它不替用户判断当前应该买入、持有还是卖出。

11.3 不是荐股 Agent

行情预测的正确性很难稳定验证,而且用户很容易只关注一两次结果。

复盘系统处理的是已经发生的交易。输入、成交、计划和规则都能留下记录,很多指标也能由代码重复计算。

更重要的是,它关注的是长期可积累的东西:

我为什么买

我为什么卖

我当时遵守了什么

我在哪一步改了规则

这次经验是否值得保留

当这些内容被版本化保存后,每一笔交易不再只留下一条盈亏数字,而会成为下一笔决策的上下文。

结语

交易结束以后,我们最容易盯着两个数字:赚了多少,后来又涨了多少。

但这两个数字无法直接告诉我们,下次应该怎么做。

232 元买入、赚 5% 离场、后来涨到 355.55,这个故事真正值得保留的,不是“当时应该拿住”,而是:

  • 买入时采用的是中长期逻辑;

  • 卖出时却切换成了短期逻辑;

  • 原始失效条件并没有记录为已触发;

  • 原计划是减仓,实际执行成了清仓;

  • 结果虽然盈利,过程仍然存在规则漂移。

TradeLoop 用 Seed Evolving 把一段自然语言整理成结构化交易,用确定性代码计算路径指标,再通过 Human Gate 把规则修改权交还给用户。

它不会告诉我下一只股票买什么。

它只希望让我在下一次按下买入或卖出按钮前,记得自己之前为什么这样做。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐