FaceCat-Kronos实战:基于大语言模型的做市商K线规律预测
2026/9/10 10:30:18 网站建设 项目流程

简介:FaceCat-Kronos是花卷猫量化研究团队自主研发的金融量化预测工具,依托清华大学开源的Kronos框架与人工智能技术,对股票历史数据进行深度预训练,辅助做市商及中短线交易者捕捉K线规律,发掘传统方法难以发现的复杂模式。资源共43个文件,压缩包仅1.41MB,以Python代码为核心(23个py),涵盖模型模块、训练/推理示例、Qlib数据接入、Token器训练、无交易量预测等脚本,并带有可视化图片、配置JSON、说明文档及附赠Word资料,目录结构清晰,便于快速定位与二次开发。已有482人学习浏览,适合量化研究者、金融算法工程师以及具备一定编程基础、希望入门AI选股或复现K线预测流程的进阶学习者。通过源码可同时理解Kronos时序建模思路与FaceCat封装工程实现,从数据预处理、模型训练到预测推理均有对应可运行实例,是一份紧凑且可实际运行的参考包。

1. Kronos 凭什么做做市商 K 线规律预测

在行情快照高度内卷的做市场景里,传统技术指标给出的信号往往滞后一到两根 K 线,而纯统计模型又很难同时吃下不同周期、不同标的的波动规律。FaceCat-Kronos 的思路是把整个股票历史 K 线当成“金融文本”:先用类似语言模型的方式做深度预训练,让模型理解价格序列里的重复结构,再做做市商 K 线规律预测。底层依赖的是清华大学开源的 Kronos 框架,它没有沿用 LSTM 或 Transformer encoder 的老路,而是把时间序列 token 化之后交给类 Llama 的 decoder-only 结构去预测下一个 patch。目录里既有 CPU 推理脚本,也有依赖 facecatcpp.dll 的本地可视化端,适合想快速用上预训练模型又不打算从头搭训练管线的量化研究人员、做市策略工程师和 AI 相关专业的学生。

2. 拆解 FaceCat-Kronos 的目录设计与技术底座

2.1 examples、model、finetune 三层源码结构

解压后的facecat-kronos-main目录分层很清晰,三个文件夹分别对应推理、模型定义和训练管线,直接按功能切分而不是按文件混排。根目录下的README.mdREADME.en.md是双语文档,说明文件.txt附赠资源.docx一般是作者补的部署笔记,安装依赖前建议先扫一眼这两个文件,里面往往包含权重文件的放置路径和已知问题记录。

路径作用
examples/cpu_prediction_example.py纯 CPU 环境下跑上一次 K 线预测,适合无 GPU 的调试机
examples/prediction_example.py默认推理示例,自动选择 GPU/CPU,带成交量输入
examples/prediction_wo_vol_example.py不依赖成交量数据的简化版预测,适合只有 OHLC 的市场
model/module.pyKronos 网络结构定义,包含 patch embedding、transformer layer
model/kronos.py对外暴露 KronosPredictor、KronosTokenizer 等高层接口
finetune/train_predictor.py基于 PyTorch Lightning 的预测头训练入口
finetune/train_tokenizer.py分位数 tokenizer 训练脚本,用历史数据重新生成码本
finetune/dataset.py序列滑窗采样与批量读取,负责把 K 线切片成训练样本
utils/qlib_data_preprocess.py把 qlib 标准格式的 CSV 数据转成训练/推理可用的 npy 序列
facecat/main_pyside.py基于 PySide 的桌面端,加载模型后直接在本地 K 线图上显示预测结果

实际跑起来时建议先用prediction_wo_vol_example.py通流程,再切到带成交量输入的prediction_example.py。后者多了量能相关的 token,输入构造上要额外对齐成交量序列和价格序列的时间索引。facecat目录下的facecat.py是封装 C++ 动态库的 Python 桥接层,它不参与模型计算,只在渲染和读取行情图片时做加速。

2.2 requirements.txt 与 CPU/GPU 推理分支

requirements.txt的内容大致围绕 PyTorch、numpy、pandas 展开,GPU 机器上一般还要额外安装对应 CUDA 版本的 torch。先看文件内容再决定用哪套环境,不要无条件pip install -r requirements.txt

# 建议先创建独立虚拟环境 conda create -n facecat python=3.10 -y conda activate facecat # 安装基础依赖(requirements.txt 里通常不含 torch,需要按硬件选装) pip install -r requirements.txt # CPU 版 pip install torch --index-url https://download.pytorch.org/whl/cpu # GPU 版(以 CUDA 12.1 为例) pip install torch --index-url https://download.pytorch.org/whl/cu121

如果只做推理复现,建议 CPU 版 torch 就够了,Kronos 模型在单条序列上不需要大矩阵并行,seq_len在 512 以下时 CPU 推理速度尚可。requirements.txt中还有pandasnumpytqdmpyyaml这类常规依赖,其中pyyaml用于读取config.py里的参数配置,训练环境还需要pytorch-lightningtensorboard,这两项在很多精简版 requirements 里不会写全。提示:如果启动main_pyside.py闪退,优先确认PySide6是否安装,它是桌面端的唯一图形依赖。

2.3 为什么是 Llama 式 decoder-only:patch 与 tokenizer 的含义

Kronos 的核心不只是“用 Transformer 预测 K 线”,而是把连续价格序列映射成离散 token,这一步决定了整个模型的表达能力。常见做法是把长度为patch_size的连续 K 线窗口(比如 16 根 K 线的 OHLC 归一化值)压缩成单个 token,然后在码本里找到最近的分位数向量作为该窗口的离散表示。训练好 tokenizer 之后,原始的浮点价格序列变成一段 token 序列,后续预测任务就是标准的自回归式 next-token prediction。

这种设计的直接好处是解决了金融数据非平稳的问题。传统回归模型直接预测未来价格数值,遇到风格切换时误差会迅速放大;而 tokenizer 把预测目标限制在码本空间里,模型只需要决定“下一段窗口落在哪个分位区间”,鲁棒性更强。decoder-only 结构则让预测头可以复用预训练阶段学到的市场结构信息,微调做市商场景时只更新最后几层,收敛速度远快于从零训练的 LSTM。FaceCat-Kronos 在model/kronos.py中暴露的KronosPredictor类,内部就是把 tokenizer 输出接上若干层自注意力,再输出未来预测区间的分位数序列,整体思路和自然语言处理里的 causal LM 高度一致。

3. 推理实战:从 examples 跑通单标的 K 线预测

3.1 最小复现:cpu_prediction_example.py 的调用方式

examples/cpu_prediction_example.py的设计目的是在没有任何独显的机器上验证模型能否正常加载和推理。脚本核心逻辑很直接:读取历史 K 线文件,转成模型输入张量,调用KronosPredictor输出未来 K 线预测。它的参数大多从命令行传入,也可以直接改脚本里的常量。

python examples/cpu_prediction_example.py \ --data-path data/example.csv \ --seq-len 512 \ --pred-len 32 \ --device cpu

seq_len是回看窗口的 K 线数量,也就是用最近多少根 K 线来预测未来,512 表示约两天的分钟级数据,日线数据建议减到 128 或 64,否则输入窗口跨度过长容易覆盖多个不同行情阶段。pred_len是预测未来 K 线根数,做市商场景下 16 到 32 比较合理,太长时预测的分位数区间会明显变宽。device参数在 CPU 脚本里固定为 cpu,但代码内部仍保留cuda分支,方便直接改设备名切换。

输出的并不是一根确定性的 K 线,而是一组分位数预测结果,通常是未来pred_len根 K 线的 open、high、low、close 的 0.1、0.5、0.9 分位值。拿 0.5 分位作为基准预测,0.1 和 0.9 分位作为风险区间,这样在做市报价时可以直接把买卖价差设在中位数附近,避险时参考分位宽度。

3.2 无成交量输入的简化模式:prediction_wo_vol_example.py 的使用场景

prediction_wo_vol_example.py这个文件名里的wo_vol是 without volume 的缩写。很多国外数据源的分钟线成交量字段缺失或对齐异常,而 Kronos 预训练时如果同时混入了含成交量和不含成交量的序列,推理时就必须保持一致的输入格式。作者单独抽出这个脚本,就是为了解决只拿到 OHLC 数据时的推理兼容问题。

