在近乎完美随机里找边:我对 PK10 的一年工程化研究

说明 :这是一篇个人学习记录,不构成任何形式的实盘建议。

文章中的所有实验都是在「已知长期负期望」的前提下进行的,目的只有一个:
用工程化的方法,把"为什么赢不了"这件事搞清楚

1. 引子:动机与设定

这一年,我把很多业余时间都砸在了 PK10 上。

不是为了「一夜暴富」,也不是相信什么「绝技」,而是想用工程化的方式回答一个简单又直白的问题:

在一个开奖几乎完全随机、赔率又让玩家天然负期望 的游戏里,

还能不能通过策略和模型,找到哪怕一丁点「可利用的规律」?

如果只看理论,答案很残酷:不行。

------ 随机独立 + 负期望,本来就意味着「长期必输」。

但我并不满足于"相信结论",而是想自己动手,用代码和数据走一遍,从另一个角度把这件事证明给自己看。同时,也借这个过程练习数据工程、统计、机器学习、深度学习、强化学习这些工具。

一年下来,结果基本可以先写在前面:

  • 从统计分布到相关性检验,PK10 的历史开奖非常接近一个独立同分布的随机过程
  • 在这种前提下,不论是规则策略、传统机器学习、深度网络还是强化学习,
    都没办法稳定地打破负期望,只能短期「好看一下」,最终回归亏损。

但这段折腾的过程本身很有价值:

我一步步把自己最初零散的脚本,整理成了一个相对完整的「个人量化实验室」,也在实践中理解了很多书本上的概念。

这篇文章就是对这一阶段的总结:

整理我做过的事情、用过的方法、得到的结论,以及接下来我打算怎么继续玩下去。


2. 游戏与数据:PK10 作为一个随机过程

2.1 游戏规则简述

PK10 的基本规则(这里只保留和本文相关的部分):

  • 每期从 1~10 这 10 个数字中,产生一个全排列

  • 10 个位置分别称为「第 1 名」到「第 10 名」;

  • 常见玩法包括:

    • 某个位置的大小(1-5 为小,6-10 为大);
    • 某个位置的单双(奇数为单,偶数为双);
    • 冠亚和及其大小、单双等。

这意味着:

  • 每一期开奖中,「大/小」各自恰好出现 5 个,「单/双」也各自恰好是 5 个;
  • 真正随机的部分在于:每个数字出现在每个位置上的概率是否均匀,彼此是否独立

这恰好非常适合作为一个「随机序列实验室」。


2.2 数据规模与采集

为了做长期的统计与回测,我从公开接口抓取了 PK10 的历史开奖数据,并存到本地数据库和 CSV。

大致数据量级是:

  • 每天 1152 期
  • 一个阶段的数据大约覆盖数十万期;
  • 每期有 10 个位置的号码,以及我额外派生出来的「大/小、单/双、冠亚和值」等字段。

数据抓取与清洗主要由一组脚本完成,比如:

  • 从接口拉原始 JSON,转成统一格式;
  • 保存为 CSV/SQL,方便做批量统计和回测;
  • 建立简单索引,支持按时间窗口检索数据。

这一块虽然没什么花哨算法,却是后面所有研究的基础。


2.3 初步统计:接近完美的均匀性

拿到数据之后,第一个问题其实很朴素:

各种简单统计量,是不是如理论所说那样「非常平均」?

我对每个位置、每种属性做了大样本统计,包括:

  • 各位置的大/小比例
  • 各位置的单/双比例
  • 数字 1~10 在各位置出现的频率;
  • 各种组合(比如「第 1 名为大且单」)的频率。

结果非常接近直觉上的「完美随机」:

  • 每个位置上,大/小出现的比例都在 49.x% ~ 50.x% 之间;
  • 每个数字在各位置出现的频率,基本都在 接近 10% 的范围内波动
  • 随着样本量增大,这些比例整体会缓慢往 50% / 10% 靠拢。

这些数字并不惊艳,却构成了一个关键信号:

