作者:老余捞鱼
原创不易,转载请标明出处及原作者。

写在前面的话:你有没有被"信号打架"坑过?几个策略同时推同一只股,有的说买、有的说卖。随便选一个,结果可能是亏得莫名其妙。现在可以在策略和交易之间,加一层"智能仲裁"。它负责综合所有信号、给个靠谱结论。这个思路可能会改变你管理交易的方式。
前言:你的筛选器可能在”骗”你
大家用股票筛选器,有没有发现一个问题:策略给的交易清单,不一定靠谱。
不是指标不准,而是当多个策略同时跑的时候,它们会打架:
- 有的说买;
- 有的说卖;
- 还有的说再等等。
如果随便选一个执行,资金就这么稀里糊涂地被消耗掉了。
所以我想做一件事:筛选器负责”发现问题”,但”拍板”这活儿,需要另一个人。 我管它叫”仲裁层”(Arbiter)。
一、为什么”仲裁”是必要的?
当你在用多个策略(趋势策略、反转策略、突破策略等)时,真正的坑不在于某个策略错了。真正的坑在于:
| 问题 | 后果 |
|---|---|
| 策略之间互相矛盾时做交易 | 被反复打脸 |
| 往喊得最凶的策略上重仓 | 单策略风险过大 |
| 忽略交易成本 | 预期收益被蚕食 |
| 在波动率飙升前加仓 | 回撤失控 |
| 让坏日子变成坏月份 | 心态崩盘 |
我的观点可能有点争议:一个只出信号、没有任何仲裁层的筛选器:本质上是个玩具。适合研究,不适合直接用。
仲裁层的作用很直接:
- “谢谢,但不采纳”;
- “可以,但仓位小点”;
- “行,但得先算清楚能承受多少”。
二、仲裁层的运作流程
交易流程是这样的:

