Skip to content

Commit 0e5df7f

Browse files
committed
Harden OpenAlphaStack data and execution integrity
1 parent a88ee57 commit 0e5df7f

41 files changed

Lines changed: 1902 additions & 362 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ data/output/
2626
data/memory/
2727
data/state/
2828
data/test_tmp/
29+
data/**/*.sqlite3
30+
data/**/*.sqlite3-wal
31+
data/**/*.sqlite3-shm
2932
data/*.json
3033
data/*.md
3134
*.log

AGENT_GUIDE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ validation, state, risk rules, backtests, and mechanical paper execution.
1212
3. Put Agent workflow instructions in `skills/`.
1313
4. Put live data and domain actions behind typed MCP tools.
1414
5. Keep risk limits, T+1 behavior, fees, state transitions, and idempotency in Python.
15-
6. MCP mutations are paper-only. Never expose a live-order tool before an explicit safety design and separate approval.
15+
6. Public engine modes are paper and backtest only. MCP mutations are paper-only; historical live runs remain read-only.
1616
7. Missing or stale plans keep the engine in observation mode; the engine must not invent a plan.
1717
8. The Dashboard is an observability surface, not an Agent terminal.
1818

@@ -22,7 +22,8 @@ validation, state, risk rules, backtests, and mechanical paper execution.
2222
- Do not expose arbitrary shell execution through HTTP, WebSocket, or MCP.
2323
- Do not commit `.env` or runtime data under `data/`.
2424
- Do not reveal private Feishu conversations or local secrets.
25-
- Preserve atomic writes and append-only ledgers.
25+
- Treat per-run SQLite as canonical; JSON/JSONL files are human-readable projections.
26+
- Preserve atomic state-plus-ledger commits and append-only ledger semantics.
2627

2728
## Development rules
2829

README.md

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ missing trading plan.
2323

2424
> Paper trading only. OpenAlphaStack does not place real orders and does not promise investment returns.
2525
26-
![OpenAlphaStack Dashboard](docs/assets/dashboard-workbench.jpg)
27-
2826
## Why OpenAlphaStack?
2927

3028
- **One plugin, two extension layers** — package reusable domain Skills and a
@@ -78,10 +76,22 @@ Requirements:
7876
```powershell
7977
git clone https://github.com/44-99/OpenAlphaStack.git
8078
cd OpenAlphaStack
81-
pip install -r requirements.txt
8279
pip install -e .
80+
openalphastack doctor
81+
```
82+
83+
The base install supports the Codex plugin, MCP contracts, and offline Demo path.
84+
Install only the surfaces you use:
85+
86+
```powershell
87+
pip install -e ".[market]" # AkShare-backed market providers
88+
pip install -e ".[engine]" # paper/backtest Parquet runtime
89+
pip install -e ".[dashboard]" # FastAPI Dashboard
90+
pip install -e ".[all]" # complete local development runtime
91+
8392
npm install
8493
npm run dashboard:build
94+
openalphastack doctor
8595
openalphastack app start
8696
```
8797

@@ -94,6 +104,22 @@ Use $market-analyzer to assess today's A-share market, cite the MCP data used,
94104
and finish with risks and invalidation conditions.
95105
```
96106

107+
### Offline first run
108+
109+
Market providers may be unavailable outside trading hours or behind a restricted
110+
network. To verify the complete Skill → MCP path without treating sample values
111+
as market facts, ask Codex:
112+
113+
```text
114+
Use $market-analyzer in offline demo mode. Read the market_overview and
115+
market_news demo datasets, show their schema version, source, as-of time and
116+
freshness status, then produce a short report clearly labelled as synthetic data.
117+
```
118+
119+
The `read_demo_dataset` MCP tool is read-only and deterministic. Skills must not
120+
publish Demo-derived values into a paper plan. Available datasets cover market
121+
overview, screening, quote, technical, fundamentals, news and a baseline backtest.
122+
97123
The repository is also a Codex plugin: `.codex-plugin/plugin.json` discovers the
98124
Skills and `.mcp.json` registers the stdio server. After installing the Python
99125
package, install/open the plugin in Codex and verify the `open-alpha-stack` MCP
@@ -105,6 +131,13 @@ Start the MCP server manually for diagnostics:
105131
openalphastack mcp serve
106132
```
107133

134+
Check the local installation at any time:
135+
136+
```powershell
137+
openalphastack doctor
138+
openalphastack doctor --json
139+
```
140+
108141
## Codex Skills
109142

110143
- `$market-analyzer`: market environment, sentiment, sectors, and leaders.
@@ -121,13 +154,35 @@ Codex Desktop to remain running.
121154
Read tools expose paper/backtest runs, market data, indicators, news, screens,
122155
risk calculations, and deterministic baseline backtests.
123156

157+
Every MCP tool returns a versioned envelope:
158+
159+
```json
160+
{
161+
"schema_version": "openalphastack.mcp/v1",
162+
"ok": true,
163+
"data": {},
164+
"meta": {
165+
"source": "provider-or-demo-dataset",
166+
"as_of": "2026-07-23T10:00:00+08:00",
167+
"freshness": {"status": "fresh"},
168+
"demo": false
169+
}
170+
}
171+
```
172+
173+
Callers must check `ok` before reading `data`. Failures use a stable
174+
`error.code` and do not expose provider exception text. JSON schemas are
175+
available through `get_contracts` and `openalphastack://contracts/v1`.
176+
124177
The only plan mutations are:
125178

126179
1. `save_plan_draft` — writes a non-executable `plan.codex-draft.json`.
127180
2. `publish_paper_plan` — validates, requires an idempotency key, checks the
128181
expected plan version, and atomically updates a paper run only.
129182

130-
Live runs are hidden from MCP mutations. No shell, arbitrary file-write, or live-order tool is exposed.
183+
There is no public live mode: the CLI cannot start or resume one, and MCP has no
184+
live-order tool. Historical `live_*` directories remain read-only for migration
185+
and audit. No shell or arbitrary file-write tool is exposed.
131186

132187
## Engine commands
133188

@@ -146,6 +201,16 @@ The paper engine can stay running outside trading hours. It idles according to
146201
the trading calendar and remains observation-only until Codex publishes a valid
147202
plan for the current date.
148203

204+
Each run uses `run.sqlite3` as the transactional source of truth for account
205+
state, the active plan, and ledger events. `state.json`, `plan.json`, and
206+
`ledger.jsonl` are human-readable projections. A trade updates account state and
207+
its matching ledger event in one SQLite transaction.
208+
209+
Backtests require real cached or provider minute bars. Missing intraday data now
210+
fails closed instead of fabricating bars from daily OHLC. Backtest output remains
211+
experimental evidence—not a profitability claim—until walk-forward,
212+
out-of-sample, and baseline comparisons are implemented.
213+
149214
## Verification
150215

151216
```powershell

docs/architecture.md

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ Scheduled premarket task
2727
-> validate_paper_plan
2828
-> save_plan_draft
2929
-> publish_paper_plan (paper only, idempotent, optimistic concurrency)
30-
-> paper engine refreshes newer plan.json
30+
-> paper engine refreshes the newer validated plan from run.sqlite3
3131
-> FastLane applies deterministic rules
32-
-> append ledger and workflow events
32+
-> atomically commit account state + ledger event to run.sqlite3
33+
-> refresh human-readable JSON/JSONL projections and workflow events
3334
-> scheduled postclose prompt reviews facts without mutation
3435
```
3536

@@ -40,7 +41,10 @@ Scheduled premarket task
4041
- The engine may execute a valid current plan; it may not call a model.
4142
- Emergency handling is deterministic and notification-based.
4243
- A missing, stale, or invalid plan produces observation mode.
43-
- Ledger records are append-only.
44+
- SQLite is the per-run source of truth; JSON and JSONL are projections.
45+
- Account mutations and their ledger events commit in one SQLite transaction.
46+
- Missing intraday bars fail closed; backtests never synthesize minute bars from daily OHLC.
47+
- Public engine modes are paper and backtest only. Historical live runs are read-only.
4448

4549
## MCP surface
4650

@@ -63,6 +67,36 @@ Mutation group:
6367
Every publication requires an idempotency key. Optional `expected_updated`
6468
provides optimistic concurrency against a plan changed since the Agent read it.
6569

70+
### Versioned response contract
71+
72+
All MCP tools return the `openalphastack.mcp/v1` envelope. Consumers check `ok`
73+
before reading `data`; failures contain a stable `error.code`, retryability and
74+
non-sensitive details. Market responses expose `meta.source`, `meta.as_of` and
75+
`meta.freshness`. Plans and run snapshots use the separate
76+
`openalphastack.plan/v1` and `openalphastack.run-snapshot/v1` contracts.
77+
78+
Resources:
79+
80+
- `openalphastack://contracts/v1`
81+
- `openalphastack://demo/catalog`
82+
- `openalphastack://demo/{dataset}`
83+
- `openalphastack://runs/{run_id}/snapshot`
84+
- `openalphastack://runs/{run_id}/ledger`
85+
86+
The bundled Demo datasets are static synthetic fixtures. They support offline
87+
Skill verification and cannot mutate or publish a trading plan. Dashboard Demo
88+
account, plan, and ledger fixtures share the same `demo_data` ownership boundary;
89+
chart and workflow fixtures remain explicitly UI-only presentation data.
90+
91+
## Persistence boundary
92+
93+
Every paper or backtest run owns a `run.sqlite3` database containing runtime
94+
state, the active validated plan, and append-only ledger events. SQLite WAL,
95+
full synchronous commits, and immediate write transactions provide the
96+
cross-record atomicity boundary. `state.json`, `plan.json`, and `ledger.jsonl`
97+
exist for operator inspection and compatibility; corrupt or stale projections
98+
must not override a valid database.
99+
66100
## Scheduling boundary
67101

68102
Codex scheduled tasks compose the domain Skills for premarket research,

docs/roadmap.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,22 @@
1111
- ✅ Paper engine reloads externally published plans and stays observation-only without one.
1212
- ✅ Embedded Agent terminal and in-process Agent scheduling removed from the main path.
1313
- ✅ Backtests no longer invoke an Agent internally.
14+
- ✅ Public live start/resume paths removed; historical live runs are read-only.
1415

1516
## Next: MCP contract hardening
1617

17-
- Add explicit JSON schemas and version fields for plans and run snapshots.
18-
- Add source freshness and provenance to every market-data response.
19-
- Add structured MCP errors rather than provider-specific exception text.
20-
- Add resource URIs for plan, state, ledger, reports, and strategy metrics.
21-
- Add a read-only demo dataset for Skill forward tests.
18+
- ✅ Added explicit JSON schemas and version fields for plans and run snapshots.
19+
- ✅ Added source freshness and provenance to every MCP market-data response.
20+
- ✅ Added structured MCP errors without provider exception text.
21+
- ✅ Added contract, Demo, run snapshot, and ledger resource URIs.
22+
- ✅ Added a read-only synthetic Demo dataset and Skill forward-contract tests.
23+
- Add dedicated report and strategy-metric resource URIs after their persisted schemas stabilize.
2224

2325
## Next: deterministic runtime
2426

27+
- ✅ Persist state, active plans, and ledger events in a per-run SQLite source of truth.
28+
- ✅ Commit account mutations and matching ledger events atomically.
29+
- ✅ Reject missing intraday data instead of synthesizing minute bars from daily OHLC.
2530
- Run the paper engine as a long-lived local service that idles outside exchange sessions.
2631
- Make plan activation a first-class state transition with an audit event.
2732
- Add plan expiry and automatic observation fallback.
@@ -38,13 +43,13 @@
3843

3944
## Next: product and distribution
4045

41-
- Replace the old screenshot with a Dashboard image without the Agent terminal.
46+
- Remove the obsolete Agent-terminal screenshot and capture a verified current Dashboard image.
4247
- Record a short Codex Scheduled task -> Skill -> MCP -> paper plan demo.
4348
- Publish honest benchmark and failure reports rather than return promises.
4449
- Publish plugin installation and scheduled-task composition examples.
4550

4651
## Live trading
4752

48-
Live trading remains unimplemented and inaccessible through MCP. It requires a
53+
Live trading remains unimplemented and inaccessible through the CLI and MCP. It requires a
4954
separate BrokerAdapter, explicit human confirmation, order idempotency, restart
5055
recovery, kill switches, authenticated deployment, and a new security review.

pyproject.toml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,36 @@ version = "0.1.0"
88
description = "Open-source Codex plugin stack for auditable A-share research and paper trading"
99
requires-python = ">=3.10"
1010
dependencies = [
11+
"mcp>=1.2.0,<2.0.0",
12+
"pydantic>=2.10.0,<3.0.0",
13+
"python-dotenv==1.0.1",
14+
"pandas>=2.2.0",
15+
"requests>=2.32.0",
16+
]
17+
18+
[project.optional-dependencies]
19+
market = [
20+
"akshare>=1.16.0",
21+
]
22+
engine = [
23+
"pyarrow>=16.0.0",
24+
]
25+
dashboard = [
1126
"fastapi==0.115.6",
1227
"uvicorn==0.34.0",
28+
"pyarrow>=16.0.0",
29+
]
30+
feishu = [
1331
"httpx==0.28.1",
14-
"pandas>=2.2.0",
15-
"akshare>=1.16.0",
16-
"python-dotenv==1.0.1",
1732
"lark-oapi>=1.4.0",
33+
]
34+
all = [
35+
"akshare>=1.16.0",
1836
"pyarrow>=16.0.0",
19-
"mcp>=1.2.0,<2.0.0",
37+
"fastapi==0.115.6",
38+
"uvicorn==0.34.0",
39+
"httpx==0.28.1",
40+
"lark-oapi>=1.4.0",
2041
]
2142

2243
[project.scripts]

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Full local development/runtime environment. End users should prefer
2+
# `pip install -e .` or `pip install -e ".[all]"` as documented in README.md.
13
fastapi==0.115.6
24
uvicorn==0.34.0
35
httpx==0.28.1
@@ -7,3 +9,5 @@ python-dotenv==1.0.1
79
lark-oapi>=1.4.0
810
pyarrow>=16.0.0
911
mcp>=1.2.0,<2.0.0
12+
pydantic>=2.10.0,<3.0.0
13+
requests>=2.32.0

skills/market-analyzer/SKILL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,10 @@ description: 分析 A 股大盘、市场情绪、板块轮动和龙头线索。
1717
6. 输出市场环境、情绪阶段、板块线索、龙头证据、数据限制和适用的风险暴露区间。
1818

1919
不要把市场研判直接当作买卖指令,也不要承诺收益。
20+
21+
## MCP 响应契约
22+
23+
- 每次调用先检查 `schema_version``ok`,只有 `ok=true` 才读取 `data`
24+
- 引用数据时保留 `meta.source``meta.as_of``meta.freshness.status`;状态为 `stale``unknown` 时降低结论置信度。
25+
- `ok=false` 时报告结构化的 `error.code`,不得把缺失数据补写成事实。
26+
- 用户要求离线演示或实时数据全部不可用时,依次调用 `read_demo_dataset(dataset="market_overview")``read_demo_dataset(dataset="market_news")`;必须明确标记 `meta.demo=true`,不得将 Demo 数值解释为今日行情。

skills/stock-analyzer/SKILL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@ description: 对具体 A 股进行技术面、基本面、新闻、位置和风
1919
8. 输出趋势、信号、位置、风险、研究建议、数据时间和缺失信息。
2020

2121
价格区间、止损和止盈必须说明依据。不得绕过 MCP 直接写 `plan.json`,不得提交真实订单,也不得把一次分析表述为收益保证。
22+
23+
## MCP 响应契约
24+
25+
- 每次调用先检查 `schema_version``ok`,分析字段只从 `data` 读取。
26+
- 报告数据来源时引用 `meta.source``meta.as_of``meta.freshness.status`;过期或时间未知的数据必须进入风险部分。
27+
- `ok=false` 时依据 `error.code` 决定重试或停止,不得把供应商异常当作个股事实。
28+
- 离线演示可读取 `stock_quote``stock_technical``stock_fundamentals``stock_news` Demo 数据集;必须注明是合成数据,不能形成真实股票建议。

skills/stock-screener/SKILL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,10 @@ description: 使用确定性规则筛选 A 股候选标的。用户要求选股
2020
6. 输出代码、名称、筛选依据、复核证据、风险和数据时间;结果不足时不要补齐数量。
2121

2222
如需进一步分析某只股票,转入 `$stock-analyzer`。如需形成模拟盘计划,必须另外读取目标 paper run、校验计划并通过 MCP 保存草稿;本 Skill 不直接发布计划。
23+
24+
## MCP 响应契约
25+
26+
- 每次调用先检查 `schema_version``ok`,候选数据只从 `data` 读取。
27+
- 输出必须携带 `meta.source``meta.as_of``meta.freshness.status``stale``unknown` 数据不能支持强结论。
28+
- `ok=false` 时使用 `error.code` 说明失败,不得为了凑足候选数量而虚构结果。
29+
- 离线演示可依次读取 `screen_candidates``stock_quote``stock_technical``stock_news` Demo 数据集,并显式标注 `meta.demo=true`;Demo 候选不能转成模拟盘计划。

0 commit comments

Comments
 (0)