如果系统存在某种偏差,它要么非常非常小,要么在我现有的数据量和方法下检测不到。


2.4 相关性检验:前后期几乎独立

均匀性只是第一步,更关键的问题是:

开奖期与期之间,有没有可利用的相关性或结构?

我做了一些简单而直接的检验:

  • 计算「某个位置当前期是大/小」与「下一期是大/小」之间的条件概率;
  • 计算不同位置之间在同一期内的相关性;
  • 做类似 NIST 随机性测试的游程检验、区块检验等。

结论可以一句话概括:

在统计误差范围内,前后期几乎可以当作独立事件

比如,对于某个固定位置:

  • P(下一期是大∣当前期是大) 与
    P(下一期是大∣当前期是小) 非常接近,都围绕 50% 左右小幅波动。

这意味着:

  • 我们肉眼看到的「连大」「补偿」「走势」,
    很大程度上只是随机序列中自然会出现的模式
  • 用这些模式作为下注依据,从数学上讲是站不住脚的。

也正是在这样的背景下,我开始了后面的各种策略与模型实验:

一方面是「不甘心」,另一方面也想用实际回测来印证这些理论。


3. 我到底在找什么:研究问题拆解

如果把各种尝试抽象一下,其实就围绕着三个核心问题:

Q1:有没有稳定的统计偏差?

也就是说:

  • 在长期数据上,是否存在某些玩法,其真实胜率 大于 赔率隐含的胜率?

如果存在这样的偏差,那么哪怕只高出 1%,只要回测和统计显著,就有理论上的「正期望策略」可以挖。


Q2:在短期窗口内,能不能预测走势?

即使长期完全均匀,短期区间内仍然可能出现偏离:

  • 未来 5 期、第 7 名是不是更有可能开「大」?
  • 未来 10 期里,某个位置出现某个数字的次数是否会「多于平均」?

很多人日常下注时,直觉其实就是在做这种「短期预测」。

我想用模型把这种直觉形式化:看看在现实数据上,能否在未来 5~10 期这种尺度上,获得哪怕稍微高于 50% 的胜率。


Q3:在负期望前提下,还能做什么?

假设前两个问题的答案都是悲观的,那第三个问题就是:

  • 在负期望已成定局的前提下,是否可以通过:

    • 资金管理;
    • bandit 或强化学习;
    • 过滤下注时机;

    来让:

    • 短期内盈利的概率更高一点,或者
    • 总体亏损的速度更慢一些

这个问题已经从「如何赢钱」转成了「如何在注定输的游戏里,控制自己的下落方式」。

这种思路在真实的金融风险管理里反而非常常见,也算是我继续研究下去的一个动机。


4. 方法路线 1:特征工程 + 传统机器学习

最系统的一条线,是把 PK10 的某个玩法,直接建成一个标准二分类问题,然后用传统机器学习来做预测。

4.1 特征设计:滚动窗口下的各种统计量

以「某个和值是否为小」为例,我构建了大量基于滚动窗口的特征,包括:

  • 过去 24 / 48 / 96 / 192 / 384 期的:

    • 平均值、标准差、最大值、最小值;
    • 最近几期的平均数(前 4、8 期);
    • 指数加权平均(EWMA);
  • 衍生的逻辑特征:

    • 当前和值与历史均值的偏差(z-score);
    • 过去窗口中「小」出现的频率、连开情况等。

这些特征的目的是:把我们脑子里那些「走势」「偏离均值」「该回调了」之类的感觉,转成明确的数值指标。


4.2 模型:Logistic + GBDT + Stacking

在模型端,我主要做了两种组合:

  1. 单模型版本

    • 以 Logistic 回归为主,简单直接,可解释性强;
  2. 集成版本

    • LightGBM + XGBoost + Logistic 的 stacking;
    • 使用 KFold 做 out-of-fold 训练,尽量避免过拟合。

这两类模型都是在严格的时间顺序下训练与验证:

用早期数据训练,用中期数据做验证调参,最后再留出一段数据做真正的测试。


4.3 信号生成与下注规则

模型给出的是「下一期是小的概率 ppp」,

我并不是在每一期都下注,而是做了阈值过滤

  • 当 ppp 非常高(比如进入 top 15%)时,只押「小」;
  • 当 ppp 非常低(比如进入 bottom 15%)时,只押「大」;
  • 其他时候跳过,不下注。

这样做的逻辑是:

只在模型「最有把握」的时候出手,宁可少下注,也要避免完全随机的情况。


4.4 回测与现实约束:从「暴利」到「认输」

在最早期的回测版本里,我用的是一系列非常理想化的假设:

  • 下注金额固定;
  • 不考虑限注和其他现实限制;
  • 可以随意在任意多盘口上下单。

在这些假设下,某些模型的回测曲线很好看,甚至出现了持续盈利 的阶段。

但随着我逐步把现实约束加回来(这也是这条线真正有意思的地方):

  1. 限制单期、单玩法的下注金额;
  2. 限制每天的总下注次数;
  3. 计入佣金、滑点等因素;

我计算了多个版本的每日收益:

  • daily_profits.csv:理想假设下的收益;
  • daily_profits_corrected.csv:加入部分现实约束后的收益;
  • daily_profits_realistic.csv:较完整考虑现实条件后的收益。

最终,在「现实版」的语境下,

这套看起来颇有技术含量的 stacking 策略,

在长样本期上总体亏损 约几万单位

和简单的固定押大/押小相比,本质上只是曲线更曲折了一些。

这一条线让我非常直观地意识到:

在一个独立随机 + 负期望的环境里,
即使模型在训练集/验证集上捕捉到了某些模式,
一旦放回到「完整的时间序列 + 现实交易约束」中,最终还是会被负期望吃掉。


5. 方法路线 2:深度学习序列模型

传统机器学习之后,我把思路推进到了深度学习:

既然 PK10 可以看作一个时间序列,那用 CNN / LSTM / Transformer 来挖更复杂的时序模式,会不会有惊喜?

5.1 输入与标签设计

为了充分利用「序列信息」,我对数据做了这样的编码:

  • 取最近 64 期或 128 期;

  • 对每一期的 10 个位置,分别编码为:

    • 是否为大(0/1);
    • 是否为单(0/1);
  • 得到一个类似 [时间步 × 特征通道] 的张量,

    例如:64 × (10 位 × 2 属性) = 64 × 20

在标签上,我尝试过多种设计:

  • 预测下一期某个位置是大/小;
  • 预测未来 6 期内某种组合(如大偶、大小交替等)是否出现;
  • 预测未来一个小窗口内,大/小的数量是否偏离均值。

这些标签本质上都是对「短期走势」的不同刻画方式。


5.2 模型结构:ResNet、CNN、Transformer、LSTM

我实现并尝试了多套架构:

  • 基于 1D CNN 的残差网络(ResNet Tiny);
  • 在 CNN 上叠加简单的 Transformer 模块,试图捕捉更长距离依赖;
  • 传统的 LSTM / GRU 序列模型;
  • 以及多个模型的 ensemble。

这些模型在工程上都是标准套路:

卷积 + 残差块 / 自注意力 + 全连接输出,

训练时用交叉熵损失、Adam 优化器、学习率衰减等。


5.3 训练表现与过拟合问题

在训练集和验证集上,这些深度模型的表现往往会比纯随机略好:

  • 准确率比 50% 高出几个百分点;
  • AUC 有时能到 0.55 或更高;
  • 损失函数相对纯随机基线明显下降。

如果只看这些数字,很容易产生错觉:

「模型学到东西了!」

然而,当我把模型放到严格按时间分割的测试集上,并用真实回测方式去检验时,情况就不那么好看了:

  • 准确率迅速向 50% 靠拢;
  • AUC 在误差范围内徘徊;
  • 不同随机种子 / 不同训练区间得到的模型,在测试集上的表现差异很大,稳定性很差。

这其实正是「在白噪声上做深度学习」的典型症状:

模型会在训练集上努力拟合各种随机噪声模式,但这些模式在未来完全不复存在。