import torch from model.kronos import KronosPredictor, KronosTokenizer tokenizer = KronosTokenizer.from_pretrained("model/tokenizer.json") predictor = KronosPredictor.from_pretrained("model/checkpoints/kronos_facecat.pt") # 输入: (seq_len, 4) -> open, high, low, close kline_input = torch.tensor(data, dtype=torch.float32).unsqueeze(0) with torch.no_grad(): pred_tokens = predictor.predict(kline_input, pred_len=24) pred = tokenizer.decode(pred_tokens) # (1, 24, 4)

这个分支内部会把输入形状从(batch, seq_len, 5)截断成(batch, seq_len, 4),也就是自动丢弃最后一列成交量。代码中的关键点在于KronosPredictorpredict方法不是一次生成全部预测 token,而是循环调用forward,每一步把上一步预测的 patch 拼回输入序列。如果你看到推理速度偏慢,问题往往出在这个循环次数等于pred_len上,而不是模型本身参数量大。

3.3 预测结果的还原与做市商信号加工

模型输出的分位数序列是在标准化空间里的,直接拿去做市没有意义。脚本末尾通常带着inverse_transform的逆归一化,但在做市商实盘建议里,更重要的一步是把“预测的 close 中位数”转换成具体策略信号。

base = close_series[-1] future_med = pred_closes[:, 0.5] # (pred_len,) future_up = pred_closes[:, 0.9] # 如果未来 16 根 K 线的 90% 分位价格高于现价 0.3% 以上,则维持正库存 signal = "long_bias" if (future_up[-1] - base) / base > 0.003 else "neutral"

注意这里用future_up而不是用未来中位数,是因为做市商面临的不对称收益:方向判断错误时,中位数信号没有提供任何风险管理信息,而 0.9 分位可以当作“最坏情况下的上涨空间”。如果你想更保守,可以同时要求 0.1 分位不低于现价下方某个阈值,否则即使中位数看涨也选择缩小报价宽度而不是加仓。这是做市商 K 线规律预测和设备端模型推理之间最容易忽略的衔接环节。

4. 微调一条真正的量价时间序列模型

4.1 数据工程:qlib_data_preprocess.py 的工作流

utils/qlib_data_preprocess.py表明作者采用 qlib 作为数据中间层。qlib 是量化投研领域常见的开源平台,它会把原始行情整理成“交易日历 + 股票列表 + 逐字段二进制”的格式。FaceCat-Kronos 里这个脚本做的是反向操作:把 qlib 的 CSV dump 导出成模型训练需要的时间序列样本。

# 先用 qlib 导出 CSV(这里以 qlib 已初始化数据目录为前提) python -m qlib.run.get_data --qlib_dir ~/.qlib/qlib_data/cn_data \ --region cn --start 2020-01-01 --end 2024-12-31 --freq 1d # 再执行项目自带的预处理脚本 python utils/qlib_data_preprocess.py \ --input-dir ~/.qlib/qlib_data/cn_data \ --output-dir data/processed \ --seq-len 512 \ --pred-len 32 \ --mode train

脚本内部会做三件事:第一,把所有股票的日线序列按绝对时间对齐,只保留交易日历上的日期;第二,对每只股票单独计算 z-score 归一化,避免高价股和低价股在 tokenizer 训练时互相干扰;第三,用滑窗切出(seq_len + pred_len)长度的子序列,前段做输入、后段做预测标签,输出为npy文件。mode参数切到test时不生成标签,只保留输入段,用于后面推理验证。

常见坑:qlib dump 出来的文件路径是按市场代码分目录的,--input-dir要指向包含calendarsinstrumentsfeatures的根目录,而不是 features 内部。判断标准是脚本里是否有open(days_path)之类的读取日历文件行为,如果有,你传的路径就必须同时能看到calendars/day.txt

4.2 训练 tokenizer 与 predictor 的参数对照

finetune目录下,训练过程被拆成 tokenizer 训练和 predictor 训练两个阶段。train_tokenizer.py负责拟合价格序列的分布,产出码本文件;train_predictor.py则在固定 tokenizer 的情况下训练预测头。两个脚本共享config.py中的参数,但同一参数在两个阶段表达的含义不同。

