引言:从 Harness Engineer 到 Loop Engineer
前段时间,"Harness Engineer" 的理念在量化圈流行了一阵。它的核心不是拍脑袋选答案,而是搭一个框架,让候选项在统一的评估标准下自己比出胜负。落到交易上,就是把多个标的、多组参数、多套规则放进同一套回测或评估框架里,用历史数据和统一目标函数筛出相对更优的组合。
这个思路解决的是一个横向选择问题:在同一时间切面上,从一堆候选里挑出表现更好的那个。它很有效,但也有一个天然局限:选出来的答案是“历史样本里的相对最优”。跑完这一轮之后,框架本身并不会真正变聪明,下一轮重新跑,本质上还是同一套评分逻辑在重复执行。
那如果问题不是“选哪个”,而是“怎么让系统在运行过程中持续积累自己的经验”呢?
这就是我最近更感兴趣的方向:可以暂且称为 Loop Engineer。
与其一次性搭好一个评分框架跑完就结束,不如搭一个“决策 → 执行 → 复盘 → 更新”的闭环,让系统把每一次信号、交易和结果,沉淀成下一次可以调用的经验。
这里说的“进化”,不是机器学习里严格意义上的在线训练,也不是更新大模型权重。更准确地说,它是一种外部经验库的持续更新:系统会把交易复盘写入数据库,把经验总结成 playbook,再让下一轮决策读取这个 playbook。模型本身没有被训练,变化的是系统运行时可引用的经验和一部分可调参数。
如果说 Harness Engineer 关心的是“空间”,也就是在候选空间里横向比较;那么 Loop Engineer 更关心的是“时间”,也就是沿着交易时间轴持续记录、复盘和修正。工程师不再直接给策略下最终结论,而是设计好闭环的骨架、评估标准和安全边界,剩下的交给系统在一次次运行中慢慢积累。
本文想聊的,就是一套基于这个思路搭建的单品种 AI 自进化交易系统。它不追求同时覆盖几百个币种,而是盯住一个标的,比如 BTC、黄金、原油任意一个永续合约,把“经验”当成系统运行过程中真正会变化的核心资产。
为什么选择单品种做闭环实验
Harness 类框架天然适合“广撒网”:候选池越大,横向比较越有意义。但代价是,每个候选身上能沉淀的信息通常比较浅。每个币可能只对应几组回测分数,很难谈得上什么“个体经验”。
Loop Engineer 的思路正好反过来。它更适合先在一个标的上做深度观察:同一个品种的波动性格、消息敏感度、假突破形态、趋势延续方式,往往有自己的“脾气”。这些东西混在几百个标的的横向比较里,很容易被平均掉;但如果只盯一个标的持续记录和复盘,就有机会被系统反复观察到,最后沉淀成可复用的规则。
当然,这不代表单品种天然更容易训练出稳定规律。恰恰相反,单品种最大的问题就是样本积累慢,统计证据弱,早期特别容易把短期噪声误当成规律。所以更准确地说,单品种适合用来观察闭环经验如何在同一交易语境里沉淀,但它并不自动保证经验一定可靠。
这也是这套系统一开始就应该被放在观察和迭代的位置,而不是直接当成成熟实盘系统。
架构拆解:一个闭环,五个环节
整套系统按照“感知 → 决策 → 执行 → 复盘 → 更新”运转。中间有两条主要信息通道:技术面和消息面。技术面来自指标快照,消息面来自新闻搜索和缓存,两者一起交给决策层。
1. 感知层:把市场翻译成结构化语言
系统会先建立一组技术指标,包括趋势、动量、波动率、量能等维度,例如 EMA、MACD、RSI、布林带、ATR、KDJ。它们不会以一堆零散数字的形式直接丢给模型,而是先组装成一份结构化快照:
python
snapshot = {
"price": price,
"trend": {
"ema_fast": ema_fast,
"ema_slow": ema_slow,
"macd_hist": hist,
"macd_hist_rising": hist > hist_prev,
},
"momentum": {
"rsi14": rsi_v,
"kdj_k": k_v,
"kdj_d": d_v,
},
"volatility": {
"boll_upper": boll_upper,
"boll_lower": boll_lower,
"atr_pct": atr_v / price * 100,
},
"volume": {
"vol_ratio_to_ma20": vol_ratio,
},
}
这一步的意义不是让模型“神秘地看懂行情”,而是把市场状态翻译成它更容易处理的结构化语言。趋势、动量、波动率、量能各自是什么状态,都被明确放进字段里。
新闻层则通过搜索接口抓取该品种相关的新闻,并做去重缓存。它不直接产生交易信号,而是作为消息面判断的原始材料。
2. 决策层:技术面和消息面至少不能互相打架
指标快照、近期新闻、当前持仓状态,以及系统当下的 playbook,会一起打包交给大模型。模型需要输出结构化交易信号,包括动作、方向、置信度、技术面判断、消息面判断和理由。
这里有一条硬性要求:技术面和消息面冲突时,不允许开仓或加仓。如果消息面明显看空,技术面却在提示做多,模型就应该给出观望或离场,而不是硬着头皮开仓。
提示词里会明确写入类似这样的约束:
python
"1. 只有technical_view与news_view不冲突(news_view为neutral/no_data,"
"或方向与technical_view一致)才能给出open_long/open_short/add_long/add_short。",
"2. 如果news_view方向与technical_view相反,action必须是hold或close。",
"4. confidence必须真实反映把握程度(0-100),不要习惯性给高分,把握不足给低分。",
需要注意的是,“不冲突”只是开仓的必要条件,不是充分条件。也就是说,技术面和消息面不打架,不代表系统一定会开仓。模型还要判断信号强度是否足够,最后输出 open_long、open_short 或 hold。执行层还会再检查置信度是否超过门槛。
python
if action in ("open_long", "open_short") and not has_pos:
if decision["confidence"] < min_conf:
return
open_position(store, decision, ticker, add_mode=False)
所以如果出现“消息面偏多,但技术面中性,最后 action 仍然是 hold”,这是符合系统设计的。它的含义是:消息面有倾向,但技术面没有给出足够确认,暂时不动。
3. 执行层:参数从 playbook 读取,但仍有硬边界
这套系统和传统固定参数策略的区别之一,是执行参数不是完全固化在策略逻辑里。仓位比例、止损百分比、移动止盈的激活和回撤阈值,会优先从当前版本的 playbook 中读取。
但这并不意味着 AI 可以随意改参数。初始值、上下限、最大仓位、最大加仓次数、杠杆等边界仍然由人工设定。playbook 只能在这些边界内提供当前版本的参数值。
python
def playbook_param(store, key, config_default, lo, hi):
v = store.get("current_playbook", {}).get("params", {}).get(key, config_default)
try:
v = float(v)
except Exception:
v = config_default
return clamp(v, lo, hi)
每次执行时,系统都会读取当前 playbook:
python
hard_stop_pct = playbook_param(
store,
"hard_stop_pct",
HARD_STOP_PCT,
HARD_STOP_PCT_MIN,
HARD_STOP_PCT_MAX,
)
仓位大小也不是一个固定比例,而是“基础仓位 × 本次决策置信度”。置信度越低,实际仓位越小;置信度越高,仓位才接近基础仓位上限。
python
base_pos_pct = playbook_param(
store,
"base_pos_pct",
BASE_POS_PCT,
BASE_POS_PCT_FLOOR,
BASE_POS_PCT_CEIL,
)
size_pct = base_pos_pct * clamp(decision["confidence"] / 100.0, 0.4, 1.0)
这里的关键不是让模型决定一切,而是让系统拥有一个可控的参数更新入口。AI 可以建议调整,但最终执行值必须经过代码层裁剪。
4. 复盘层:完整交易结束后才生成经验
每完成一笔完整的开平仓交易后,系统会把这笔交易的上下文交给大模型复盘,包括入场理由、方向、盈亏、平仓原因等。模型需要输出一条具体的中文经验,而不是“操作失误”“行情不好”这种空泛总结。
比如更理想的经验应该类似:
RSI 超过 70 且新闻面偏空时追多容易被套,应等待回调或放弃开仓。
复盘结果会连同问题类型一起写入数据库:
python
schema = {
"outcome": "win|loss|breakeven",
"mistake_type": "none|chased_move|ignored_news_conflict|"
"stop_too_tight|stop_too_wide|overleveraged|held_too_long|other",
"lesson": "",
"tags": [""],
}
这里要强调一点:复盘不是在每次模型做出决策后立刻发生,而是在交易真正结束之后发生。开仓只会记录 decision,只有平仓后系统才知道这笔交易最后是赢、亏还是基本持平。
5. 更新层:把近期复盘整理成新版 playbook
当复盘记录积累到一定数量,或者到了固定时间窗口,系统会触发一轮 playbook 更新。它会读取近期复盘、整体胜率和盈亏统计,让大模型输出新版经验手册,包括新的 do / avoid 规则,以及对部分参数的调整建议。
但新参数不会被无条件采纳,而是逐个裁剪进人工预设的安全上下限:
python
bounds = {
"min_confidence": (MIN_CONFIDENCE_FLOOR, MIN_CONFIDENCE_CEIL),
"base_pos_pct": (BASE_POS_PCT_FLOOR, BASE_POS_PCT_CEIL),
"hard_stop_pct": (HARD_STOP_PCT_MIN, HARD_STOP_PCT_MAX),
"trail_activate_pct": (TRAIL_ACTIVATE_PCT_MIN, TRAIL_ACTIVATE_PCT_MAX),
"trail_giveback_pct": (TRAIL_GIVEBACK_PCT_MIN, TRAIL_GIVEBACK_PCT_MAX),
}
for k, (lo, hi) in bounds.items():
if k in suggested:
new_params[k] = round(clamp(float(suggested[k]), lo, hi), 4)
裁剪后的新参数和新规则会写回数据库,成为下一轮决策读取的当前 playbook。
这就是这套系统所谓“自进化”的真实含义:不是模型权重变了,而是外部经验库和可调参数在运行中被更新了。下一次决策时,模型会看到新的 playbook,从而在同一套代码下表现出不同的行为倾向。
进化不等于失控:闭环里的硬约束
给系统“更新自己经验”的能力,风险也很直观。如果没有边界,连续几笔亏损可能会让模型总结出错误经验,进而把系统推向更差的参数。
所以这套设计里有几层限制。
第一,AI 不能修改代码,只能在人工设定的数值区间内微调参数。比如止损百分比只能在某个上下限之间浮动,区间本身由代码或平台参数控制,playbook 不能突破。
第二,硬止损、单标的最大仓位、最大加仓次数,是代码层强约束。它们和 playbook 里的软性参数是两套东西。后者可以被更新,前者不能被 AI 放宽。
第三,开仓需要技术面和消息面至少不冲突。单一信号源不能独立触发交易。
第四,系统默认可以运行在“仅通知”模式下,先观察信号、复盘和 playbook 变化,而不是一开始就直接实盘下单。
例如单标的仓位上限和最大加仓次数会在执行层被硬性检查:
python
max_qty = equity * MAX_SINGLE_POS_PCT * LEVERAGE / ticker["Last"] / market["ctVal"]
if cur_qty + qty > max_qty:
qty = max(0, max_qty - cur_qty)
if pos.get("add_count", 0) >= MAX_TOTAL_ADD_COUNT:
return
这几条约束本质上是在说:闭环可以自己调整“怎么做得更好”,但不能自己放宽“最多能冒多大风险”的底线。
它和真正成熟的持续学习系统还有多远
这里必须说清楚:这套系统离真正成熟的持续学习系统还有很长距离。
| 维度 | 成熟的持续学习系统 | 这套单品种闭环 |
|---|---|---|
| 学习对象 | 通常会更新模型、策略权重或经过严格验证的规则 | 不更新模型权重,主要更新外部 playbook 和参数 |
| 样本规模 | 通常需要大量迭代才具备统计意义 | 单品种样本积累慢,早期噪声占比高 |
| 新版本验证 | 有影子模式、A/B 测试或样本外验证 | 新版 playbook 生成后直接影响下一轮决策 |
| 归因可靠性 | 有专门方法区分运气和规律 | 复盘依赖大模型定性归因,存在事后归因偏差 |
| 环境变化识别 | 有 concept drift 检测或 regime 判断机制 | 主要依赖固定笔数或固定时间触发更新 |
| 参数调整证据 | 有显著性检验、置信区间或严格回测支持 | 更多依赖近期复盘和模型总结 |
核心差距可以归结为一句话:成熟的持续学习系统会追问“这条新经验在没见过的数据上是否仍然成立”,而这套闭环目前更多是在总结已经发生的、数量有限的交易。
这并不意味着它没有价值。它的价值在于把交易系统里经常被人工完成的事情结构化了:记录、复盘、总结、更新、再引用。以前这些经验可能散落在人的笔记、聊天记录或主观记忆里,现在它们被写成数据库里的 playbook,成为下一轮决策真正能读到的上下文。
但这也意味着,早期阶段必须非常谨慎。系统总结出的经验可能是规律,也可能只是短期噪声。尤其是单品种、低频交易、样本数量还很薄的时候,任何“进化结果”都不应该被过度相信。
结语:闭环的价值不在于一次搭对,而在于持续观察
Loop Engineer 这个思路真正吸引我的地方,不是它承诺“系统会越用越准”,而是它把“变得更好”这件事从人工调参、重新发布策略,变成了系统运行过程中可以被记录、被复盘、被更新的一部分。
当然,这里的“变好”不是自动发生的。系统可能学到有效经验,也可能学到噪声;可能让参数更稳健,也可能因为样本太少而产生错误偏移。人仍然需要观察 playbook 每次更新后的变化,检查规则是不是具体,参数是不是大幅震荡,信号是不是越来越合理。
所以这套系统更适合先被当成一个观察和迭代的起点,而不是一个可以直接放心加杠杆实盘的成品。更稳妥的方式,是先在“仅通知”模式下跑一段时间,观察它的信号质量、复盘质量和 playbook 演化方向,再决定是否进入小仓实盘。
闭环搭起来,只是第一步。它能不能真的沉淀出有效经验,最终还是要交给足够长的时间、足够多的交易样本,以及严格的风险控制去验证。
本文仅为策略设计思路的技术讨论,不构成任何投资建议。加密货币与其他金融衍生品交易存在较高风险,请谨慎评估自身风险承受能力。
- 1