5.4 从深度学习的角度再认识一次「随机」

这条路线给我的最大收获是认知上的:

只要底层过程真的是「独立随机」,

再强大的函数近似器(CNN、Transformer......)也只能努力拟合过去的噪声,

却无法在未来创造出稳定的 edge。

这听起来像是常识,但当你在代码和 GPU 上亲自体验一遍之后,这个结论会刻进骨子里:
模型并不是无所不能,信息边界之外的东西,它也无从下手。


6. 方法路线 3:强化学习与 Bandit

尝试完「先预测,再下注」的思路后,我也玩了一些更"直接"的方法------让强化学习模型自己在仿真环境里学习下注策略。

6.1 环境建模

我把 PK10 简化成一个 RL 环境:

  • 状态:最近 N 期的开奖特征(大小、单双、和值、滚动统计等);

  • 动作

    • 押大、押小、押单、押双,或者不下注;
  • 奖励

    • 单期押中的赢利,押错的亏损,不下注则 0。

在这个环境里,智能体可以自由探索「什么时候下注」「怎么下注」「压哪一边」。


6.2 算法与实现

我做过的尝试包括:

  • 基于 Q 表的小规模 Q-learning;
  • 线性近似 / 简单网络逼近 Q 函数;
  • 多臂 bandit 算法(ε-greedy 等),
    用来在线调整一些策略参数,比如返现比例、下注规模。

这些实验更多是在验证一个直觉:

如果不给它任何"未来信息",只让它在历史数据上反复玩,

强化学习能否自主摸索出一套比人类直觉更好的下注策略?


6.3 结果:学到的只是「如何更体面地输」

现实很有趣,也很诚实:

  • 有些 Q-learning 策略,最终学出来的行为是几乎不下注,只在极少数情况下出手;
  • 有些 bandit 在长时间仿真后,调整出一套「亏得稍微慢一点」的参数;
  • 如果强行规定「每期必须下注」,策略的长期收益仍然明显为负。

这与理论是一致的:

在一个没有任何信息 edge 的赌场游戏里,强化学习无法凭空创造正期望,只能在负期望的框架内调整路径------要么减少参与,要么在局部看起来更顺滑。


7. 全局回顾:从「想赢」到「学会认输」

回头看这一年,其实可以分成三个阶段:

7.1 阶段一:带着幻想上路

最开始,我和很多普通玩家没有本质差别:

  • 觉得走势里可能有「某种规律」;
  • 相信足够聪明的策略、足够复杂的模型,
    能在某些阶段捕捉到高于 50% 的胜率。

于是我写了很多「看起来有道理」的策略:

  • 跨路挑出出现最少的号码;
  • 押「最长没出的那一边」;
  • 盯着连开次数、K 线走势、窗口偏离均值......

短期内,这些策略确实时不时会「表演」一下------

但一旦拉长时间、引入更多数据,所有曲线都逐步滑回负区间。


7.2 阶段二:用模型验证「真的没门」

后来我开始系统地用模型和回测框架来验证这些想法:

  • 统计检验告诉我:

    • 各位置、各数字的分布几乎完美均匀;
    • 前后期之间几乎独立;
  • Logistic / GBDT / CNN / Transformer 告诉我:

    • 在严格的时间切分下,
      模型在未来的表现很难稳定超过随机;
  • 强化学习告诉我:

    • 在没有 edge 的游戏里,
      最稳妥的策略往往是降低参与度

这些都是同一个事实,从不同角度的重复证明。

我也逐渐从「想法不够好」「模型不够强」的自我怀疑中走出来,改成:

信息边界就在那里,在给定的条件下,这个问题本身就没有可行解。


7.3 阶段三:把失败变成方法论

当我接受「靠走势和模型赢不了」这一点之后,这个项目的意义反而清晰了:

  • 我做了一整套数据抓取与清洗的流水线;

  • 搭建了一个支持各种策略与模型的回测框架;

  • 实践了如何:

    • 设计特征;
    • 评估模型;
    • 避免数据泄漏和过拟合;
    • 把看起来漂亮的回测,逐步修正成现实可执行的策略;
  • 也在 RL、bandit 的实验里,

    深刻感受到了「在没有 edge 的环境里,算法的能与不能」。

这些经验完全可以迁移到别的领域:

无论是金融量化,还是对其他随机过程的建模,它们都能发挥作用。


8. 下一阶段:从 PK10 走向更广泛的量化与随机性研究

这一阶段的结论并不浪漫:
在目前的假设和信息下,我很难通过任何走势或模型击败 PK10。

但我并不打算就此停下,而是把它当成一个好的起点,

下一阶段,我大概会往这几个方向继续探索:

8.1 把现有代码整理成一个「随机序列体检框架」

把这一年积累的脚本系统化:

  • 输入:任意时间序列(不一定是 PK10,可以是价格、指标、实验数据);

  • 输出:

    • 基本分布统计;
    • 随机性检验(游程、区块、NIST 风格);
    • 简单 ML / DL 预测基线;
    • 如果连这些模型都学不到东西,就可以大胆假设:这个序列在给定信息下几乎是「白噪声」。

这套工具可以作为以后做量化或实验时的「第一层 sanity check」。


8.2 把回测框架迁移到更有结构的信息源

既然在真正的随机序列上「无计可施」,那不妨把这套 pipeline 用到别的地方:

  • 使用公开金融数据(如指数 ETF、期货连续合约),
    练习最基础的因子选股 / CTA 策略;
  • 用宏观数据、网络数据、业务指标做一些简单预测任务,
    观察在这些有真实结构的场景里,
    模型是否真的能学到可复现的模式。

这样既能保持工程上的连续性,又能把视野扩展到 PK10 之外。


8.3 保持几个原则:少一些幻想,多一些理性

不管下一步研究对象是什么,我大概会坚持这几个原则:

  1. 先算期望,再谈策略

    • 了解规则与成本,搞清楚理论上是不是负期望;
  2. 严格时间切分,拒绝数据泄漏

    • 训练、验证、测试分明,避免自嗨式回测;
  3. 任何「太好看」的曲线,都值得怀疑

    • 优先检查假设、数据质量、样本外表现;
  4. 模型不是魔法,只能在信息允许的范围内工作

    • 不要指望它在真正的白噪声上创造奇迹。

结语

PK10 最终没有给我一套赢钱策略,这一点我现在可以非常坦然地承认。

但它确实给了我很多别的东西:

一套从数据抓取到回测评估的工程流程、一堆亲手踩过的坑、一堆被证伪的念头,以及一个更稳固的概率与随机性直觉。

如果说这一年的研究有什么价值,大概就是:

把「赢不了」这三个字,从别人嘴里的结论,

变成了一套由我自己动手、用数据和模型反复验证过的、

足够让我信服的 个人答案

接下来,我会带着这套答案,去挑战一些不是完全随机 的问题。

至于能走多远,那就是下一阶段故事里的事了。

相关推荐
z***3351 小时前
PON架构(全光网络)
网络·数据库·架构
腾讯云开发者1 小时前
共谈架构师 AI 进化论,腾讯云架构师技术沙龙圆满落幕
架构
国科安芯1 小时前
AS32系列MCU芯片TIM模块的捕获和比较
单片机·嵌入式硬件·fpga开发·架构·risc-v
七宝大爷2 小时前
编码器-解码器架构:理解Transformer的两种基本模式
深度学习·架构·transformer
j***49562 小时前
CentOS7安装Mysql5.7(ARM64架构)
adb·架构
nvd112 小时前
Agent架构升级:解决Gemini超大Prompt处理问题
架构·prompt
稚辉君.MCA_P8_Java2 小时前
DeepSeek Java 多线程打印的12种实现方法
java·linux·后端·架构·maven
JienDa2 小时前
JienDa聊PHP:电商系统实战架构深度解析与优化策略
开发语言·架构·php
n***63272 小时前
华为HuaweiCloudStack(一)介绍与架构
服务器·华为·架构