1. 定时触发(每天/每小时,根据你的周期来) ;
2. 加载当前持仓(看看哪些该平了) ;
3. 先处理退出信号(止损/止盈/时间止损/反向信号) ;
4. 收集新信号(来自所有策略) ;
5. 白名单过滤(只留可交易标的) ;
6. 仲裁:把多个策略的信号合并成”每只股票一个结论” ;
7. 输出推荐结果 + 诊断信息(方便以后复盘) ;
8. 推送通知(微信/邮件/群) ;
9. 持久化记录(重启后不会丢失风险状态);
核心哲学: 仲裁层是一个”关卡”,而不是”预测模型”。
你可以把这个流程逻辑喂给你的AI,让它来帮你修订交易流程。
三、仲裁层到底在”判”什么?
每只股票,我用四个维度打分。
1. 方向共识(投票比例)
多个策略同时说”做多”,和有的说”做多”、有的说”做空”,完全不是一回事。
我用一个 [-1, 1] 的数字来表达:
- +1:全员看多
- -1:全员看空
- 0:多空基本持平
2. 策略广度(分散程度)
如果只有1个策略提到某只股,它的可信度就比较低。
广度大意味着”多个独立视角都注意到了这只股票”,减少踩中某个策略”抽风期”的概率。
3. 矛盾惩罚(分歧代价)
策略之间打架,是要付出代价的:来回交易磨损、假信号亏损、仓位计算错误。
所以我给矛盾加了一个惩罚项:不是因为我喜欢惩罚,而是诚实地反映现实。
4. 分数压缩(防止虚高)
直接把几个分数加起来,容易出现”虚假精准”的问题。
我用了 tanh 函数来压缩最终分数,让它落在 [-1, 1] 这个稳定区间,零是中心点。这样输出就是一个”可信度系数”,后续想转概率也行。
四、算笔账:你的策略能覆盖成本吗?
先别急着调参数,把数学做一遍。假设:
- 持仓金额:2万美元
- 预期盈利幅度:+0.5%
- 止损幅度:-0.4%
- 双向摩擦成本(点差+滑点):0.08%
计算:
| 项目 | 金额 |
|---|---|
| 达标止盈收入 | 0.5% × $20,000 = $100 |
| 摩擦成本 | 0.08% × $20,000 = $16 |
| 最好情况净利润 | $84 |
| 止损亏损 | 0.4% × $20,000 = $80 |
| 加摩擦后亏损 | $80 + $16 = $96 |
结论: 如果胜率不到50%以上,这个策略是脆弱的。如果你的仲裁层还增加了交易频率,那更糟糕。
这就是为什么我坚持:矛盾不是噪音,是税。
五、一个可以跑起来的仲裁层代码
下面的代码实现了最核心的仲裁逻辑(Python):
import numpy as npimport pandas as pd# 模拟策略信号rows = [ {"asset":"AAPL", "strategy":"mr_1", "dir":"long", "w":1.0}, {"asset":"AAPL", "strategy":"brk_2", "dir":"long", "w":1.0}, {"asset":"AAPL", "strategy":"trend_1", "dir":"short", "w":1.0}, {"asset":"MSFT", "strategy":"mr_1", "dir":"long", "w":1.0}, {"asset":"MSFT", "strategy":"brk_2", "dir":"long", "w":1.0}, {"asset":"TSLA", "strategy":"trend_1", "dir":"short", "w":1.2},]df = pd.DataFrame(rows)all_strats = sorted(df["strategy"].unique())S = max(1, len(all_strats))def arbiter(g): wl = g.loc[g.dir.eq("long"), "w"].sum() ws = g.loc[g.dir.eq("short"), "w"].sum() tot = max(1e-9, wl + ws) vote = (wl - ws) / tot contr = min(wl, ws) / tot div = g["strategy"].nunique() / S div_conf = 0.5 + 0.5 * div raw = vote * div_conf - 0.4 * contr score = float(np.tanh(1.6 * raw)) conf = int(round(abs(score) * 100)) action = "NO_TRADE" if conf >= 60: action = "LONG" if score > 0 else "SHORT" return pd.Series({"score":score, "conf":conf, "vote":vote, "contr":contr, "div":div, "action":action})out = df.groupby("asset", sort=False).apply(arbiter).reset_index()print(out.sort_values(["conf", "score"], ascending=False).to_string(index=False))运行结果:
| asset | score | conf | vote | contr | div | action |
|---|---|---|---|---|---|---|
| MSFT | 0.6640 | 66 | 1.000 | 0.000 | 0.667 | LONG |
| TSLA | -0.5370 | 54 | -1.000 | 0.000 | 0.333 | NO_TRADE |
| AAPL | 0.1100 | 11 | 0.333 | 0.333 | 1.000 | NO_TRADE |
结果解读:
- MSFT:所有策略一致看多,广度充足 → 结论:做多
- AAPL:策略多,但多空打架 → 结论:不参与
- TSLA:方向明确,但只有一个策略提到 → 结论:需要额外审核
小而朴素,这就是它有效的原因。
六、仓位管理:回撤真正被控制的地方
仲裁层回答的是 “买什么”,而仓位管理回答的是 “买多少”。
这里有一个学术界也有支撑的思路:根据近期波动率来调整仓位。
实际操作中,我有三条防线:
| 防线 | 规则 |
|---|---|
| 波动率目标 | 近期ATR或实际波动率上升时,缩减仓位 |
| 单票上限 | 任何一只股票不能占用过多风险敞口 |
| 回撤节流 | 账户回撤超过X%时,新开仓位缩减Y% |
📌 观点总结
- 多个策略信号打架时,不要随便选一个就执行,要先”仲裁”。
- 仲裁层打分看4个维度:方向共识、策略广度、矛盾惩罚、分数压缩。
- 矛盾不是噪音,是成本——要诚实地把它算进决策。
- 仲裁层只管”买什么”,仓位管理才是控制回撤的关键。
- 代码逻辑不复杂,关键是坚持执行、有记录可查。
你现在用什么方式处理策略打架?
评论区聊聊,我挺想看看大家各自的做法。
风险提示:本文仅供参考,不构成投资建议。投资有风险,入市需谨慎。版权声明:本文为原创内容,转载请注明出处。
Be First to Comment