Skip to content

jjyr/value-tracker

Repository files navigation

Value Tracker

价值追踪是一个全静态生成的美股机构 13F 信号仪表盘。Value Tracker tracks the trades of value investors, helping you see what they buy, sell, and hold over time.

页面由 Hugo 构建,后台数据链路现在保持为轻量的文件流水线:

  1. 原始接入:Longbridge 当前 13F / 行情、SEC 历史 13F、Longbridge 日 K 线等 provider 生成原始事实或更新缓存。
  2. 规范化:scripts/stockhunt_backend.py 在内存中比较最近两个 13F 报告期,生成 raw/generated/snapshot.yaml
  3. 历史曲线:scripts/historical_backtest.py 基于 SEC cache 和 Longbridge K 线 cache 生成重点机构 13F 持仓收益曲线。
  4. 静态导出:scripts/generate_stockhunt_data.py 合并 snapshot 和机构曲线,输出 Hugo 读取的 data/stockhunt.json

流水线不再维护中间数据库,也不把 live raw input 作为标准产物落盘。可持久化的是最终 JSON/JSONL 产物和外部数据 cache。

目录

config/stockhunt.yaml          主配置:白名单、重点机构、策略参数
config/cusip-symbols.yaml      13F CUSIP -> Longbridge symbol 显式覆盖映射
raw/sample/13f_holdings.yaml   sample 原始 13F + 行情输入
raw/generated/                 本地生成产物,已 gitignore
raw/generated/cache/           SEC / Longbridge K 线 cache
data/stockhunt.json            Hugo 当前消费的数据
scripts/build_live_input.py    Longbridge live data 调试入口
scripts/stockhunt_backend.py   raw input -> normalized snapshot
scripts/historical_backtest.py SEC 历史 13F + Longbridge K 线 -> 机构收益曲线
scripts/generate_stockhunt_data.py
                               snapshot + institution curves -> Hugo data

依赖

需要本机有:

uv
hugo
longbridge

首次使用真实 Longbridge 数据前,需要登录:

longbridge auth login

Python 依赖由 uv 根据 pyproject.toml / uv.lock 管理,不需要手动 pip install

常用命令

查看可用命令:

uv run build --help
uv run fetch --help
uv run fetch-all --help
uv run schedule --help

只构建静态站点:

uv run build

增量抓取数据,不运行 Hugo build:

uv run fetch

全量抓取数据,刷新 SEC filing cache 和 Longbridge 价格 cache,不运行 Hugo build:

uv run fetch-all

定时任务入口。daily 更新价格和机构曲线;weekly 会先检查 SEC 最新 13F 元数据,若 13F 未更新则提前退出;若更新则增量抓取 13F 并重算机构曲线。实际跑数据的任务执行完都会自动 build:

uv run schedule daily
uv run schedule weekly
uv run schedule weekly --force  # 跳过早停检查,强制跑完整 weekly

本地预览:

uv run hugo server

默认访问:

http://localhost:1313/

GitHub Pages 部署

仓库已支持 GitHub Actions 部署到 GitHub Pages。

GitHub Pages 设置:

Settings -> Pages -> Build and deployment -> Source: GitHub Actions

Workflow

.github/workflows/deploy.yml
.github/workflows/schedule.yml

deploy.yml

  • main 分支 push 或手动触发。
  • 使用仓库当前 data/stockhunt.json 构建 Hugo。
  • 发布 public/ 到 GitHub Pages。

