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

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors