Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# QuantCockpit uses local-only defaults. Add optional local overrides here.
# QUANTCOCKPIT_DB_PATH=./quantcockpit.duckdb
# QUANTCOCKPIT_DEMO_AS_OF=2026-07-20T18:00:00Z

# v0.2 has no AI provider integration and requires no model API key.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: CI

on:
push:
branches: [main]
pull_request:

permissions:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ quantcockpit-report.md
.env.*
!.env.example
.gstack/
.worktrees/
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

QuantCockpit 的重要变更记录在这里。版本遵循 [Semantic Versioning](https://semver.org/)。

## [0.2.0] - 2026-07-20

### Added

- 可先只读预览、再导入现有 CSV、JSON 或 JSONL 仓位快照,并用版本化映射配置适配不同列名和嵌套结构,不需要修改策略代码。
- 可按严格组合身份查看最新仓位覆盖、gross / net、Top-1 / Top-5、HHI、资产类别、行业和国家敞口,并从页面或报告追溯到事件与映射哈希。
- 合成演示现在同时包含策略事件和仓位快照,接入命令、API 契约、前端类型与失败状态均有自动测试。

### Boundaries

- 尚不提供券商直连、成交重建、因子 Beta、VaR、压力测试、告警派发或 AI 摘要运行时。
- 不完整的数值基础返回候选基础与覆盖率,明确空仓单独标记;两者都不会被伪装成数值零。

## [0.1.0] - 2026-07-20

### Added
Expand Down
16 changes: 14 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bun install

1. 先写能准确失败的最小测试,再写实现。
2. 事件、API 或错误语义变化时,同步更新 README 和架构文档。
3. 示例必须完全合成,使用虚构策略名、固定时间和 `paper` 环境。
3. 示例必须完全合成,使用虚构策略名、工具名和标的、固定时间以及 `paper` 环境。
4. 不新增交易执行、券商连接、收益承诺或自动调仓建议。
5. 保持 API 对外错误为安全摘要,不回显坏行、绝对路径或密钥。

Expand All @@ -35,7 +35,19 @@ bun audit

## 契约变更

`schema_version` 是公共边界。新增必填字段、改变收益口径或改变幂等键都属于破坏性变更,必须提供迁移说明和旧数据测试。未知字段当前会被拒绝;不要用静默忽略来掩盖版本不匹配。
`schema_version` 和仓位映射的 `profile_version` 都是公共边界。新增必填字段、改变收益/敞口口径或改变幂等键都属于破坏性变更,必须提供迁移说明和旧数据测试。未知字段当前会被拒绝;不要用静默忽略来掩盖版本不匹配。

## 贡献仓位适配

优先贡献声明式映射示例,只有现有 CSV / JSON / JSONL 读取器无法表达时才新增代码适配器。每个新适配必须同时提供:

- 完全合成且不含品牌、账户或真实标的的最小输入夹具;
- 固定版本的映射配置,以及确定性的 `mapping_profile_hash` 测试;
- preview 输出测试和正式导入测试,证明 preview 不写数据库;
- 缺字段、坏数字、重复标的、半写尾行、超限输入和错误脱敏测试;
- README 接入命令或独立文档入口,并说明数据来源的时间、方向和币种口径。

不要把特定券商 SDK、凭据读取或订单接口塞进通用导入器。适配器的职责是把已有导出文件变成规范 `position_snapshot`,不是控制交易账户。

## 报告问题

Expand Down
67 changes: 56 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> Local-first, read-only and traceable observability for quantitative strategy logs.

QuantCockpit 是一个**本地、只读、可追溯**的量化策略日志观测台:把版本化日频 JSONL 导入 DuckDB,再展示健康度、原始事件证据、UTC 日期交集相关性和本地 Markdown 报告。
QuantCockpit 是一个**本地、只读、可追溯**的量化策略与仓位日志观测台:它把版本化策略事件,以及现有系统导出的 CSV / JSON / JSONL 仓位快照,规范化到本地 DuckDB,再展示健康度、事件证据、集中度、敞口、UTC 日期交集相关性和 Markdown 报告。

> **Public Alpha**:契约与交互仍可能调整,请勿用于生产告警或交易决策。示例数据全部合成。

Expand Down Expand Up @@ -51,16 +51,17 @@ export QUANTCOCKPIT_DB_PATH=/absolute/path/to/quantcockpit.duckdb
1. 看顶部的连接状态、模式与最后刷新时间。
2. 在“数据可信度”确认导入错误为空;故意导入坏行时,此处显示安全摘要,不回显原始敏感内容。
3. 在“策略健康”查看状态,再到“证据详情”核对规则、阈值、观测值和事件引用。
4. 在“相关性”核对 `n` 和 UTC 日期窗口;不可计算时显示原因,不用 `0` 冒充结果。
5. 复制页面底部的本地命令生成报告:
4. 在“仓位覆盖”确认快照时间、仓位数量和能力等级,再到“集中度与敞口”核对 gross、net、Top-N、HHI、分类覆盖率与事件引用。
5. 在“相关性”核对 `n` 和 UTC 日期窗口;不可计算时显示原因,不用 `0` 冒充结果。
6. 复制页面底部的本地命令生成报告:

```bash
uv run scripts/generate_report.py --output quantcockpit-report.md --generated-at 2026-07-20T18:00:00Z
```

报告入口只提供可复制命令;只读 API 不会伪装成能够生成或下载报告。

## JSONL 输入契约
## 策略事件 JSONL 契约

每行是一条独立 JSON 事件。完整合成示例位于 [`examples/data`](examples/data)。

Expand All @@ -70,10 +71,10 @@ uv run scripts/generate_report.py --output quantcockpit-report.md --generated-at

公共字段:

- `schema_version`:当前固定为 `1.0`。
- `schema_version`:既有策略事件使用 `1.0`;规范仓位快照使用 `1.1`。
- `strategy_id`:1–128 字符,只允许字母、数字、点、下划线和连字符。
- `environment`:`live` 或 `paper`;只描述日志来源环境,不代表平台连接了真实账户。
- `event_type`:`heartbeat`、`run_status`、`nav` 或 `return`
- `event_type`:`heartbeat`、`run_status`、`nav`、`return` 或 `position_snapshot`;后者由仓位导入器生成,不要求现有策略直接输出
- `event_time`:事件发生时间;必须是 UTC 且包含时区,例如尾缀 `Z`。
- `recorded_at`:日志记录时间;同样必须是 UTC。
- `source`:生成日志的来源标识。
Expand All @@ -94,6 +95,40 @@ uv run scripts/generate_report.py --output quantcockpit-report.md --generated-at
uv run scripts/import_demo.py --database ./local.duckdb --data-dir ./path/to/jsonl
```

## 零侵入接入现有仓位文件

你不需要改交易策略或接券商 SDK。先导出现有系统已经保存的 CSV、JSON 或 JSONL,再用一个版本化映射配置说明“哪一列是什么”。零侵入不等于零配置:不同机构没有统一的实盘仓位日志结构,QuantCockpit 把适配成本收敛到可审查、可复用的 JSON 配置,而不是散落在交易代码里的胶水逻辑。

先预览合成示例。`--preview` 只读取、校验和输出最多 5 个安全样本,不创建或修改数据库:

```bash
uv run scripts/import_positions.py --input examples/positions/demo-positions.csv --profile examples/positions/demo-positions-profile.json --preview --observed-at 2026-07-20T18:00:00Z
```

确认 `snapshot_count`、来源字段、样本和 `mapping_profile_hash` 后再正式导入:

```bash
uv run scripts/import_positions.py --input examples/positions/demo-positions.csv --profile examples/positions/demo-positions-profile.json --database ./quantcockpit.duckdb --observed-at 2026-07-20T18:00:00Z
```

正式使用时复制 [`examples/positions/demo-positions-profile.json`](examples/positions/demo-positions-profile.json),修改输入格式和字段绑定。配置的核心字段如下:

| 区域 | 字段 | 说明 |
| --- | --- | --- |
| 配置 | `format` | `csv`、`json` 或 `jsonl` |
| 配置 | `layout` | 行式快照 `tabular_snapshot`,或含仓位数组的 `document_snapshot` |
| 配置 | `snapshot_scope` | 按元数据分组的 `grouped_rows`,或整文件一个快照的 `whole_file` |
| 快照元数据 | `strategy_id`、`environment`、`source`、`portfolio_id`、`snapshot_time` | 必填;每项可取固定 `literal` 或来源 `path` |
| 快照元数据 | `recorded_at`、`base_currency` | 可选;没有 `recorded_at` 时使用本次观察时间 |
| 仓位 | `instrument_id` | 必填;同一快照内与可选 `venue` 共同唯一 |
| 仓位数值 | `quantity`、`weight`、`market_value_base`、`exposure_value_base` | 至少映射一种;必须是有限定点十进制,不能用浮点或科学计数法 |
| 仓位分类 | `instrument_id_type`、`side`、`asset_class`、`sector`、`country` | 可选;缺失分类明确进入“未分类” |
| 转换 | `trim`、`uppercase`、`lowercase`、`decimal`、`utc_timestamp` | 按声明顺序执行;JSON 路径使用 RFC 6901 JSON Pointer |

本地无偏移时间必须同时配置 `timestamp_format` 和 IANA `assume_timezone`;夏令时重叠或不存在的时间会被拒绝。输入文件上限 100 MiB,单条记录上限 1 MiB,单快照上限 100,000 个仓位。CSV 表头必须唯一。JSONL 半写尾行会明确报错,不会被静默吞掉。

仓位身份严格是 `(portfolio_id, strategy_id, environment, source)`。同一快照重放会跳过,内容变化且记录时间更新会保留修订;分析只选择评估时点及之前的最新 current 快照。映射配置按 RFC 8785 规范化后计算 SHA-256,并随结果作为证据引用,因此改列映射不会伪装成同一份数据。

## API

API 是本机只读观察接口,不启用宽泛 CORS:
Expand All @@ -104,6 +139,8 @@ GET /api/v1/strategies
GET /api/v1/strategies/{strategy_id}/{environment}/health?source={source}
GET /api/v1/correlations
GET /api/v1/ingestion/errors
GET /api/v1/portfolios
GET /api/v1/portfolios/{portfolio_id}/exposure?strategy_id={strategy_id}&environment={environment}&source={source}
```

快速检查:
Expand All @@ -113,6 +150,8 @@ curl -fsS http://127.0.0.1:8000/healthz
curl -fsS http://127.0.0.1:8000/api/v1/strategies
curl -fsS 'http://127.0.0.1:8000/api/v1/strategies/healthy-demo/paper/health?source=synthetic-demo'
curl -fsS http://127.0.0.1:8000/api/v1/correlations
curl -fsS http://127.0.0.1:8000/api/v1/portfolios
curl -fsS 'http://127.0.0.1:8000/api/v1/portfolios/synthetic-book/exposure?strategy_id=healthy-demo&environment=paper&source=synthetic-demo'
```

健康接口的 `source` 查询参数必填,长度为 1–256。除 `/healthz` 外,API 每次请求都只读打开已经存在且由当前版本初始化的 DuckDB,绝不在请求路径执行 `CREATE` 或 `ALTER`。数据库缺失或未初始化时数据接口返回 `503` 且不会创建文件;`/healthz` 仍只表示 API 进程存活。先运行导入脚本,或显式执行一次 `DuckDBStore(path).close()`,再启动数据查询。
Expand All @@ -123,16 +162,19 @@ curl -fsS http://127.0.0.1:8000/api/v1/correlations

相关性是 Pearson 相关系数,严格按 UTC 日历日交集对齐,只保留双方均有限的样本,并且只读取评估时点及之前的收益。少于 3 个样本、无共同日期、零方差、重复日期或数值错误都会返回结构化 `reason` 和证据;不可计算不等于相关性为零。每一对结果还返回按左侧日期、右侧日期稳定排序的 `event_refs`,可直接追溯本次候选输入。

仓位分析不会混拼不同数值基础。它按 `exposure_value_base`、`market_value_base`、`weight` 的顺序选择第一个覆盖全部有效仓位的基础,对应能力等级 3、2、1;没有完整基础时返回 `unavailable`、候选基础和覆盖率,不伪造 gross、net 或集中度。明确空仓返回 `empty_portfolio`,与数据缺失严格区分。分类覆盖单独报告,缺失标签归为 `unclassified`。

更完整的数据流、公式与故障语义见 [`docs/architecture.md`](docs/architecture.md)。

## 架构与目录

```text
examples/data/*.jsonl
↓ 校验、幂等、修订、隔离
examples/data/*.jsonl ──────────────┐
现有 CSV / JSON / JSONL 仓位文件 ─→ 映射配置 + 安全预览
↓ 校验、幂等、修订、隔离
DuckDB (events / ingestion_runs / quarantine)
↓ current 只读查询
健康度 + UTC 日期相关性
健康度 + 仓位敞口/集中度 + UTC 日期相关性
├── FastAPI → React 观察台
└── 本地 Markdown 报告
```
Expand All @@ -153,11 +195,12 @@ make verify
## 局限与边界

- 本地单用户、单写者;没有认证、多租户、分布式锁或远程数据库支持。
- 当前只处理日频事件;时区统一为 UTC,不负责交易所日历、停牌或节假日语义。
- 策略收益仍按日频事件处理;仓位是离散快照,不是逐笔成交重建,也不负责交易所日历、停牌或节假日语义。
- 健康阈值是通用默认值,不替代策略自身的运行手册和告警系统。
- Pearson 相关性只描述选定窗口内的线性共同变化,不代表因果、未来稳定性或组合风险。
- v0.2 不含券商直连、因子 Beta、VaR、压力测试、告警派发或 AI 报告运行时;当前报告是确定性的本地模板。
- 前端桌面优先,1024px 可用;低于 900px 会给出明确提示,不提供移动布局。
- Alpha 不保证契约向后兼容;升级前请保留原始 JSONL
- Alpha 不保证契约向后兼容;升级前请保留原始输入文件和映射配置

## 作为求职作品的价值

Expand All @@ -166,3 +209,5 @@ make verify
## 贡献、安全与许可

贡献前请阅读 [`CONTRIBUTING.md`](CONTRIBUTING.md),安全问题请遵循 [`SECURITY.md`](SECURITY.md)。项目采用 [Apache License 2.0](LICENSE)。

设计判断与实施记录:[`v0.2 接入设计`](docs/superpowers/specs/2026-07-20-v0-2-position-ingestion-design.md)、[`v0.2 实施计划`](docs/superpowers/plans/2026-07-20-v0-2-position-ingestion.md)、[`v0.1 加固设计`](docs/superpowers/specs/2026-07-20-v0-1-hardening-design.md)、[`v0.1 加固计划`](docs/superpowers/plans/2026-07-20-v0-1-hardening.md) 和 [`Public Alpha 计划`](docs/superpowers/plans/2026-07-20-public-alpha.md)。这些文件保留“为什么这样做”的上下文,实际命令和支持范围以本 README 为准。
4 changes: 3 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Public Alpha 只支持当前默认分支。尚未承诺长期维护窗口或安

## 威胁模型与部署边界

QuantCockpit 设计为本机只读观察工具:API 默认只监听 `127.0.0.1`,没有认证,也不应直接暴露到公网。若自行更改监听地址或部署到共享网络,必须另行提供 TLS、认证、授权、速率限制和日志脱敏;这不在 Public Alpha 的支持范围内。
QuantCockpit 设计为本机只读观察工具:API 默认只监听 `127.0.0.1`,没有认证,也不应直接暴露到公网。仓位源文件只由本地进程读取,不上传到外部服务;DuckDB 保存校验后的规范事件、来源坐标、映射哈希,以及组成快照的原始记录证据。原始记录不会通过当前 API 返回,但导入前仍应删除与监控无关的敏感列。若自行更改监听地址或部署到共享网络,必须另行提供 TLS、认证、授权、速率限制和日志脱敏;这不在 Public Alpha 的支持范围内。

请把以下内容视为敏感并保持在 Git 之外:

Expand All @@ -22,3 +22,5 @@ QuantCockpit 设计为本机只读观察工具:API 默认只监听 `127.0.0.1`
- 含绝对路径或原始坏行的诊断输出。

仓库示例只允许固定、完全合成的 `paper` 数据。发现疑似真实数据或密钥时,请停止传播并按漏洞流程私密报告。

当前版本没有运行 AI 助手,也不会把日志或报告发送给模型提供商。未来若加入 AI 摘要,必须采用显式启用、数据最小化、供应商与保留策略可见、可在不配置模型时完整使用核心监控的设计;在这些边界实现并审计前,文档中的“AI 报告”只属于后续方向。
Loading