GPT 5.6 上线第一天,我就想体验体验。
本来随便写个小工具、跑几个提示词,也算体验过了。但想想又没什么意思。新模型到底行不行,还是得拿一个真的麻烦、真的会碰到各种边角问题的项目试。于是我把自己跑了很长时间的 Polymarket ETH 15 分钟策略翻了出来。
这个老版本不是不能用,胜率看着甚至还可以。问题是赚的时候一笔一点点,亏起来却不客气。这个毛病困扰我挺久了,也正好拿来看看 GPT 5.6 sol 到底能把策略推到什么程度。
先说一个有点夸张、但确实是真的事:这次前后大概吃掉了 GPT 5.6 sol 几千万 Token。最后代码复制到 FMZ,一把过,没报错,直接跑起来了。
不过,“能跑”跟“能赚钱”完全是两回事。这个得先讲在前面,不然文章看到一半容易误会。
起因:胜率看着不错,钱却没怎么留下来
我之前已经跑过很长时间的 Polymarket ETH 15 分钟策略。
这个市场很好理解:每 15 分钟一轮,结束价高于开盘参考价就是 Up,低于参考价就是 Down。看起来非常简单,甚至有点像抛硬币。
老版本的胜率其实还可以,但有个挺烦人的问题:平时一笔赚一点,错一次就吐回去不少。有时候连赢好几笔,账户曲线慢吞吞往上爬;碰上一笔大的亏损,前面的努力没了。
这也是预测市场很容易掉进去的坑。
比如 Up 已经卖到 0.85,你买进去,赢了最多赚 0.15,输了却可能亏掉 0.85。粗略看一下,盈亏比已经是:
text
0.85 / 0.15 ≈ 5.67
也就是说,胜率很高不一定赚钱。你付出的价格、手续费、滑点和偶尔一次归零,都会来找你算账。
所以这次重构我没再问“怎么把胜率做得更高”,而是换了一个问题:
这张合约的真实胜率,真的比它的价格高出足够多吗?
说起来就一句话,但后面 4000 多行代码基本都在给这句话擦屁股。
先把三种价格分清楚,不然越做越乱
这个策略同时看 Chainlink、Binance 和 Polymarket。三个地方都有 ETH 的价格,但用途不是一回事。
text
Chainlink RTDS:官方参考价和结算依据
Binance:观察短线领先、动量和波动率
Polymarket CLOB:买卖价格、深度、费用和真正成交
我一开始也很容易下意识把 Binance 当“真价格”,毕竟它更新快,深度又好。但在这个市场里不行。
Chainlink 是裁判
Polymarket 这类 15 分钟市场最后按指定价格源判断输赢。策略必须在每轮边界捕获官方 Price-to-Beat,后面的 Up 或 Down 都围绕它计算。
这里有个很容易偷懒的地方:策略如果在一轮中途启动,能不能把启动时看到的 Chainlink 价格当成本轮开盘价?
不能。差几美元看着不多,放在最后几十秒里可能直接把方向搞反。
所以策略找不到这一轮的正式参考价时,会跳过整轮。刚启动后看它“不交易”,不一定是坏了,它可能只是在等下一轮的正确起点。
Binance 更像场边观察员
Binance ETH/USDT 更新快,适合拿来观察:
- 最近 5 秒往哪边走;
- Binance 和 Chainlink 平时相差多少;
- 当前波动突然变大没有;
- Binance 是否比 Chainlink 先动了一点。
但是 Binance 不负责最终判决。它能给提示,不能替 Chainlink 宣布比赛结果。
Polymarket 才是买东西的地方
模型算出 90% 没用,最后还是得看盘口愿意多少钱卖给你。
比如理论胜率 90%,合约成交总成本已经接近 89%,这种单我宁愿不要。看上去十拿九稳,实际上能赚的空间薄得像张纸,随便一点误差就没了。
策略真正关心的是:
text
净优势 = 保守胜率 - 实际成交价 - 入场费 - 退出成本预留
代码里对应的是:
text
netEdge = conservativeProb - cappedFillPrice - entryFee - exitReserve
注意这里用的是保守概率,也不是盘口第一档摆出来的好看价格,而是按深度估算后的可成交价格。这两处要是乐观一点,回测和实盘可能就是两套东西了。
为什么只盯最后 105 秒到 45 秒
一轮 900 秒,策略真正允许入场的时间只有:
text
T+795 秒到 T+855 秒
换句话说,就是剩下 105 秒到 45 秒。
为什么不从开盘一直找机会?因为太早的时候,ETH 后面还有很长时间可以乱跑。现在领先一点,五分钟后可能已经来回穿了好几次参考价。
那干脆最后十秒买,不是更确定?也不太行。
最后十秒时,网络延迟、盘口抽走、订单状态确认,这些平时不起眼的问题都会突然变得很大。你甚至还没搞清订单到底成交没有,市场已经结束了。真遇到异常,也没时间处理。
105 到 45 秒不是一个神奇答案,只是目前取的一个折中:结果开始变得比较清楚了,同时还留了一点执行余地。以后有足够样本,窗口当然可以继续切开研究。
“领先了多少”,怎么变成一个概率
策略先算 Chainlink 当前价距离本轮参考价有多远:
text
rawGap = direction × log(Chainlink当前价 / 本轮参考价)
如果研究的是 Up,价格高于参考价就是正距离;研究 Down 时把方向反过来。用对数主要是为了让上下涨跌的处理更一致一点。
接着会看 Binance 相对 Chainlink 的领先残差。这个地方我故意做得偏怂:
- 对当前方向有利的 Binance 领先,只信 35%;
- 对当前方向不利的变化,全部算进去;
- 调整最多 3 bps;
- 另外再扣 2 bps,给参考价的不确定性留位置。
简单讲就是,好消息先打个折,坏消息暂时当真的。可能会错过一些机会,但至少模型不容易被自己感动。
然后用最近一分钟 K 线估计短期波动,再按剩余时间缩放:
text
剩余波动 ≈ 每秒波动率 × 压力系数 × sqrt(剩余秒数 + 延迟缓冲)
最后得到 z-score:
text
z = 安全领先距离 / 剩余波动
同样领先 10 美元,在平静行情里可能很安全;碰到一分钟能甩几十美元的行情,这点距离就不算什么。z 值就是想把“距离”和“当前还可能动多远”放到一起比较。
之后用正态分布函数把 z 转成概率。但没有直接拿这个概率下单,还会向 50% 收缩,再扣一层 haircut,并限制最终范围。
当前默认门槛是:
text
z-score ≥ 1.45
保守概率 ≥ 86%
这些参数不是数学真理,只是策略的研究起点。策略运行久了以后,应该用实际结算样本去修它,而不是看着公式挺漂亮就一直信。
概率过关了,还不能买
这一点挺反直觉。模型都说胜率 86% 以上了,怎么还不下单?
因为一个判断正确的信号,完全可能是一笔不划算的交易。
策略还会检查下面这些东西:
- 卖价是不是落在允许区间;
- 买卖价差有没有突然变宽;
- Up 和 Down 的互补价格是不是异常;
- 最近 5 秒有没有突然跳价;
- 短动量是不是正在朝反方向走;
- 扣完费用还剩多少净优势;
- 盘口深度能不能真的装下这笔订单。
普通模式允许的 ask 大约是 0.65~0.86。固定 1 USDC 市价模式更谨慎,最高只买到 0.80。
有人会觉得,上限好理解,为什么低于 0.65 也不买?不是越便宜越好吗。
正常情况下,一个“最后阶段、明显领先、模型胜率很高”的方向,不应该便宜得离谱。如果模型喊 90%,市场却只卖 0.55,先别急着捡漏,更可能是某处数据不同步、参考价有问题,或者市场看到了策略没看到的东西。
便宜有时候是机会,有时候是警报。程序区分不了所有情况,那就先不买。
信号要站稳一会儿,盘口还得重新读
第一次出现入场信号时,策略不会立刻冲进去。默认需要连续确认 3 次,而且至少持续 800ms。
这里也不能拿主循环重复读到的同一笔报价,硬算成三次确认。关键判断会要求跨过新的源 tick,否则一个卡住的旧价格,也可能被误认为信号很稳定。
确认完成以后还没结束。真正发单前,策略会:
- 重新拉 Up、Down 两边完整 REST 深度;
- 从头再跑一次概率和盘口条件;
- 按新深度计算 VWAP、手续费和净优势;
- 1 USDC 市价模式再单独刷新目标侧盘口。
重新检查时只要有一项不满足,这轮就算了。
这会损失一点速度,肯定会。但我更怕拿着 800ms 前的盘口去买现在的市场。15 分钟盘到最后阶段,800ms 有时已经不是很短了。
1 USDC 下单是认真交易,不是接口演示
这个版本专门做了一条固定 1 USDC 的市价买入路径,主要就是给小资金实盘研究用。
按 FMZ 的 Polymarket 适配方式:
- 市价
BUY的 amount 按 USDC 金额; - 市价
SELL的 amount 按 shares 数量; - 限价单通常有最少 5 shares 的限制;
- 市价买入可以按 1 USDC 的订单价值执行。
这样就不用为了凑 5 份,硬把单笔仓位放大。
但有个账不能装看不见:账户如果只有 9 美元,一笔 1 美元加费用,最坏情况就会亏掉账户 11% 以上。连着错几次,钱很快就不够继续收集样本了。所以“一美元而已”只是绝对金额小,百分比风险一点不小。
目前小资金模式加了这些约束:
- 每天最多 2 笔;
- 同时最多 1 个未结算仓位;
- 单笔最坏风险不能超过账户 15%;
- 下一笔若全部亏损,不能越过会话回撤线;
- 吃掉的深度不超过可见深度 15%;
- 允许的入场滑点不超过 1 个百分点;
- 净优势至少 6.5%;
- 最大亏盈比不超过 4.5。
还有个现实问题,挺尴尬的:1 美元买入后,如果仓位跌得很厉害,可卖价值可能低于交易所主动卖出的最小金额。也就是你想止损,订单都发不出去。
所以策略从入场时就按“这张合约可能归零”来计算最坏损失,没有假设止损一定能成交。小单尤其要这样算。
下单代码不难,难的是:它到底成交了没有
策略教程里经常能看到这种代码:
javascript
if (signal) {
exchange.Buy(price, amount)
}
实盘不会这么配合。请求超时了,订单可能没发出去,也可能已经成交;撤单返回成功,之前可能成交了一部分;WebSocket 说成交了,REST 那边还没更新。更麻烦的是,程序刚成交就重启,内存里的状态全没了。
这种问题不处理好,策略不只是算错收益,甚至可能重复买一遍。
所以策略花了很多代码在订单状态机上。大概逻辑是:
- 下单前先写 intent
先把“这一轮准备买什么”持久化,再向交易所发请求。就算中间崩了,重启也知道有一笔事情没查完。 - 同一轮只允许一个 intent
网络抖一下不能变成多买一单。没查清之前,不开第二次尝试。 - 撤单后还要查部分成交
撤掉的是剩余数量,不代表之前一份都没成交。订单回报、成交记录和实际仓位要放在一起核对。 - 市价单也有观察期
API 暂时显示FAILED或CANCELED,不马上认定零成交。策略会交叉查看订单查询、User WebSocket、用户成交 REST 和仓位变化。 - 真查不清,就停
既不能证明没成交,也不能确认成交多少时,策略会 fail closed,停止继续交易,等人工核对。
这个处理有点笨,但比“再发一单试试看”靠谱。少做一次是一笔机会成本,重复买入可能直接变事故。
买对之后,别急着为了几分钱来回折腾
预测市场合约最后正确的一侧兑付 1,错误的一侧归零。如果入场逻辑还成立,频繁止盈往往会多付一轮价差和手续费。
因此策略的基本想法是:赢家尽量拿到官方结算,风险真的变了才主动卖。
会触发退出的情况主要有:
- Chainlink 正式穿越本轮参考价;
- z-score 跌破硬阈值;
- 实际亏损触及硬止损;
- 当前可卖价格已经明显高于模型公允价值;
- 临近结束时关键数据持续失效;
- 软退出信号经过连续新 tick 确认。
如果仓位太小,卖出金额连交易所最小门槛都达不到,策略不会反复发一张肯定会拒绝的单,只能继续等官方结算。
最终输赢只认 Polymarket 的官方市场状态,确认后再进入 redeem 流程。Binance 涨没涨、自己觉得赢没赢,都不算数。
先让它“假装下单”,样本够了再说
策略默认是:
javascript
var SimMode = true
模拟模式不是只看屏幕上有没有信号。策略会把那些已经满足全部实盘条件、如果开实盘就真会下单的机会,作为影子交易保存下来。
样本按三个维度分桶:
- 入场 ask 区间;
- z-score 区间;
- 距离结算的时间区间。
等市场正式结算后,再给每个桶更新样本数、胜场、实际盈亏、模型优势和 Wilson 单侧置信下界。
这里为什么要搞个听起来有点学术的 Wilson 下界?举个简单例子:10 笔赢了 9 笔,表面胜率 90%,但十个样本实在太少。再来十笔会怎样,谁也不知道。直接拿 90% 填进模型,很容易高估自己。
策略实盘校准时使用:
text
有效概率 = min(模型概率, 经验胜率置信下界)
也就是说,历史样本只能给模型泼冷水,不能把一个普通信号吹成神单。
当前建议至少先收集 300 个影子样本。即使整体样本够了,具体入场桶也至少要有 25 个样本并通过净优势检查。
300 这个数字也不是说到了就毕业,只是比十几二十笔靠谱一些。市场状态会变,样本分布也会偏,这些后面都还要继续看。
状态栏和 JSONL,其实比漂亮曲线更有用
一个策略跑几天之后,如果日志里只有“买入成功”和“卖出成功”,基本没法研究。
策略的 FMZ 状态栏会显示当前轮次、参考价、Chainlink 和 Binance 数据年龄、方向、z-score、概率、盘口、费用、净优势、账户风险、影子样本以及最近结算等信息。
详细事件还会写进:
text
pm_eth15_alpha_v8.jsonl
里面会记录信号为什么被拒绝、当时的波动率、影子策略快照、订单 intent、部分成交、仓位诊断、官方结算和恢复过程。
这些日志短期看很啰嗦,跑久以后反而是最值钱的部分。因为我真正想查的不是“它昨天赢了几笔”,而是:
- 0.70 买入和 0.80 买入,哪个最后净收益更好?
- 高 z 的胜率有没有真的更高?
- 剩余 45~75 秒和 75~105 秒,差别多大?
- 纸面 edge 最后兑现了多少?
- 利润到底被手续费、滑点还是退出逻辑吃掉了?
不把当时现场留下来,过两天再看账户曲线,很多解释都只是脑补。
几千万 Token,都花哪儿了
这个数字确实很抓眼球。要是只让 AI 写个均线交叉,花这么多 Token 肯定离谱。
但这次大量消耗不在“预测下一分钟涨还是跌”,而是在各种很碎、又绕不开的边界问题上:
- 官方参考价怎么捕获和恢复;
- 三套数据的时间戳怎么对齐;
- Binance 只能辅助,不能污染结算口径;
- 概率收缩和费用到底先算哪个;
- 市价 BUY 的 USDC 与持仓 shares 怎么记;
- 最小订单、部分成交和订单状态冲突;
- 程序恰好在关键位置重启怎么办;
- 如何避免同一轮重复下单;
- 影子策略和以后实盘用的是不是同一套条件;
- 官方结算后什么时候才能 redeem。
这些单独看都不算高深,凑到一起就很磨人。改一个口径,状态栏、持仓记账、风险计算和日志可能全要跟着动。很多 Token 就耗在来回核对这里。
“一把过,零报错”对我来说最有意思的地方,也不是 AI 证明了自己会赚钱。而是这么长的一套 FMZ 策略,第一次复制进去,WebSocket、状态栏、模拟流程和日志就都启动了。工程上确实省了不少折腾。
至于 Alpha 有没有,还是得老老实实等样本。代码不会因为写得长,胜率就自动增加,这个没办法骗。
如果你也要跑,我建议先别急着关模拟
我自己的顺序大概会是这样。
先保留:
javascript
var SimMode = true
确认 Chainlink、Binance 和 Polymarket 三路连接正常,状态栏里的数据年龄不会频繁变红,JSONL 也在持续写。
启动时间最好靠近新一轮开始之前。如果中途启动后策略跳过当前轮,不要急着删保护代码,等下一轮看参考价能不能正常捕获。
然后收集影子样本。300 笔只是第一道线,重点还是看每个桶的样本量、Wilson 下界、平均实际盈亏,以及理论 edge 和最后兑现之间差多少。
接下来先查费用,再看胜率。预测市场最会制造一种错觉:交易记录一片绿色,余额却不怎么动。把实际成交价、费用和完整亏损放进去算,才知道是不是正期望。
最后才考虑小额实盘。即便固定每次只买 1 USDC,也要确认账户、签名方式、User WebSocket、最小订单规则和 FMZ 当前适配行为都一致。
准备好后才是:
javascript
var SimMode = false
9 美元账户理论上能跑 1 美元模式,但容错空间真不大。它更适合验证真实成交和记账链路,不适合用来证明策略长期有效。连续几笔不顺,样本实验就可能提前结束了。
最后说几句
polymarket_eth15m_alpha_v8 看起来是在预测 ETH 最后涨还是跌,其实大部分时间都在拒绝交易。
参考价不确定,不做。数据旧了,不做。盘口太宽,不做。费用扣完没优势,不做。深度不够也不做。订单状态查不清,干脆停下来。
它真正下单的动作可能就那么一下,前面却堆着一大串“不行”。
以前我会觉得策略有信号却不买,好像错过了钱。现在反而觉得,能把不划算的高胜率交易过滤掉,也许才是这个版本最有价值的地方。
GPT 5.6 sol、几千万 Token、一把过、0 错误,这个故事当然挺适合拿出来讲。我自己也觉得有点不可思议。
但策略最终能不能活下来,不看 Token,也不看代码行数。就看一件事:
市场卖给你的概率,是否真的比它值的价格便宜。
剩下的,交给样本慢慢回答吧。
完整策略源码
最后,策略分享给大家。以下策略源码可以直接复制到 FMZ 的 JavaScript 策略中。
源码默认 SimMode = true。读者复制后会先进入模拟和影子样本模式,实盘交易需要修改一下模式。
风险提示
本文只是策略研究和程序设计分享,不构成投资建议,也不承诺收益。预测市场合约可能归零,还存在流动性、滑点、接口、费用、结算、监管和智能合约等风险。策略零报错启动,不代表逻辑零风险,更不代表以后可以稳定盈利。实盘前请先做足模拟、影子样本校准和小额验证。
- 1