# config.py 中的示例配置(实际以项目内文件为准) config = { "patch_size": 16, # tokenizer: 每个 patch 覆盖 K 线根数 "vocab_size": 4096, # tokenizer: 码本容量 "d_model": 768, # predictor: 注意力隐层维度 "n_layers": 12, # predictor: transformer 层数 "seq_len": 512, # predictor: 输入 K 线数 "pred_len": 32, # predictor: 预测 K 线数 "batch_size": 64, "lr": 1e-4, "weight_decay": 0.01, }
参数tokenizer 阶段含义predictor 阶段含义
patch_size一个 token 覆盖的 K 线窗口长度输入序列被 reshaped 的基础块大小
vocab_size分位数码本条目数分类头输出维度
seq_len训练 tokenizer 时截取的单段序列长度模型输入窗口,影响显存占用
lr码本更新步长,一般用 1e-3transformer 全参数微调用 1e-4,冻结编码器时用 5e-5

训练顺序不能颠倒。tokenizer 不收敛时,predictor 无论训练多久都不可能学到有效规律,因为离散 token 一直漂移。先跑train_tokenizer.py,确认训练损失降到稳定水平后,再检查model/tokenizer.json是否生成,最后执行train_predictor.py

4.3 在本地复现时最容易出错的三个配置问题

第一个问题是batch_size显存爆炸。seq_len=512d_model=768时单条样本已经是几十万浮点数,如果显存只有 8GB,batch_size调到 8 就是极限,建议先用 4 验证前向和反向传播正常,再逐步加大。第二个问题是数据集里含大量停牌垃圾样本。qlib 预处理脚本默认会把 NaN 填充为 0,但如果你在训练集生成前没有过滤amount=0的交易日,模型会学到“连续零成交量”这种虚假规律。第三个问题是 tokenizer 训练和 predictor 训练用了不同的归一化参数。qlib_data_preprocess.py输出的scaler.json一定要同时保留,并用它来预处理后续推理数据,否则预测结果会出现整体偏移。

5. 附带资源中的 facecatcpp 加速与 PySide 看盘界面

5.1 facecatcpp.dll 加速与图形输出

facecat/facecatcpp.dll是 FaceCat 团队封装的 C++ 扩展库,核心解决两个问题:一是大规模 K 线数据的快速渲染,二是把 PySide 界面里的高频刷新从 Python 层解放出来。facecat.py通过 ctypes 加载这个动态库:

import ctypes dll = ctypes.CDLL("facecat/facecatcpp.dll") dll.CreateKLineView.restype = ctypes.c_void_p view = dll.CreateKLineView()

加载成功后会返回一个窗口句柄,main_pyside.py拿这个句柄往 PySide 的QWidget上贴图。日常使用时你不需要直接调这些接口,直接运行python facecat/main_pyside.py即可看到封装好的界面,模型预测结果会以虚线绘制在当前 K 线的右侧。

5.2 用 main_pyside.py 把预测接进本地 K 线界面

桌面端配置好模型路径后,启动命令很简单:

python facecat/main_pyside.py \ --model-path model/checkpoints/kronos_facecat.pt \ --tokenizer-path model/tokenizer.json \ --data-dir data/csv

界面里会同时显示历史 K 线和未来预测区间,预测区域默认用半透明色带表示 0.1 到 0.9 分位。色带宽度大说明模型不确定性高,此时做市商应主动收窄挂单量;色带窄且中位数线朝一个方向延伸,才是相对高置信度的行情信号。如果你把鼠标悬停在预测色带上,状态栏会显示当前预测位置对应的未来时间和分位价格。

5.3 值得补做的验证:把预测落成可回测的 PnL

代码包里没有现成的回测引擎,但你可以把pred_len的预测结果平移到历史数据上做 rolling 验证。常见做法是:对每个交易日 t,用t-1时刻之前seq_len根 K 线做预测,把预测的 0.5 分位 close 和真实 close 做差,统计绝对百分比误差;如果误差中位数大于 1%,优先检查scaler.json是否匹配;误差分布右偏说明预测系统性高估,需要在inverse_transform后减去偏差项。最后用不超过 20 行的 pandas 脚本就能把预测序列和真实序列画在一起,这比任何日志指标都更能暴露边界问题。验证时要注意避免以未来数据回填输入窗口,即预测第 t 根 K 线时只能用 t-1 及之前的信息,这是做市策略回测数据泄漏最常见也最隐蔽的错误。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询