HuggingFace镜像/stockprediction-ai
模型介绍文件和版本分析
下载使用量0

Stock Prediction AI — 基于状态感知的 LightGBM

我逆向工程解析了某对冲基金的交易策略,并将该模型开源。

这是一个 LightGBM 回归器,用于预测 150 只美国股票的次日对数收益率,同时搭配一条简单的状态规则来决定是否根据预测采取行动。该模型在 MacBook M1 上完成训练,无需云 GPU,除了单一的 FMP API 订阅外,无需其他付费数据。

作者:@jc_builds


在 4 种市场状态下的净值曲线与买入持有策略及 SPY 的对比

核心摘要

市场状态策略 vs 买入持有策略 vs SPY
2010 年牛市−0.1%+10.9% ✓
2018 年熊市+11.9% ✓+18.1% ✓
2020 年 COVID+22.0% ✓+38.8% ✓
2022 年熊市−0.0%−3.8%
2025–26 年实盘−3.2%−6.2%
5 个区间平均+6.1%+11.6%

该模型在市场崩盘期间(2018 年、2020 年)表现优于买入持有策略,而在牛市和震荡熊市(2010 年、2022 年、实盘期间)表现基本持平。它是一个“崩盘防护盾”,而非选股工具。


工作原理

流程图

整个系统由五个常规部分组成:

  1. 股票池 — 150 只美国大盘股,20 年的日度数据,来源于 FMP。
  2. 特征工程 — 每只股票包含 47 个特征:多周期收益率、滚动波动率、回撤指标、移动平均线、SPY 市场状态背景、横截面排名。所有特征均严格基于 t 日已知数据,用于预测 t+1 日。
  3. 模型 — 单个 LightGBM 回归器,训练目标为预测次日对数收益率。采用 MSE 损失函数,在按时间顺序划分的 10% 验证集尾部进行早停。
  4. 决策机制 — 单只股票的做多或现金持有决策门限,通过在验证集上调优以最大化相对于买入持有策略的超额收益。
  5. 回测 — 滚动前向测试,样本外验证,每次调仓手续费为 5 个基点。

无卖空,无杠杆,无期权,无日内交易。


真正带来改变的一条规则

regime rule diagram

原始模型已经相当不错,但真正提升指标的是一行代码的状态门控:

# Pseudocode — see src/strategy.py for the real version
bull = spy_price > spy_200_day_moving_average
threshold = bull_threshold if bull else bear_threshold  # bull: -0.003, bear: tuned
position = 1 if pred > threshold else 0
  • 在牛市(SPY 高于 200 日均线)中,只有出现强烈看空信号时才转为现金。否则保持多头,享受牛市收益。
  • 在熊市中,采用更严格的标准:只有当模型确实预期上涨时才做多。

正是这一个 if 语句,将 2018 年的收益从持平提升至相对买入并持有策略 +11.85%。


五个滚动前向测试阶段的结果

各阶段相对 SPY 的超额收益

训练采用经典的滚动前向方式:对于每个测试年份 Y,使用 2005 年至 Y-1 年的所有数据进行训练,完全不接触 Y 年的数据。对于实盘阶段,训练数据截止到 2025 年 4 月 22 日,测试从该时间点开始向前进行。

策略表现优异的时期(市场暴跌):

  • 2018 年熊市——波动剧烈的第四季度暴跌。策略相对 SPY 上涨 18.05%,在 130 只股票中跑赢买入并持有策略 128 只。
  • 2020 年 COVID 疫情——V 型暴跌与反弹。策略相对 SPY 上涨 38.83%,在 138 只股票中跑赢买入并持有策略 113 只。

策略勉强获胜或失利的时期(牛市和缓慢熊市):

  • 2010 年牛市——相对 SPY 上涨 10.90%(2010 年 150 只股票的篮子恰好显著跑赢 SPY,而该策略仅相当于篮子收益减去成本)。
  • 2022 年熊市——相对 SPY 下跌 3.78%。LightGBM 的早停机制在第 1 轮迭代触发;2005–2021 年的训练分布根本无法很好地预测 2022 年加息引发的熊市。策略实际上是一直持有,收益相当于篮子收益减去成本。
  • 2025–26 年实盘——相对 SPY 下跌 6.16%。这是强劲的牛市年份。与 2010 年面临同样的上限问题——在持续上涨的牛市中,一个要么做多要么持现的策略,其上限基本上就是买入并持有策略的收益减去成本。

在测试的 675 个股票年中,平均相对 SPY 超额收益为 +11.57%,相对个股买入并持有策略超额收益为 +6.11%。


有效方法与失败尝试

有效与失败对比

共尝试了八个模型版本。七个版本表现倒退,一个版本成功上线。最终的优胜模型并不复杂——它是最简单有效的方法,再加上一条市场阶段规则。

版本思路结果
v1基础 LightGBM,MSE 损失,验证集调优阈值有效的基准模型
v2非对称 y 加权损失表现倒退——在第 1 轮迭代早停
v3基于幅度加权的训练表现倒退——平均化后丢失了暴跌信号
v4v1 + 市场阶段感知阈值优胜模型——已上线
v4bv4 采用固定阈值略有倒退
v55 种子集成表现倒退——平均化后丢失了高确信度的暴跌选股
v6大幅下跌概率分类器表现倒退——目标事件过于罕见
v7基于 Apple GPU 的 MLX MLP表现倒退——校准失败
v8v4 仅使用 2015 年以后的数据训练表现倒退——最佳迭代次数从 120 降至 5,失去正则化效果
v9多模态前 10 轮换单独上线,收益波动剧烈

我实际学到的经验

learnings

  1. 模型仅在市场崩盘时发挥作用。 在牛市中,买入并持有策略就能获胜。任何做多或持现策略的收益上限都是买入并持有策略的收益减去交易成本。
  2. 一个简单规则胜过所有复杂的损失函数。 我花了数周时间研究非对称损失、量级加权和自定义目标函数。而一个简单的“标普500指数是否高于其200日均线?”的判断标准却胜过了所有这些复杂方法。
  3. 更多的训练数据通常有帮助——但并非总是如此。 二十年的训练数据通常比十年的表现更好。但有一个版本(v8)却出现了相反的情况。因此,必须通过测试来验证,而不是凭猜测。
  4. 在README中保留亏损年份的记录。 2025年的实盘运行相较于标普500指数亏损了6%。隐瞒这一事实会使其他所有数据都变得不可信。

项目成果

本仓库包含:

stockprediction-ai/
├── README.md                  this file
├── config.json                hyperparameters, feature columns, regime thresholds, splits
├── results.json               per-split metrics (strat final, B&H final, excess)
├── boosters/
│   ├── 2010.txt               LightGBM text-format booster, trained on 2005–2009
│   ├── 2018.txt               trained on 2005–2017
│   ├── 2020.txt               trained on 2005–2019
│   ├── 2022.txt               trained on 2005–2021
│   └── live.txt               trained on 2005-01-01 through 2025-04-22
└── images/                    charts used in this card

Booster 是纯 LightGBM 文本文件,可使用任何 LightGBM 运行时加载,无需 Python。


使用实时 booster

import json
import lightgbm as lgb
import numpy as np
import pandas as pd
from huggingface_hub import hf_hub_download

REPO = "jc-builds/stockprediction-ai"

# 1. Grab the live booster and config
booster_path = hf_hub_download(REPO, "boosters/live.txt")
config_path  = hf_hub_download(REPO, "config.json")

booster = lgb.Booster(model_file=booster_path)
config  = json.loads(open(config_path).read())
feature_cols = config["feature_columns"]

# 2. Build a feature row for one stock on one trading day
#    (see github.com/jc-builds/stockprediction/blob/main/src/features.py
#     for the full 47-feature builder — the code is open-source).
features: pd.DataFrame = build_features_for_today(symbol="AAPL")
x = features[feature_cols].astype(float).values

# 3. Predict next-day log return
pred = booster.predict(x)[0]

# 4. Apply the regime rule
bull        = spy_close_today > spy_200_day_ma_today
thr_bull    = config["regime_rule"]["bull_threshold"]   # -0.003
thr_bear    = config["splits"]["live"]["bear_threshold"]
threshold   = thr_bull if bull else thr_bear
position    = 1 if pred > threshold else 0              # 1=long, 0=cash

局限性 — 使用前请阅读

  • 非投资建议。在标普500指数ETF(SPY)全年上涨32%的情况下,我实盘操作却亏损了6%。请将此视为一件教育性的参考作品。
  • 150只股票的选股范围存在幸存者偏差。所选股票代码在2025-26年仍全部上市;2008-10年间任何破产的股票均未纳入数据集。
  • 交易成本模型为线性。每次交易(买入或卖出)成本为5个基点(bps)。对于小盘股以及市场恐慌期间,实际滑点会更大。
  • 未进行税务建模。洗售交易、短期资本利得等均未考虑。
  • 市场状态规则存在不易察觉的信息泄露。标普500指数ETF(SPY)的200日均线使用了与增强器训练时相同的历史数据。实际上,这并非前瞻偏差(该规则仅比较当日价格与其移动平均值),但任何市场状态规则本质上都是对测试集的二次优化。
  • 2022年的案例是一次真实的预测失误。2005–2021年的训练分布未能实现泛化。v4版本中best_iter=1意味着模型“放弃了”——它返回了近乎恒定的预测值。任何实际部署都需要检测到这种情况(例如,当验证损失趋于平稳时拒绝交易),而不是默认转为全仓做多。

复现步骤

git clone https://github.com/jc-builds/stockprediction
cd stockprediction
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# Set FMP_API_KEY in .env, then:
PYTHONPATH=src python src/run.py --model v4

引用说明

如果本项目对您的研究工作或教学有所帮助,请引用:

@misc{jcbuilds_stockprediction_2026,
  author       = {Jared Cassoutt (@jc_builds)},
  title        = {Stock Prediction AI: Regime-Aware LightGBM},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/jc-builds/stockprediction-ai}},
}

许可协议

MIT 许可协议。你可以随意使用,但如果你因此亏损,请勿起诉我。