schedule.yml

  • 手动触发时可选择 dailyweeklyfetch-all
  • 定时触发:
    • 周二/周三 09:30 Asia/Shanghai 跑 weekly
    • 周四/周五/周六 09:30 Asia/Shanghai 跑 daily
  • 恢复 raw/generated/cache/snapshot.yamlraw/generated/historical/ 的 Actions cache。
  • 数据变化时自动提交 data/stockhunt.json 和补齐的 content/en/**content/zh/**,让仓库快照与 Pages 数据保持一致。
  • 跑完数据任务后发布 GitHub Pages;weekly 若判定 13F 未更新,会跳过后续提交、cache 保存和 Pages 发布。

Longbridge Secrets

定时数据任务需要 GitHub Secrets:

LONGBRIDGE_CLIENT_ID
LONGBRIDGE_TOKEN_FILE_B64

CI 需要 SDK OAuth token 文件,不要使用 longbridge auth login 生成的 cli-auth。详细更新流程见 docs/ci-longbridge-token.md

快速生成 token 文件:

CLIENT_ID="fd52fbc5-02a9-47f5-ad30-0842c841aae9"
uv run --with longbridge python -c 'from longbridge.openapi import OAuthBuilder; import webbrowser; OAuthBuilder("'$CLIENT_ID'").build(webbrowser.open)'

生成 secrets:

printf "%s" "$CLIENT_ID"
base64 -i "$HOME/.longbridge/openapi/tokens/$CLIENT_ID" | tr -d '\n'

把第一行输出填入 LONGBRIDGE_CLIENT_ID,第二行输出填入 LONGBRIDGE_TOKEN_FILE_B64

首次部署

第一次建议手动运行:

Actions -> Update Data and Deploy Pages -> Run workflow -> mode: fetch-all

之后定时任务会复用 Actions cache。若 cache 丢失,daily 会自动 fallback 到 fetch-all

生成流程

1. 增量抓取数据

uv run fetch

默认产物:

raw/generated/snapshot.yaml
raw/generated/historical/
raw/generated/cache/sec/
raw/generated/cache/longbridge-kline/
data/stockhunt.json
content/en/institutions/*.md
content/en/stocks/*.md
content/zh/institutions/*.md
content/zh/stocks/*.md

增量语义:

  • Longbridge 当前 13F / 行情会在内存中生成 live raw input。
  • 当前 snapshot 每次都从 raw input 和配置纯内存重算,不保留中间状态。
  • SEC submissions index 会刷新,用于发现新 13F;已有 filing index / information table XML 继续复用 cache。
  • 未显式映射的 CUSIP 会用 Longbridge US security-list 按 issuer name 自动匹配 symbol;成功匹配会追加写回 config/cusip-symbols.yaml,后续直接复用本地表。
  • Longbridge 日 K 线按 symbol 追加缺失日期,不再按每个 start/end 重新抓整段。
  • 历史曲线写入 raw/generated/historical/ JSONL store;非全量任务会在配置和 CUSIP 映射未变时从 checkpoint 续算尾部。
  • 13F 指纹变化时,dirty_from 取最早变动 13F 的 filing_date;没有 13F 变化时,只重算最新 equity point 之后的尾部。
  • data/stockhunt.json 会重新导出,供后续 build 使用。
  • content/en/**content/zh/** 会按白名单机构和股票自动补齐,用于详情页。

13F 没有 ticker,只有 CUSIP。数据抓取会先查 config/cusip-symbols.yaml;未命中时,用 Longbridge US security-list 按 issuer name 自动匹配 symbol,并把成功匹配追加到本地表。仍无法匹配的持仓会进入 warnings,不会进入榜单。

2. 全量抓取数据

uv run fetch-all

适合修改白名单、CUSIP 映射、核心计算逻辑,或想刷新外部数据 cache 口径。它会:

  • 重新生成当前 Longbridge raw input。
  • 刷新 SEC submissions、filing index、information table XML。
  • 刷新 Longbridge 历史 K 线。
  • 重新计算 snapshot、机构历史曲线和 data/stockhunt.json

3. 机构曲线规则

  • 只使用当时已经公开披露的 13F 持仓,避免提前使用未来报告。
  • 曲线以重点机构公开持仓的收益指数计算,不把 13F 总持仓规模变化计入收益。
  • 今日、本月、YTD 和最大回撤都基于收益指数口径;持仓市值单独展示为当前公开持仓规模。
  • 价格使用 Longbridge 日 K 线,默认 period=dayadjust=forward

4. 构建静态站点

uv run build

这个命令只执行 Hugo build,不抓数据、不重新回测。

5. 定时任务

推荐用两个 schedule:

# 每周更新:美股周一收盘后,香港时间周二早上执行
uv run schedule weekly

# 每日价格和收益更新:美股其他交易日收盘后执行
uv run schedule daily

第一次部署先跑一次 uv run schedule weekly --forceuv run fetch-all && uv run build,生成历史机构曲线文件;之后 daily 只更新价格和收益。weekly 默认会在 SEC 13F 报告期/filing 指纹未变化时提前退出,不重跑 Longbridge、回测、导出和 Hugo build。

cron 示例:

# 周度更新。周二跑;周三再跑一次用于覆盖周一美股休市顺延的情况。
30 8 * * 2,3 cd /Users/jjy/Workspace/stockhunt && uv run schedule weekly >> /tmp/schedule-weekly.log 2>&1

# 日常价格更新。避开周二/周三,防止和 weekly 重复。
30 8 * * 4-6 cd /Users/jjy/Workspace/stockhunt && uv run schedule daily >> /tmp/schedule-daily.log 2>&1

重跑规则

全量重跑

uv run fetch-all
uv run build

fetch-all 会重新拉取当前 Longbridge live raw input、刷新 SEC / K 线 cache、重新计算 snapshot 和历史回测并导出 Hugo 数据。build 只把当前 data/stockhunt.json 构建成 public/

增量重跑

uv run fetch
uv run build

当前增量语义:

  • 当前 raw input 和 snapshot 每次重算。
  • SEC 只刷新 submissions index 来发现新增 filing,已有 filing XML 继续使用 cache。
  • 历史 K 线只追加缺失日期。
  • 历史回测会按当前配置重新模拟。

只重建前端

如果只改了 Hugo 模板、CSS、JS 或文案:

uv run build

只重导 Hugo 数据

如果已经有 raw/generated/snapshot.yamlraw/generated/historical/,但改了 scripts/generate_stockhunt_data.py 或页面数据格式:

uv run python scripts/generate_stockhunt_data.py \
  --snapshot raw/generated/snapshot.yaml \
  --simulation raw/generated/historical
uv run build

修改白名单

白名单在 config/stockhunt.yaml

institutions:
  whitelist_version: "2026-06-01-whitelist-v1"
  managers:
    - cik: "0001709323"
      name: "Himalaya Capital Management LLC"
      display_name: "李录"
      enabled: true
      style: "value"

修改规则:

  • 新增机构:添加一条 managers,设置 enabled: true,并更新 whitelist_version
  • 暂停机构:保留配置但设置 enabled: false,并更新 whitelist_version
  • 修改展示名:改 display_name,建议也更新 whitelist_version,保证静态数据可追溯。
  • CIK 必须能被标准化为 10 位数字,脚本会自动补前导 0。

修改白名单后推荐全量重跑:

uv run fetch-all
uv run build

如果新增机构的持仓里出现大量 unmapped CUSIP,优先检查 Longbridge security-list 是否能覆盖;无法稳定自动匹配的股类、ADR、改名证券,再手动补 config/cusip-symbols.yaml

修改 CUSIP 映射

本地映射在 config/cusip-symbols.yaml。自动匹配成功会追加到这里;手动条目也写这里,并优先于 Longbridge 自动映射。它适合股类、ADR、改名证券或名称匹配可能漂移的情况:

mappings:
  "037833100":
    symbol: "AAPL.US"
    company_name: "Apple Inc."
    tags: ["Nasdaq 100", "S&P 500", "Mag7"]

修改映射或自动映射逻辑后,需要重新生成 live input,因为 raw input 里已经按映射过滤过持仓:

uv run fetch-all
uv run build

历史回测也依赖同一套映射逻辑。补充 CUSIP 后重新运行完整 build,历史 SEC 13F 会按新映射重新解析;已缓存的 SEC 原始文件和 K 线会复用。

修改重点机构

重点机构在同一个配置文件:

key_institutions:
  version: "2026-06-01-key-v1"
  members:
    - cik: "0001759760"
      display_name: "段永平"
      enabled: true

修改重点机构会影响:

  • 重点机构姓名标签
  • 首页机构收益曲线
  • 机构详情页曲线和图例

如果只改重点机构配置,推荐重新增量计算并 build:

uv run fetch
uv run build

如果新增的重点机构本身不在白名单里,先修改白名单,再全量抓取:

uv run fetch-all
uv run build

修改策略参数

策略在:

strategy:
  max_positions: 10
  max_position_weight_pct: 50
  weighting_method: "key_institution_signal_score"
  score_weight_exponent: 1.0
  rebalance_step_weight_pct: 20
  min_buy_gap_weight_pct: 5
  allocation_signal:
    key_new_position_score: 30
    key_added_score: 20
    key_holding_score: 8
    key_buy_intensity_score_per_pct: 8
    key_buy_intensity_max_score: 40
    below_key_latest_buy_price_bonus: 15
    multiple_key_institution_bonus: 8
    key_reduced_penalty: -15
    key_exit_penalty: -50

当前前端不展示规则化组合回测;策略参数主要保留给历史数据管线中的机构信号计算。首页排序和机构详情曲线使用公开 13F 持仓收益指数。

修改策略参数后,推荐重新抓取并 build:

uv run fetch
uv run build

常用检查

验证脚本语法和 Hugo 构建:

uv run python -m py_compile scripts/build_live_input.py scripts/historical_backtest.py scripts/historical_store.py scripts/stockhunt_backend.py scripts/generate_stockhunt_data.py scripts/tasks.py
uv run build

检查关键产物:

du -sh raw/generated/snapshot.yaml raw/generated/historical data/stockhunt.json

日常只需要 buildfetchfetch-allschedule。底层拆步调试时,可以直接用 uv run python scripts/*.py 调用具体脚本。

后续接入

  1. Index tag adapter:自动维护 S&P 500、Nasdaq 100、Russell 1000/2000/3000、Mag7 标签。
  2. 更完整的历史数据质量报告:展示自动映射 CUSIP、未映射 CUSIP、退市股票、缺失价格和 13F value 单位修正。
  3. 为机构详情页补充更细的历史变动图表。

About

Value Tracker tracks the trades of value investors, helping you see what they buy, sell, and hold over time.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors