简介:这份资源面向希望在Windows平台落地金融AI模型的开发者与量化研究者,提供清华团队开源Kronos金融K线基础模型的完整部署源码。Kronos是首个针对金融烛台图的开源基础模型,训练数据覆盖全球45个以上交易所,采用两阶段框架设计,适合具备一定Python基础、想搭建GPU加速推理环境的中高级用户。压缩包共4个文件,约9KB,包含Python脚本、inscode配置、HTML页面与gitignore文件,分别用于CUDA加速验证、环境配置、WebUI交互与版本管理,结构精简但覆盖部署关键环节。目前已有223人学习下载。通过这份源码,读者可快速完成仓库克隆、虚拟环境创建、依赖安装与CUDA验证,并借助WebUI进行模型加载、设备配置、数据加载与预测测试,为后续量化研究与策略回测建立可用的开发环境,同时理解EPGF架构与数据准备流程,减少自行摸索的排错成本。
1. 在 Windows 上把 Kronos 金融模型跑起来:一次讲清环境、数据与推理链路
很多做量化研究的朋友第一次听到 Kronos 金融模型,第一反应是「又一个时序预测大模型」,第二反应是「它到底能不能在 Windows 上跑」。我最初也这么想,直到某天需要在一台只有 Windows 的办公机上验证一段行情预测逻辑,才发现真正卡住人的不是模型本身,而是环境、依赖和数据处理这三件事。Kronos 属于金融时序基础模型这一类,输入是一段 OHLCV 行情序列,输出是对后续走势的表征或预测,适合做因子挖掘、趋势判断和回测前的信号生成。它不需要你从零训练,更多是加载权重做推理或轻量微调。这篇文章面向的是手上有 Windows 机器、想快速把 Kronos 跑通并接到自己数据上的从业者,从环境搭建一路讲到推理脚本和踩坑记录,新手能照着走,熟手能直接看参数和边界。
2. 环境准备:Windows 上把 Kronos 依赖装干净的顺序
2.1 为什么 Windows 装金融模型依赖总翻车
Kronos 这类金融时序模型,底层基本是 PyTorch 加一堆数值计算库,再叠上数据处理和可视化。它在 Linux 上跑得好好的,搬到 Windows 就容易出问题,原因集中在三块:一是部分依赖包在 Windows 上没有预编译 wheel,pip 会尝试源码编译,而 Windows 默认没有 C++ 编译工具链;二是路径分隔符和文件编码差异,导致读取行情 CSV 时中文列名或反斜杠路径报错;三是 CUDA 版本和 PyTorch 版本对不上,装完 import torch 直接报 DLL 加载失败。我一般的原则是:先定 Python 版本,再定 PyTorch 版本,最后装其余依赖,顺序错了就要反复卸载重装,非常折腾。
选型上,Python 建议 3.10 或 3.11,这两个版本在 Windows 上 wheel 覆盖最全。PyTorch 如果要用 GPU,先确认显卡驱动支持的 CUDA 上限,再去 PyTorch 官网找对应命令,不要直接 pip install torch,那样装到的是 CPU 版或者版本不匹配的包。CPU 推理也能跑,只是慢,做小规模验证完全够用。
2.2 用 conda 建独立环境并锁定版本
我习惯用 conda 建一个干净环境,避免和系统里其他项目的包打架。下面这套命令在 Windows 的 Anaconda Prompt 里执行,注意先建环境再装包。
# 创建独立环境,指定 Python 3.10 conda create -n kronos python=3.10 -y # 激活环境 conda activate kronos # 安装 PyTorch,这里以 CUDA 11.8 为例,CPU 用户把 cu118 换成 cpu 对应命令 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装金融时序常用依赖 pip install numpy pandas scipy scikit-learn matplotlib tqdm pyyaml # 验证 torch 是否可用,以及能否识别 GPU python -c "import torch; print(torch.__version__, torch.cuda.is_available())"这段逻辑的关键在于:conda 负责隔离 Python 解释器和基础科学计算库,pip 负责装 PyTorch 和上层依赖。最后一行验证必须看到版本号和一个 True 或 False,如果 import 就报错,说明 PyTorch 和 CUDA 不匹配,回到上一步换命令重装。参数上,--index-url指向的是 PyTorch 官方 wheel 源,cu118 表示 CUDA 11.8,如果你的驱动只支持到 11.7,就换成 cu117,不要硬上。
2.3 目录结构与数据放置约定
Kronos 的推理脚本通常需要一个固定的目录结构,我一般这样组织,避免路径写死导致换机器就崩:
kronos_project/ ├── configs/ │ └── infer.yaml ├── data/ │ └── btc_1h.csv ├── weights/ │ └── kronos_base.pt ├── outputs/ └── run_infer.pydata 放行情 CSV,weights 放模型权重,outputs 存预测结果,configs 放配置文件。这样做的好处是脚本里全部用相对路径,换机器只要整体拷贝目录就能跑。注意 Windows 下路径用正斜杠或双反斜杠,单反斜杠在字符串里会被当转义符,这是新手最容易踩的坑之一。
3. 数据与配置:把行情喂给 Kronos 的正确姿势
3.1 行情 CSV 的字段规范与时间对齐
Kronos 吃的是时序数据,最常见的是 OHLCV 格式,即开盘、最高、最低、收盘、成交量。字段名建议统一成小写英文,时间列命名为 timestamp,格式用 ISO 8601,例如 2024-01-01 00:00:00。很多数据源导出的时间列带时区或者用毫秒时间戳,直接喂进去会导致时间索引错乱,预测结果整体偏移。我一般会先做一次清洗,把时间列转成标准格式并按升序排列,同时检查有没有重复时间戳和缺失值。
import pandas as pd # 读取原始行情,假设时间列叫 time,价格列叫 open/high/low/close/volume df = pd.read_csv("data/raw.csv") # 统一时间格式并设为索引 df["timestamp"] = pd.to_datetime(df["time"], utc=True).dt.tz_localize(None) df = df.sort_values("timestamp").drop_duplicates("timestamp").set_index("timestamp") # 只保留模型需要的列,缺失值用前向填充 cols = ["open", "high", "low", "close", "volume"] df = df[cols].ffill().dropna() # 保存成标准输入 df.to_csv("data/btc_1h.csv") print(df.shape, df.index.min(), df.index.max())这段代码做了四件事:时间标准化、去重排序、列筛选、缺失值处理。参数上,utc=True再tz_localize(None)是为了把带时区的时间统一成无时区的本地时间,避免后续对齐出问题;ffill是前向填充,金融数据里比均值填充更合理,因为价格具有连续性。最后打印形状和时间范围,确认数据没有断档。
3.2 推理配置文件的关键参数
Kronos 的推理行为基本靠一个 YAML 配置控制,下面是我常用的一份最小配置,字段名按常见约定写,实际以你拿到的源码为准:
model: weights: weights/kronos_base.pt device: cuda # 没有 GPU 就改成 cpu context_length: 512 # 输入历史窗口长度 pred_length: 24 # 预测未来步数 data: path: data/btc_1h.csv target: close # 预测目标列 normalize: true # 是否做标准化 infer: batch_size: 32 seed: 42context_length决定模型看多长的历史,太小捕捉不到趋势,太大显存吃紧,512 是一个比较稳的起点。pred_length是你要预测的未来步数,做日内就看 24,做波段可以拉到 96 或 168。normalize建议开,金融价格量纲差异大,标准化后模型更稳。seed固定随机种子,方便复现结果,做研究一定要设。
3.3 写一个最小推理脚本跑通链路
配置和数据都齐了,接下来写推理脚本。下面是一个最小可运行版本,重点是把加载、推理、保存三步串起来:
import yaml import torch import pandas as pd from model import KronosModel # 按实际源码的类名导入 # 读配置 with open("configs/infer.yaml", "r", encoding="utf-8") as f: cfg = yaml.safe_load(f) # 加载数据 df = pd.read_csv(cfg["data"]["path"], index_col="timestamp", parse_dates=True) series = df[cfg["data"]["target"]].values # 初始化模型并加载权重 device = cfg["model"]["device"] model = KronosModel(context_length=cfg["model"]["context_length"], pred_length=cfg["model"]["pred_length"]) state = torch.load(cfg["model"]["weights"], map_location=device) model.load_state_dict(state) model.to(device).eval() # 取最后一段历史做推理 ctx = series[-cfg["model"]["context_length"]:] x = torch.tensor(ctx, dtype=torch.float32).unsqueeze(0).to(device) with torch.no_grad(): pred = model(x).cpu().numpy().flatten() # 保存结果 out = pd.DataFrame({"pred": pred}) out.to_csv("outputs/pred.csv", index=False) print("done", pred[:5])逻辑说明:先读配置,再读数据,然后按配置初始化模型并加载权重,取最后一段历史作为输入,推理后保存。参数上,map_location=device保证权重能正确加载到 CPU 或 GPU;unsqueeze(0)是加 batch 维度,模型一般要求输入形状是[batch, length];torch.no_grad()关闭梯度,省显存也更快。跑通这一步,说明整条链路已经通了,后面就是调参和接自己的数据。
4. 避坑与排查:Windows 跑 Kronos 最常见的 5 个问题
4.1 现象:import torch 报 DLL load failed
原因基本是 PyTorch 版本和 CUDA 驱动不匹配,或者装到了 CPU 版却按 GPU 用。解决方法是先nvidia-smi看驱动支持的 CUDA 版本,再去 PyTorch 官网复制对应命令重装,装完用torch.cuda.is_available()验证。如果一直搞不定,直接装 CPU 版先跑通逻辑,别在环境上耗太久。
4.2 现象:读取 CSV 报 UnicodeDecodeError
Windows 默认编码是 GBK,而行情文件常是 UTF-8。解决方法是读文件时显式指定encoding="utf-8",如果文件本身是 GBK 就写encoding="gbk"。我一般统一把数据转成 UTF-8 保存,一劳永逸。
4.3 现象:路径报错 FileNotFoundError
多半是用了单反斜杠或者相对路径基准不对。解决方法是全部用正斜杠,或者用os.path.join拼接,脚本里尽量用相对于项目根目录的路径,并在开头os.chdir到项目根目录。
4.4 现象:推理结果全是 NaN 或一条直线
常见原因是输入数据没做标准化,或者历史窗口里有缺失值。解决方法是开启normalize,并在喂数据前dropna。另外检查context_length是否大于实际数据长度,数据太短会取到空数组。
4.5 现象:显存不足 CUDA out of memory
context_length或batch_size设太大。解决方法是先把batch_size降到 8 或 16,再逐步降context_length。CPU 推理不存在显存问题,但内存要够,数据量大时建议分块推理。
5. 进阶技巧:让 Kronos 的输出真正可用
跑通推理只是第一步,真正决定这套东西值不值得投入的,是输出能不能用。我一般会做三件事。第一是滚动推理,不要只预测一次,而是用滑动窗口不断更新输入,得到连续的预测序列,这样能看到模型在不同市场阶段的稳定性。第二是对比基线,把 Kronos 的预测和简单移动平均、ARIMA 这类基线放一起看,如果连基线都跑不赢,说明参数或数据有问题,别急着上实盘。第三是固定随机种子并记录配置,金融时序模型对随机性敏感,不记录配置的复现都是玄学。
下面是一个滚动推理的骨架,核心是每次预测后把真实值拼回输入窗口:
window = list(series[-cfg["model"]["context_length"]:]) preds = [] for i in range(48): # 滚动 48 步 x = torch.tensor(window[-cfg["model"]["context_length"]:], dtype=torch.float32).unsqueeze(0).to(device) with torch.no_grad(): p = model(x).cpu().numpy().flatten()[0] preds.append(p) window.append(p) # 用预测值续接,实盘时换成真实值 print(preds[:10])参数上,滚动步数按你的预测周期定,日内可以 24,波段可以 96。注意这里用预测值续接是开环,实盘验证时应该用真实值续接做闭环,两者差距能反映模型的误差累积情况。我自己的习惯是每次实验都存一份配置和输出,过一周再回头看,很多当时觉得不错的结果其实是过拟合。踩过几次坑之后,我现在只信能稳定复现且跑赢基线的结果。希望帮到你。
本文还有配套的精品资源,点击获取