青年是整个社会力量中的一部分最积极最有生气的力量。他们最肯学习,最少保守思想,在社会主义时代尤其是这样。——毛泽东

https://github.com/shiyu-coder/Kronos

当金融市场开始“说话”:认识 Kronos 这位读 K 线的基础模型

在很多人的印象里,K 线图像一张沉默的地图:开盘、收盘、最高、最低,外加成交量和成交额,把市场一天、一小时,甚至几分钟的情绪,压缩成一根根蜡烛形状的线段。它不解释,只呈现;不说话,却总像在暗示什么。

而 Kronos 做的事情,恰恰很有意思——它试图把这种“沉默的表达”当成一种真正的语言来理解。

Kronos 的项目 description 只有一句话,却已经把它的定位说得很清楚:

Kronos: A Foundation Model for the Language of Financial Markets

README 进一步补上了更有分量的一句介绍:Kronos 是首个开源的金融蜡烛图基础模型,面向金融 K 线,训练数据来自全球超过 45 个交易所。这不是把通用模型硬套到金融序列上,而是从一开始就把目标锁定在 K-line sequences 这一类特殊对象上。

项目地址:https://github.com/shiyu-coder/Kronos


它想理解的,不只是时间序列,而是“市场语言”

Kronos 在 README 里的核心表达非常鲜明:它是一个decoder-only 的基础模型家族,专门为金融市场的“语言”——也就是 K 线序列——进行预训练。

这里最值得玩味的,是“语言”这个比喻。

在一般叙述里,K 线常被当作数值序列、特征集合,或者预测输入;但在 Kronos 的视角中,它更像一种有结构、有上下文、有组合规则的表达系统。README 提到,Kronos 并不是沿着通用时间序列基础模型的路线前进,而是围绕 K 线自身的表达方式构建了一套专门机制。它大致分成两步:

  1. 先通过一个专门的 tokenizer,把连续的、多维的 K 线数据,也就是 OHLCV 这类信息,量化为分层离散 token
  2. 再用一个大型自回归 Transformer 在这些 token 上进行预训练,从而把模型变成能够服务多种量化任务的统一模型

这两步连起来看,Kronos 的思路就非常完整了:先把市场的连续波动“翻译”成模型更擅长处理的离散符号,再用语言模型式的方法去学习这些符号之间的上下文关系。

如果说传统做法更像是在测量市场,那么 Kronos 更像是在“读”市场。


一个模型家族,而不是单点实验

Kronos 并不是只放出一个模型就结束了。README 给出了一个明确的 Model Zoo,说明它提供了一组不同容量的预训练模型,用来适配不同的计算资源和应用需求。

目前列出的模型包括:

  • Kronos-mini
    • Tokenizer:Kronos-Tokenizer-2k
    • Context length:2048
    • 参数量:4.1M
  • Kronos-small
    • Tokenizer:Kronos-Tokenizer-base
    • Context length:512
    • 参数量:24.7M
  • Kronos-base
    • Tokenizer:Kronos-Tokenizer-base
    • Context length:512
    • 参数量:102.3M
  • Kronos-large
    • Tokenizer:Kronos-Tokenizer-base
    • Context length:512
    • 参数量:499.2M

从这个列表里能看出,Kronos 并不是只考虑“把模型做出来”,也在认真处理“怎么让不同场景的人都能用起来”这件事。轻量版、平衡版、更大容量版本被摆在同一体系里,形成了一个清晰的层次结构。

README 还说明,这些预训练模型可以从 Hugging Face Hub 获取。也就是说,Kronos 的使用方式并不神秘,它不是一个只能停留在论文图里的概念,而是带着可加载、可调用、可运行的形态出现的。


从原始 K 线到预测结果,Kronos 的上手路径很直白

一个项目是否“能看”,和它是否“能用”,往往是两回事。Kronos 在 README 里给出的 Getting Started 部分,相当直接,也相当务实。

安装要求

首先是环境准备。README 写得很清楚:

  • 需要 Python 3.10+
  • 安装依赖使用:
1
pip install -r requirements.txt

没有额外铺陈,也没有复杂前置,入门路径非常明确。


KronosPredictor 做预测:流程被封装得很完整

README 里提到,使用 Kronos 进行预测时,KronosPredictor 是一个很关键的入口。它负责处理:

  • 数据预处理
  • 归一化
  • 预测
  • 反归一化

也就是说,从原始数据到最终输出,中间那一段通常容易“黏手”的流程,被这个类统一接住了。

第一步:加载 tokenizer 和模型

1
2
3
4
5
from model import Kronos, KronosTokenizer, KronosPredictor

# Load from Hugging Face Hub
tokenizer = KronosTokenizer.from_pretrained("NeoQuasar/Kronos-Tokenizer-base")
model = Kronos.from_pretrained("NeoQuasar/Kronos-small")

这一步之后,Kronos 从概念变成了一个真正可实例化的对象。

第二步:初始化预测器

1
2
# Initialize the predictor
predictor = KronosPredictor(model, tokenizer, max_context=512)

这里 README 还特别强调了一点:Kronos-smallKronos-basemax_context512。这代表模型能处理的最大序列长度就是 512。并且为了获得更好的效果,README 建议输入长度尽量接近这个值。

换句话说,Kronos 不只是告诉你“能用”,还把一些与效果相关的使用边界直接写明了。

第三步:准备输入数据

README 对输入要求也写得非常清楚:

  • df:一个 pandas DataFrame,必须包含 openhighlowclose
  • volumeamount 是可选项
  • x_timestamp:历史数据时间戳
  • y_timestamp:未来待预测时间戳

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd

# Load your data
df = pd.read_csv("./data/XSHG_5min_600977.csv")
df['timestamps'] = pd.to_datetime(df['timestamps'])

# Define context window and prediction length
lookback = 400
pred_len = 120

# Prepare inputs for the predictor
x_df = df.loc[:lookback-1, ['open', 'high', 'low', 'close', 'volume', 'amount']]
x_timestamp = df.loc[:lookback-1, 'timestamps']
y_timestamp = df.loc[lookback:lookback+pred_len-1, 'timestamps']

这段代码有一种很“落地”的气质。它没有故意炫技,而是把真实使用时最关键的切片动作展示了出来:历史窗口怎么取,预测长度怎么定,列名怎么组织,时间戳怎么对齐。

第四步:生成预测结果

1
2
3
4
5
6
7
8
9
10
11
12
13
# Generate predictions
pred_df = predictor.predict(
df=x_df,
x_timestamp=x_timestamp,
y_timestamp=y_timestamp,
pred_len=pred_len,
T=1.0, # Temperature for sampling
top_p=0.9, # Nucleus sampling probability
sample_count=1 # Number of forecast paths to generate and average
)

print("Forecasted Data Head:")
print(pred_df.head())

这里最有意思的地方,在于 README 明确提到了 Ttop_psample_count 这些参数,用来控制采样过程,从而支持概率式预测。这让 Kronos 的使用界面带上了一点语言模型世界的味道:不是只有单一路径,也可以通过采样方式来组织预测输出。

而返回结果则是一个 pandas DataFrame,包含:

  • open
  • high
  • low
  • close
  • volume
  • amount

并且以用户提供的 y_timestamp 作为索引。

这意味着,从调用体验上看,Kronos 尽量把输出维持在数据分析人员熟悉的形式里,而不是把结果困在某种生硬的中间张量结构中。


不只会“一条一条看”,它还支持批量预测

如果只有单序列预测,一个模型还像是在安静处理单个样本;而 README 提到的 predict_batch,则让 Kronos 显得更像一个真正准备进入工作流的工具。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Prepare multiple datasets for batch prediction
df_list = [df1, df2, df3] # List of DataFrames
x_timestamp_list = [x_ts1, x_ts2, x_ts3] # List of historical timestamps
y_timestamp_list = [y_ts1, y_ts2, y_ts3] # List of future timestamps

# Generate batch predictions
pred_df_list = predictor.predict_batch(
df_list=df_list,
x_timestamp_list=x_timestamp_list,
y_timestamp_list=y_timestamp_list,
pred_len=pred_len,
T=1.0,
top_p=0.9,
sample_count=1,
verbose=True
)

# pred_df_list contains prediction results in the same order as input
for i, pred_df in enumerate(pred_df_list):
print(f"Predictions for series {i}:")
print(pred_df.head())

README 还专门列出了批量预测的要求:

  • 所有序列必须拥有相同的历史长度
  • 所有序列必须拥有相同的预测长度
  • 每个 DataFrame 必须包含 openhighlowclose
  • volumeamount 可选;缺失时会自动补零

同时,README 说明 predict_batch 会利用 GPU 并行能力 进行高效处理,并为每条序列独立完成归一化和反归一化。

这段说明很重要,因为它把“批量处理”从一个接口名字,落到了一个具体可理解的执行机制上。


预测之外,它还给了示例和可视化

Kronos 没有把用户丢在“你自己试试吧”这一步。README 里明确提到:

  • 有完整、可运行的示例脚本:examples/prediction_example.py
  • 这个脚本包含数据加载、预测和绘图
  • 运行后会生成一张对比真实数据与模型预测结果的图
  • 此外还提供了一个不带 volume 和 amount 数据的预测脚本:examples/prediction_wo_vol_example.py

这一点很能体现项目的气质。它不是只把方法抛出来,而是把“从调用到看图”的路径一起铺平了。对于很多人来说,真正建立直觉的,不是接口说明本身,而是那张模型预测与真实曲线摆在一起的图。


从“用模型”到“调模型”:Kronos 也提供了微调流程

如果说预测部分像是 Kronos 向外伸出的第一只手,那么 finetuning 部分就是它更进一步的表达:不只是给你现成模型,还允许你把模型往自己的数据世界里带。

README 中有一整节专门介绍 Finetuning on Your Own Data,并以 A-Share Market Example 作为演示。

文档把微调流程划分成四个步骤:

  1. Configuration
  2. Data Preparation
  3. Model Finetuning
  4. Backtesting

这个结构非常工整,也非常实战导向。


微调前的准备:依赖、Qlib 与配置文件

README 写明了微调流程的依赖前提:

  1. 先确保已经安装 requirements.txt 里的依赖
  2. 这个流程依赖 qlib
  3. 安装方式如下:
1
pip install pyqlib

此外,README 说明需要准备好自己的 Qlib 数据,并按照官方 Qlib 指南在本地完成数据下载和设置。示例脚本默认使用中国 A 股市场数据。

接着,配置集中放在 finetune/config.py 中。在运行脚本之前,需要根据本地环境修改这些路径:

  • qlib_data_path
  • dataset_path
  • save_path
  • backtest_result_path
  • pretrained_tokenizer_path
  • pretrained_predictor_path

README 还提到,还可以调整:

  • instrument
  • train_time_range
  • epochs
  • batch_size

以及 use_comet 之类的设置。

这类说明的价值在于,它没有把微调包装成一个“点一下按钮就万事大吉”的神话,而是坦率地告诉你:路径、数据、超参数、实验配置,这些都需要认真处理。


数据预处理:先把原始市场数据整理好

README 给出的第二步,是运行数据预处理脚本:

1
python finetune/qlib_data_preprocess.py

它的作用是:

  • 从 Qlib 目录读取原始市场数据
  • 进行处理
  • 划分训练集、验证集、测试集
  • 把结果保存成 pickle 文件

运行后,会在 dataset_path 指定目录下得到:

  • train_data.pkl
  • val_data.pkl
  • test_data.pkl

整个过程描述得不花哨,但特别清晰,像在告诉使用者:模型训练之前,数据秩序要先建立起来。


两阶段微调:先 tokenizer,再 predictor

README 进一步说明,微调分成两个阶段,并且训练脚本为多 GPU 训练设计,使用 torchrun

微调 tokenizer

1
2
# Replace NUM_GPUS with the number of GPUs you want to use (e.g., 2)
torchrun --standalone --nproc_per_node=NUM_GPUS finetune/train_tokenizer.py

README 对这一步的解释是:让 tokenizer 更适应你所在领域的数据分布。

微调 predictor

1
2
# Replace NUM_GPUS with the number of GPUs you want to use (e.g., 2)
torchrun --standalone --nproc_per_node=NUM_GPUS finetune/train_predictor.py

这一步则是对主模型进行面向预测任务的微调。

README 还写明,两者的最佳 checkpoint 会保存到 config.py 中配置好的路径下。

这种“先词表理解方式,再主模型预测能力”的两段式安排,也让 Kronos 的整体体系显得更完整:它不是只关心模型最后一层怎么输出,而是在更前面的表示层面也允许域适配。


微调之后,还要回到市场里验证它

README 的第四步是 Backtesting,运行脚本如下:

1
2
# Specify the GPU for inference
python finetune/qlib_test.py --device cuda:0

文档说明,这个脚本会:

  • 加载模型
  • 在测试集上进行推理
  • 生成预测信号
  • 输出详细的性能分析
  • 生成策略累计收益曲线与基准对比图

也就是说,在 Kronos 的 README 中,微调并不是训练结束就画句号,而是会继续走到回测这一步。模型不是停在 loss 曲线上,而是被重新放回评估路径里。

同时,README 还单独给出了一段“From Demo to Production: Important Considerations”,里面强调了几件事:

  • 这里生成的是原始信号
  • 真实量化流程中,这些信号通常还要进入组合构建和风险管理模块
  • 提供的 QlibDataset 只是一个示例
  • 对于不同数据源和格式,需要调整数据加载与预处理逻辑
  • 示例中的 top-K 策略只是一个基础起点

这段话很克制,也很重要。它没有把演示流程夸张成完整生产系统,而是明确指出了它在工作流中的位置。


除了 Qlib 流程,仓库里还有一套面向 CSV 数据的微调说明

在仓库的 finetune_csv/README.md 中,Kronos 还提供了一套针对自定义 CSV 金融数据的微调流程。这一点很值得注意,因为它让项目的输入方式更贴近日常数据处理场景。

这份 README 说明,CSV 文件需要包含这些列:

  • timestamps
  • open
  • high
  • low
  • close
  • volume
  • amount

其中 volumeamount 在不可用时可以为 0。

文档还给出了一份配置片段,例如:

1
2
3
4
5
6
7
8
# Data configuration
data:
data_path: "/path/to/your/data.csv"
lookback_window: 512
predict_window: 48
max_context: 512

...

从这里可以看到,CSV 微调路径同样保留了关键时间窗口配置,包括:

  • lookback_window
  • predict_window
  • max_context

CSV 微调支持顺序训练,也支持分开训练

这份 README 给出了两种训练方式。

方法一:顺序训练

train_sequential.py 会自动处理完整训练流程:

1
2
3
4
5
6
7
8
9
10
11
# Complete training (tokenizer + predictor)
python train_sequential.py --config configs/config_ali09988_candle-5min.yaml

# Skip existing models
python train_sequential.py --config configs/config_ali09988_candle-5min.yaml --skip-existing

# Only train tokenizer
python train_sequential.py --config configs/config_ali09988_candle-5min.yaml --skip-basemodel

# Only train predictor
python train_sequential.py --config configs/config_ali09988_candle-5min.yaml --skip-tokenizer

方法二:分组件训练

1
2
3
4
5
# Step 1: Train tokenizer
python finetune_tokenizer.py --config configs/config_ali09988_candle-5min.yaml

# Step 2: Train predictor (requires fine-tuned tokenizer)
python finetune_base_model.py --config configs/config_ali09988_candle-5min.yaml

此外,它还提供了 DDP 训练示例:

1
2
3
# Set communication backend (nccl for NVIDIA GPUs, gloo for CPU/mixed)
DIST_BACKEND=nccl \
torchrun --standalone --nproc_per_node=8 train_sequential.py --config configs/config_ali09988_candle-5min.yaml

这一整套设计给人的感觉是:Kronos 并没有把微调写成一条唯一道路,而是留出了不同训练控制粒度。


训练结束之后,会留下些什么

finetune_csv/README.md 还清楚列出了训练产物。

模型检查点

  • Tokenizer 会保存到:
    {base_save_path}/{exp_name}/tokenizer/best_model/
  • Predictor 会保存到:
    {base_save_path}/{exp_name}/basemodel/best_model/

训练日志

  • 控制台实时输出训练进度和指标
  • 日志文件保存到:
    {base_save_path}/logs/
  • 最佳模型会根据验证集 loss 进行保存

这种交代方式非常实用,因为它把“训练完之后去哪找结果”这个最容易让人卡住的问题提前回答了。


如果你更喜欢图形界面,Kronos 还有一个 Web UI

对于很多人来说,命令行和脚本当然高效,但图形界面更容易建立第一印象。仓库中的 webui/README.md 展示了一个 Kronos Web UI,它被描述为一个用于 Kronos 金融预测模型的 Web 用户界面,提供直观的图形化操作方式。

这个界面的功能列表相当完整,README 中列出了这些特性:

  • 支持 CSV、Feather 等金融数据格式
  • 提供固定 400+120 数据点时间窗口滑块选择
  • 集成真实 Kronos 模型,并支持多种模型尺寸
  • 可调节温度、nucleus sampling、sample count 等预测质量参数
  • 支持 CPU、CUDA、MPS
  • 提供预测结果与实际数据的详细对比分析
  • 支持专业的 K 线图展示

这几个点连起来看,Web UI 的角色就很明确了:它不是简单把命令行包一层壳,而是把数据选择、模型选择、参数调整、时间窗口控制和结果可视化都组织进了同一个操作界面里。


Web UI 的启动方式也很直接

README 提供了三种启动方式。

方式一:通过 Python 脚本启动

1
2
cd webui
python run.py

方式二:通过 Shell 脚本启动

1
2
3
cd webui
chmod +x start.sh
./start.sh

方式三:直接启动 Flask 应用

1
2
cd webui
python app.py

启动成功后,访问地址为:

http://localhost:7070

它把上手门槛压得很低:你不一定非得先理解训练流程,也不一定要从脚本接口开始,完全可以先打开界面,看数据、选模型、拖窗口、跑预测。


这个界面怎么用,README 写得像操作说明书一样清楚

Web UI 的使用步骤被拆成了六步:

  1. 选择数据文件
  2. 选择模型和计算设备
  3. 调整预测参数
  4. 通过滑块选择 400+120 数据点时间范围
  5. 点击按钮开始预测
  6. 在图表和表格中查看结果

这种顺序非常自然,像是在带着人一步步走进模型内部,而不是把一堆参数直接摊到面前。


预测质量参数,被摆到了用户眼前

webui/README.md 里专门有一节叫 Prediction Quality Parameters,把三个参数单独说明出来:

Temperature

  • 范围:0.1 - 2.0
  • 作用:控制预测随机性
  • 推荐值:1.2 - 1.5

Nucleus Sampling

  • 范围:0.1 - 1.0
  • 作用:控制预测多样性
  • 推荐值:0.95 - 1.0

Sample Count

  • 范围:1 - 5
  • 作用:生成多个预测样本
  • 推荐值:2 - 3

这部分很有意思。它让原本更偏模型内部的采样机制,变成了界面层面可调的操作项。于是 Kronos 的使用就不再只是“运行一个预测”,而更像是在和模型协商:你想更稳定,还是更发散;你想更单一路径,还是多看几种可能。


支持哪些数据、哪些模型、哪些设备,文档都写明白了

在数据格式上,Web UI README 要求必须包含:

  • open
  • high
  • low
  • close

可选列包括:

  • volume
  • amount
  • timestamps / timestamp / date

在模型支持上,它列出了:

  • Kronos-mini:4.1M 参数,轻量、快速预测
  • Kronos-small:24.7M 参数,平衡性能与速度
  • Kronos-base:102.3M 参数,高质量预测

在设备支持上,它列出了:

  • CPU
  • CUDA
  • MPS

从文档表达来看,Web UI 并不试图把一切复杂性隐藏掉,而是把用户最关心的选择项——数据、模型、设备——整齐地摆到台前。


它还会主动做对比分析

Web UI README 说明,系统会自动提供预测结果与真实数据之间的对比分析,包括:

  • 价格差异统计
  • 误差分析
  • 预测质量评估

这意味着,这个界面并不满足于只把图画出来,而是还想补上“怎么看”的那一层。图像负责让人直观感受,分析负责让结果更容易被整理和比较。


这一整套东西,是怎么搭起来的

Web UI 文档最后还给出了一份技术架构说明:

  • 后端:Flask + Python
  • 前端:HTML + CSS + JavaScript
  • 图表:Plotly.js
  • 数据处理:Pandas + NumPy
  • 模型:Hugging Face Transformers

这套组合并不花哨,但很稳。它像一个把研究模型送到使用界面的中间层:既保留 Python 生态里的模型和数据处理能力,又通过 Web 技术把交互性建立起来。


一个项目的气质,往往就藏在这些细节里

Kronos 的 README 给人的感觉,不是那种只强调概念高度的项目,也不是只堆参数表和术语的项目。它更像是一个认真把“研究表达”和“可用路径”都铺出来的仓库:

  • 有清晰的模型定位
  • 有明确的模型家族
  • 有从安装到预测的可执行路径
  • 有批量预测能力
  • 有示例脚本和可视化输出
  • 有面向自有数据的微调流程
  • 有回测环节
  • 还有一套图形化 Web UI

这些内容并不喧哗,却很完整。它们共同拼出了一个非常鲜明的形象:Kronos 不是只想让人“知道有这么个模型”,而是希望人真的把它运行起来、调起来、看起来。


结语:让 K 线从图形,变成可以被“阅读”的序列

Kronos 最吸引人的地方,不只是它在做金融预测,也不只是它提供了预训练模型和微调脚本,而是它给 K 线赋予了一种新的理解方式。

在这个项目里,K 线不再只是被动输入模型的数字列,而更像是一种可以被 tokenizer 切分、被 Transformer 建模、被上下文关联、被采样生成的市场表达。

它把金融市场里的那些起伏、影线、实体、量能与时间节奏,重新整理成一套模型可以学习的“语言秩序”。

当一个项目开始认真对待这种秩序时,它就不只是一个工具仓库了。它更像是在试着回答一个很有意思的问题:

如果市场真的有自己的语言,那么我们能不能训练一个模型,去读懂它。