trade-trace 0.0.1rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. trade_trace-0.0.1rc2/LICENSE +21 -0
  2. trade_trace-0.0.1rc2/PKG-INFO +238 -0
  3. trade_trace-0.0.1rc2/README.md +220 -0
  4. trade_trace-0.0.1rc2/pyproject.toml +42 -0
  5. trade_trace-0.0.1rc2/setup.cfg +4 -0
  6. trade_trace-0.0.1rc2/src/trade_trace/__init__.py +5 -0
  7. trade_trace-0.0.1rc2/src/trade_trace/cli.py +266 -0
  8. trade_trace-0.0.1rc2/src/trade_trace/clock.py +60 -0
  9. trade_trace-0.0.1rc2/src/trade_trace/contracts/__init__.py +45 -0
  10. trade_trace-0.0.1rc2/src/trade_trace/contracts/envelope.py +98 -0
  11. trade_trace-0.0.1rc2/src/trade_trace/contracts/errors.py +24 -0
  12. trade_trace-0.0.1rc2/src/trade_trace/contracts/grammar.py +80 -0
  13. trade_trace-0.0.1rc2/src/trade_trace/contracts/report_filter.py +167 -0
  14. trade_trace-0.0.1rc2/src/trade_trace/contracts/tool_registry.py +167 -0
  15. trade_trace-0.0.1rc2/src/trade_trace/core.py +237 -0
  16. trade_trace-0.0.1rc2/src/trade_trace/events/__init__.py +27 -0
  17. trade_trace-0.0.1rc2/src/trade_trace/events/log.py +332 -0
  18. trade_trace-0.0.1rc2/src/trade_trace/events/semantic_keys.py +329 -0
  19. trade_trace-0.0.1rc2/src/trade_trace/events/unit_of_work.py +113 -0
  20. trade_trace-0.0.1rc2/src/trade_trace/exporter.py +353 -0
  21. trade_trace-0.0.1rc2/src/trade_trace/mcp_server.py +66 -0
  22. trade_trace-0.0.1rc2/src/trade_trace/models/__init__.py +43 -0
  23. trade_trace-0.0.1rc2/src/trade_trace/models/ledger.py +181 -0
  24. trade_trace-0.0.1rc2/src/trade_trace/models/memory.py +41 -0
  25. trade_trace-0.0.1rc2/src/trade_trace/projections.py +327 -0
  26. trade_trace-0.0.1rc2/src/trade_trace/reports/__init__.py +74 -0
  27. trade_trace-0.0.1rc2/src/trade_trace/reports/buckets.py +105 -0
  28. trade_trace-0.0.1rc2/src/trade_trace/reports/calibration.py +337 -0
  29. trade_trace-0.0.1rc2/src/trade_trace/reports/coach.py +308 -0
  30. trade_trace-0.0.1rc2/src/trade_trace/reports/decision_velocity.py +118 -0
  31. trade_trace-0.0.1rc2/src/trade_trace/reports/integrity.py +223 -0
  32. trade_trace-0.0.1rc2/src/trade_trace/reports/playbook_adherence.py +136 -0
  33. trade_trace-0.0.1rc2/src/trade_trace/reports/pnl.py +93 -0
  34. trade_trace-0.0.1rc2/src/trade_trace/reports/source_quality.py +311 -0
  35. trade_trace-0.0.1rc2/src/trade_trace/reports/tag_aggregates.py +138 -0
  36. trade_trace-0.0.1rc2/src/trade_trace/reports/unscored.py +95 -0
  37. trade_trace-0.0.1rc2/src/trade_trace/reports/watchlist.py +91 -0
  38. trade_trace-0.0.1rc2/src/trade_trace/security/__init__.py +28 -0
  39. trade_trace-0.0.1rc2/src/trade_trace/security/patterns.py +179 -0
  40. trade_trace-0.0.1rc2/src/trade_trace/storage/__init__.py +31 -0
  41. trade_trace-0.0.1rc2/src/trade_trace/storage/database.py +120 -0
  42. trade_trace-0.0.1rc2/src/trade_trace/storage/migrations.py +1053 -0
  43. trade_trace-0.0.1rc2/src/trade_trace/storage/paths.py +34 -0
  44. trade_trace-0.0.1rc2/src/trade_trace/storage/policy.py +241 -0
  45. trade_trace-0.0.1rc2/src/trade_trace/timestamps.py +59 -0
  46. trade_trace-0.0.1rc2/src/trade_trace/tools/__init__.py +14 -0
  47. trade_trace-0.0.1rc2/src/trade_trace/tools/_examples.py +172 -0
  48. trade_trace-0.0.1rc2/src/trade_trace/tools/_helpers.py +259 -0
  49. trade_trace-0.0.1rc2/src/trade_trace/tools/admin.py +446 -0
  50. trade_trace-0.0.1rc2/src/trade_trace/tools/decision_matrix.py +129 -0
  51. trade_trace-0.0.1rc2/src/trade_trace/tools/errors.py +24 -0
  52. trade_trace-0.0.1rc2/src/trade_trace/tools/fixture.py +468 -0
  53. trade_trace-0.0.1rc2/src/trade_trace/tools/imports.py +115 -0
  54. trade_trace-0.0.1rc2/src/trade_trace/tools/journal.py +388 -0
  55. trade_trace-0.0.1rc2/src/trade_trace/tools/ledger.py +1463 -0
  56. trade_trace-0.0.1rc2/src/trade_trace/tools/memory.py +901 -0
  57. trade_trace-0.0.1rc2/src/trade_trace/tools/playbook.py +616 -0
  58. trade_trace-0.0.1rc2/src/trade_trace/tools/reflection.py +226 -0
  59. trade_trace-0.0.1rc2/src/trade_trace/tools/reports.py +501 -0
  60. trade_trace-0.0.1rc2/src/trade_trace/tools/review_bundle.py +75 -0
  61. trade_trace-0.0.1rc2/src/trade_trace/tools/signals.py +268 -0
  62. trade_trace-0.0.1rc2/src/trade_trace/tools/strategy.py +393 -0
  63. trade_trace-0.0.1rc2/src/trade_trace/version.py +2 -0
  64. trade_trace-0.0.1rc2/src/trade_trace.egg-info/PKG-INFO +238 -0
  65. trade_trace-0.0.1rc2/src/trade_trace.egg-info/SOURCES.txt +69 -0
  66. trade_trace-0.0.1rc2/src/trade_trace.egg-info/dependency_links.txt +1 -0
  67. trade_trace-0.0.1rc2/src/trade_trace.egg-info/entry_points.txt +3 -0
  68. trade_trace-0.0.1rc2/src/trade_trace.egg-info/requires.txt +9 -0
  69. trade_trace-0.0.1rc2/src/trade_trace.egg-info/top_level.txt +1 -0
  70. trade_trace-0.0.1rc2/tests/test_smoke.py +80 -0
  71. trade_trace-0.0.1rc2/tests/test_timestamps.py +59 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Trade Trace contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: trade-trace
3
+ Version: 0.0.1rc2
4
+ Summary: Local, open-source, AI-only journal, memory, and calibration substrate for LLM trading agents.
5
+ Author: Trade Trace contributors
6
+ License: MIT
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pydantic<3,>=2.7
11
+ Provides-Extra: mcp
12
+ Requires-Dist: mcp>=1.0; extra == "mcp"
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=8; extra == "dev"
15
+ Requires-Dist: ruff>=0.5; extra == "dev"
16
+ Requires-Dist: mypy>=1.10; extra == "dev"
17
+ Dynamic: license-file
18
+
19
+ # Trade Trace
20
+
21
+ **A local, open-source, AI-only journal, memory, and calibration substrate for LLM trading agents.**
22
+
23
+ Trade Trace records trading decisions an LLM agent makes and helps the agent improve through a closed learning loop: journal a decision, resolve the outcome, score calibration, review deterministic reports, write reflections, update a versioned playbook, and recall that learning next time. It runs locally, exposes both an MCP server and a CLI with JSON-first contracts, and never executes trades.
24
+
25
+ ## What this is
26
+
27
+ - A **decision journal** with instruments, snapshots, theses, forecasts, outcomes, and process tags.
28
+ - A **trading-native memory layer** modeled on Retain / Recall / Reflect, with outcome-linked and calibration-aware recall.
29
+ - A **binary MVP calibration grader** that scores supported binary forecasts with Brier score when outcomes resolve.
30
+ - A **playbook loop** that versions rules, records manual/advisory overrides, and keeps provenance from reflections.
31
+ - **Strategies** that group decisions, theses, and reviews under a named edge thesis (e.g., `earnings-momentum`) so reports, recall, and reflection can be scoped to one logical grain without depending on free-form tags.
32
+ - An **MCP server** and **CLI** whose schemas and semantics are equivalent after transport normalization.
33
+
34
+ ## What this is not
35
+
36
+ - Not a trade executor. No order signing, wallet handling, broker credentials, seed phrases, or trade routing.
37
+ - Not a human dashboard. There is no product web UI; P2 may add optional static/read-only inspection exports.
38
+ - Not a generic agent memory framework. The schema is trading-shaped.
39
+ - Not a backtesting engine, tax accountant, social platform, or source of financial advice.
40
+
41
+ For the full vision, see [`VISION.md`](./VISION.md). For the working PRD, see [`PRD.md`](./PRD.md).
42
+
43
+ ## Status
44
+
45
+ **M0 / M1 / M2 / M3 / M4 shipped.** All four milestones cleared their
46
+ implementation, test-QC, docs-QC, and gate beads. Package skeleton +
47
+ storage + full manual write surface, event log + outbox + idempotency,
48
+ deterministic reports + integrity / source-quality diagnostics +
49
+ sample-size warnings, memory graph (retain/reflect/link/recall) with
50
+ bi-temporal validity + RRF over BM25 + temporal + graph, first-class
51
+ strategies, playbook versioning + normalized adherence + override-outcome
52
+ tracking, deterministic reflection-prompt packet, secret-pattern write
53
+ guard + file-permission + no-telemetry audit, journal backup/restore
54
+ with SHA-256 manifest, deterministic-replay clock injection + fixture
55
+ seed. The P1+ work that remains (embeddings opt-in, review.bundle / import
56
+ implementations, web/sync features) is explicitly scoped out of MVP and
57
+ tracked under beads `trade-trace-a4p` and the P1 design docs.
58
+
59
+ What works today:
60
+
61
+ - `pip install -e .` then `tt journal init` creates `$TRADE_TRACE_HOME/trade-trace.sqlite` with WAL, 5s busy_timeout, 0600 permissions, and the current schema head.
62
+ - The full manual ledger write surface: `venue.add`, `instrument.add`, `snapshot.add`, `thesis.add`, `forecast.add` (binary invariants enforced as `INVARIANT_VIOLATION`), `forecast.supersede`, `decision.add` (13-type required-field matrix enforced), `outcome.add` / `resolve.record` alias, `resolve.pending`, `source.add`, `source.attach_to_{thesis,decision,forecast}`. `source.attach_to_memory_node` returns `UNSUPPORTED_CAPABILITY` until M3.
63
+ - Decision → outcome → auto-scoring loop: an `outcome.add` with `status="resolved_final"` automatically scores every pending binary forecast against the resolved label using the single-probability Brier form per [`docs/architecture/scoring.md`](./docs/architecture/scoring.md) §3.
64
+ - Idempotent retries: every retryable write requires `idempotency_key` (per PRD §2); pure replays return the original event row with `meta.idempotent_replay=true`; semantically-different payloads return `IDEMPOTENCY_CONFLICT` with a structural diff (no raw bodies leaked).
65
+ - Append-only invariants enforced at the SQLite layer via BEFORE UPDATE/DELETE triggers on every M1 source/event table; the projection (`positions`) and the outbox state column are the only exceptions.
66
+ - `import.validate` and `import.commit` registered as contract stubs (P1 implementation pending); their schemas + the `import_ready_writers` list are introspectable today.
67
+ - `review.bundle` registered as a contract stub (P1 implementation pending); the input/output Pydantic schemas including `bundle_hash` are introspectable today.
68
+ - CLI emits NDJSON for list tools (`tt resolve pending`) with one envelope per record plus a summary line per [`docs/architecture/contracts.md`](./docs/architecture/contracts.md) §1.2; exit code mapping: `VALIDATION_ERROR`→2, `INVARIANT_VIOLATION`→3, other errors→1.
69
+ - A registration-time + startup CLI-name-collision check ensures two MCP tool names can never map to the same `tt` invocation; the runtime check emits a `STORAGE_ERROR` envelope rather than a Python traceback.
70
+ - UTC timestamps validated at the boundary: naive timestamps rejected, non-UTC offsets converted, sub-millisecond digits truncated.
71
+ - Outbound network is unconditionally off by default: `tests/security/test_no_network_default.py` monkeypatches `socket.connect`/`getaddrinfo` to refuse any outbound attempt and exercises the full ledger flow without a single call escaping.
72
+ - Credential-shaped args (api_key, wallet_seed, private_key, mnemonic, broker_token, etc.) are silently ignored by every write tool and never persist in any column or `metadata_json` blob; verified by `tests/security/test_no_credentials.py`.
73
+
74
+ Design artifacts:
75
+
76
+ - [`VISION.md`](./VISION.md) — north star
77
+ - [`PRD.md`](./PRD.md) — working PRD and MVP scope
78
+ - [`docs/architecture/memory-layer.md`](./docs/architecture/memory-layer.md) — memory layer spec (node taxonomy, retrieval, bi-temporal validity, embeddings posture)
79
+ - [`docs/architecture/scoring.md`](./docs/architecture/scoring.md) — forecast scoring (Brier, log score, ECE, sharpness, reliability bins, lifecycle, `failure_reason` enum)
80
+ - [`docs/architecture/persistence.md`](./docs/architecture/persistence.md) — events, outbox, idempotency (incl. §5.2.1 per-event-type structural-field registry)
81
+ - [`docs/architecture/contracts.md`](./docs/architecture/contracts.md) — CLI/MCP envelope and error codes
82
+ - [`docs/architecture/operability.md`](./docs/architecture/operability.md) — timezone, multi-process, migrations, logging, blob caps, JSONL on-disk format
83
+ - [`docs/architecture/reports.md`](./docs/architecture/reports.md) — `ReportFilter` / `ReportResult` / drill-down / `review.bundle`
84
+ - [`docs/architecture/imports.md`](./docs/architecture/imports.md) — JSONL/CSV local-import contract
85
+ - [`docs/architecture/risk-units.md`](./docs/architecture/risk-units.md) — P1 risk-unit / R-multiple analytics design
86
+ - [`docs/architecture/opportunity-analysis.md`](./docs/architecture/opportunity-analysis.md) — P1 path-dependent process diagnostics
87
+ - [`docs/architecture/dogfood-protocol.md`](./docs/architecture/dogfood-protocol.md) — MVP loop-usefulness protocol and provenance policies
88
+
89
+ ## Install
90
+
91
+ Today (development):
92
+
93
+ ```bash
94
+ pip install -e .
95
+ tt journal init
96
+ ```
97
+
98
+ The published package (`pip install trade-trace`) ships once the MVP M1–M4
99
+ write surface lands. Requirements today: Python 3.11+, SQLite with FTS5.
100
+ The base wheel will ship `sqlite-vec` and `sentence-transformers` as runtime
101
+ dependencies once M3 lands.
102
+
103
+ **Vectors are off by default in MVP**: a fresh `journal.init` makes zero
104
+ outbound network calls (verified by `tests/security/test_no_network_default.py`).
105
+ MVP recall runs with FTS5 + graph + temporal retrieval. Opt in to semantic
106
+ recall via `tt config set embeddings.provider local` (one-time model-weight
107
+ download, ~130 MB; lands in M3) or `tt model import <path>` for air-gapped
108
+ installs. See [`docs/architecture/memory-layer.md`](./docs/architecture/memory-layer.md)
109
+ §8.
110
+
111
+ Trade Trace never fetches trading data, broker data, market prices, order books, or outcomes. The agent calling it supplies all market data through the structured ingestion APIs. The single opt-in outbound path (embedding model download) carries no trading data; the optional API-embeddings path is separately opt-in and warned about at configure time. See [`PRD.md`](./PRD.md) §2.4.1.
112
+
113
+ ## MVP vertical slice
114
+
115
+ The MVP proves a complete learning-loop slice with narrow breadth:
116
+
117
+ 1. `journal.init`
118
+ 2. manual `instrument.add` / `snapshot.add` / `thesis.add` / binary `forecast.add` / `decision.add` — with optional `strategy_id` linkage to a named strategy
119
+ 3. optional `strategy.create` to group decisions/theses/reviews under a named edge thesis (M3; nullable FK column is reserved in M1)
120
+ 4. `outcome.add`
121
+ 5. binary Brier scoring
122
+ 6. deterministic reports and `report.coach` — all accept an optional `strategy_id` filter
123
+ 7. agent-written `memory.reflect`, including reflections targeted at a strategy
124
+ 8. `playbook.propose_version` with advisory/manual override tracking
125
+ 9. `memory.recall` during the next thesis, optionally scoped to a strategy
126
+
127
+ Deferred or optional after the manual loop: JSONL/CSV import implementations (the write schemas are import-ready in MVP), `sqlite-vec` semantic recall, multi-class/scalar scoring, trading-native edge/market reports (forecast-vs-market, calibration-by-liquidity-bucket), `report.compare`, `report.strategy_performance`, `report.risk` (see [`docs/architecture/risk-units.md`](./docs/architecture/risk-units.md)), `report.opportunity` (see [`docs/architecture/opportunity-analysis.md`](./docs/architecture/opportunity-analysis.md)), `review.bundle` implementation, exact ForecastBench compatibility, sync, HTTP/SSE, websockets, and a web viewer.
128
+
129
+ ## Quickstart for an agent (MCP, planned)
130
+
131
+ ```jsonc
132
+ {"tool": "journal.init"}
133
+
134
+ {"tool": "instrument.add", "args": {
135
+ "venue": "manual",
136
+ "asset_class": "prediction_market",
137
+ "title": "Will X happen by 2026-06-30?",
138
+ "currency_or_collateral": "USDC",
139
+ "actor_id": "agent:default"
140
+ }}
141
+
142
+ {"tool": "strategy.create", "args": {"name": "Thin-liquidity prediction markets", "slug": "thin-liquidity-prediction-markets", "hypothesis": "Markets with < $5K ADV near resolution are systematically mispriced; favor skips when spread > expected edge.", "actor_id": "agent:default"}}
143
+
144
+ {"tool": "snapshot.add", "args": {"instrument_id": "...", "price": 0.37, "bid": 0.36, "ask": 0.39, "actor_id": "agent:default"}}
145
+ {"tool": "thesis.add", "args": {"instrument_id": "...", "side": "yes", "body": "...", "falsification_criteria": "...", "strategy_id": "...", "actor_id": "agent:default"}}
146
+ {"tool": "forecast.add", "args": {"thesis_id": "...", "kind": "binary", "outcomes": [{"label": "YES", "probability": 0.48}, {"label": "NO", "probability": 0.52}], "actor_id": "agent:default"}}
147
+ {"tool": "decision.add", "args": {"instrument_id": "...", "thesis_id": "...", "type": "skip", "reason": "Estimated edge < spread + resolution risk", "strategy_id": "...", "tags": ["liquidity-ignored", "good-skip"], "actor_id": "agent:default"}}
148
+
149
+ {"tool": "outcome.add", "args": {"instrument_id": "...", "outcome_label": "NO", "outcome_value": 0.0, "status": "resolved_final", "resolved_at": "2026-06-30T00:00:00Z", "actor_id": "agent:default"}}
150
+
151
+ {"tool": "report.coach", "args": {"horizon_days": 30, "strategy_id": "..."}}
152
+
153
+ {"tool": "memory.reflect", "args": {
154
+ "target": {"kind": "decision", "id": "..."},
155
+ "insight": "Skip was correct here; spread compression never materialized.",
156
+ "strength_tags": ["good-skip", "good-liquidity-discipline"],
157
+ "actor_id": "agent:default"
158
+ }}
159
+
160
+ {"tool": "memory.recall", "args": {"context": {"kind": "strategy", "id": "..."}, "node_types": ["observation", "reflection", "playbook_rule"], "k": 10}}
161
+ ```
162
+
163
+ ## CLI dogfood surface
164
+
165
+ The CLI mirrors the MCP tool catalog. Stdout is JSON only by default;
166
+ `--human` may add prose to stderr without changing stdout semantics.
167
+
168
+ Working today (M0 + M1):
169
+
170
+ ```bash
171
+ # Foundation
172
+ tt journal init # idempotent SQLite bootstrap
173
+ tt journal status # version + capability report
174
+ tt journal schema --tool Decision # Pydantic JSON schema for a model
175
+
176
+ # Manual ledger write path (M1)
177
+ tt venue add --name "Polymarket" --kind prediction_market --actor-id agent:default
178
+ tt instrument add --venue-id ven_... --asset-class prediction_market \
179
+ --title "Will X happen by 2026-06-30?" --currency-or-collateral USDC \
180
+ --actor-id agent:default
181
+ tt snapshot add --instrument-id ins_... --captured-at 2026-05-18T14:00:00Z \
182
+ --price 0.37 --bid 0.36 --ask 0.39 --actor-id agent:default
183
+ tt thesis add --instrument-id ins_... --side yes --body "..." --actor-id agent:default
184
+ tt forecast add --thesis-id th_... --kind binary \
185
+ --outcomes-json '[{"outcome_label":"YES","probability":0.48},{"outcome_label":"NO","probability":0.52}]' \
186
+ --resolution-at 2026-06-30T00:00:00Z --actor-id agent:default
187
+ tt decision add --instrument-id ins_... --type skip \
188
+ --reason "Estimated edge < spread + resolution risk" --actor-id agent:default
189
+ tt outcome add --instrument-id ins_... --resolved-at 2026-06-30T00:00:00Z \
190
+ --outcome-label NO --status resolved_final --actor-id agent:default
191
+ # (auto-scoring fires; forecast_scores row appears)
192
+
193
+ # Source / evidence (M1)
194
+ tt source add --kind research_doc --title "Liquidity profile" --stance supports \
195
+ --actor-id agent:default
196
+ tt source attach_to_thesis --source-id src_... --target-id th_... --actor-id agent:default
197
+
198
+ # Resolution helpers (M1)
199
+ tt resolve pending # NDJSON stream of forecasts awaiting resolution
200
+ tt resolve record ... # alias for `tt outcome add`
201
+ ```
202
+
203
+ Shipped (M2–M4):
204
+
205
+ ```bash
206
+ tt report calibration # M2: Brier/log/ECE/sharpness panel + integrity diagnostics
207
+ tt report calibration_integrity # M2: 6 anti-goodhart hygiene diagnostics
208
+ tt report source_quality # M2: 5 provenance hygiene diagnostics
209
+ tt report mistakes / strengths # M2: tag-aggregated patterns
210
+ tt report pnl / watchlist # M2: position roll-up + stale-watch list
211
+ tt report unscored_forecasts # M2: time-passed unscored detection
212
+ tt report decision_velocity # M2: daily/weekly decision bucketing
213
+ tt report playbook_adherence # M4: per-version followed/overridden counts
214
+ tt report coach # M2-M4: synthesized signal packet (no LLM)
215
+ tt memory retain / reflect / link # M3: typed memory graph with bi-temporal validity
216
+ tt memory recall --query "..." # M3: BM25+temporal+graph recall (RRF combined)
217
+ tt strategy create / list / show / update # M3: first-class strategies
218
+ tt playbook create / propose_version / adherence # M4: versioned playbooks
219
+ tt decision record_adherence # M4: normalized adherence rows
220
+ tt reflection prompt_for_outcome # M3: deterministic prompt packet
221
+ tt journal backup / restore # MVP-hardening: SHA-256-verified roundtrip
222
+ tt journal config_set # MVP-hardening: persisted config keys
223
+ tt journal fixture_seed --target=mvp-eval # Deterministic eval-harness dataset
224
+ ```
225
+
226
+ Still planned (P1+):
227
+
228
+ ```bash
229
+ tt review bundle ... # P1 (contract is M1-locked; impl in P1)
230
+ tt import validate / import commit # P1 (contract is M1-locked; impl in P1)
231
+ tt config set embeddings.provider local # P1: sqlite-vec + bge-small (bead trade-trace-a4p)
232
+ tt model import / model warm # P1: air-gap embedding model staging (bead a4p)
233
+ tt memory reindex --confirm # P1: re-embed on provider change (bead a4p)
234
+ ```
235
+
236
+ ## License
237
+
238
+ MIT. See [`LICENSE`](./LICENSE).
@@ -0,0 +1,220 @@
1
+ # Trade Trace
2
+
3
+ **A local, open-source, AI-only journal, memory, and calibration substrate for LLM trading agents.**
4
+
5
+ Trade Trace records trading decisions an LLM agent makes and helps the agent improve through a closed learning loop: journal a decision, resolve the outcome, score calibration, review deterministic reports, write reflections, update a versioned playbook, and recall that learning next time. It runs locally, exposes both an MCP server and a CLI with JSON-first contracts, and never executes trades.
6
+
7
+ ## What this is
8
+
9
+ - A **decision journal** with instruments, snapshots, theses, forecasts, outcomes, and process tags.
10
+ - A **trading-native memory layer** modeled on Retain / Recall / Reflect, with outcome-linked and calibration-aware recall.
11
+ - A **binary MVP calibration grader** that scores supported binary forecasts with Brier score when outcomes resolve.
12
+ - A **playbook loop** that versions rules, records manual/advisory overrides, and keeps provenance from reflections.
13
+ - **Strategies** that group decisions, theses, and reviews under a named edge thesis (e.g., `earnings-momentum`) so reports, recall, and reflection can be scoped to one logical grain without depending on free-form tags.
14
+ - An **MCP server** and **CLI** whose schemas and semantics are equivalent after transport normalization.
15
+
16
+ ## What this is not
17
+
18
+ - Not a trade executor. No order signing, wallet handling, broker credentials, seed phrases, or trade routing.
19
+ - Not a human dashboard. There is no product web UI; P2 may add optional static/read-only inspection exports.
20
+ - Not a generic agent memory framework. The schema is trading-shaped.
21
+ - Not a backtesting engine, tax accountant, social platform, or source of financial advice.
22
+
23
+ For the full vision, see [`VISION.md`](./VISION.md). For the working PRD, see [`PRD.md`](./PRD.md).
24
+
25
+ ## Status
26
+
27
+ **M0 / M1 / M2 / M3 / M4 shipped.** All four milestones cleared their
28
+ implementation, test-QC, docs-QC, and gate beads. Package skeleton +
29
+ storage + full manual write surface, event log + outbox + idempotency,
30
+ deterministic reports + integrity / source-quality diagnostics +
31
+ sample-size warnings, memory graph (retain/reflect/link/recall) with
32
+ bi-temporal validity + RRF over BM25 + temporal + graph, first-class
33
+ strategies, playbook versioning + normalized adherence + override-outcome
34
+ tracking, deterministic reflection-prompt packet, secret-pattern write
35
+ guard + file-permission + no-telemetry audit, journal backup/restore
36
+ with SHA-256 manifest, deterministic-replay clock injection + fixture
37
+ seed. The P1+ work that remains (embeddings opt-in, review.bundle / import
38
+ implementations, web/sync features) is explicitly scoped out of MVP and
39
+ tracked under beads `trade-trace-a4p` and the P1 design docs.
40
+
41
+ What works today:
42
+
43
+ - `pip install -e .` then `tt journal init` creates `$TRADE_TRACE_HOME/trade-trace.sqlite` with WAL, 5s busy_timeout, 0600 permissions, and the current schema head.
44
+ - The full manual ledger write surface: `venue.add`, `instrument.add`, `snapshot.add`, `thesis.add`, `forecast.add` (binary invariants enforced as `INVARIANT_VIOLATION`), `forecast.supersede`, `decision.add` (13-type required-field matrix enforced), `outcome.add` / `resolve.record` alias, `resolve.pending`, `source.add`, `source.attach_to_{thesis,decision,forecast}`. `source.attach_to_memory_node` returns `UNSUPPORTED_CAPABILITY` until M3.
45
+ - Decision → outcome → auto-scoring loop: an `outcome.add` with `status="resolved_final"` automatically scores every pending binary forecast against the resolved label using the single-probability Brier form per [`docs/architecture/scoring.md`](./docs/architecture/scoring.md) §3.
46
+ - Idempotent retries: every retryable write requires `idempotency_key` (per PRD §2); pure replays return the original event row with `meta.idempotent_replay=true`; semantically-different payloads return `IDEMPOTENCY_CONFLICT` with a structural diff (no raw bodies leaked).
47
+ - Append-only invariants enforced at the SQLite layer via BEFORE UPDATE/DELETE triggers on every M1 source/event table; the projection (`positions`) and the outbox state column are the only exceptions.
48
+ - `import.validate` and `import.commit` registered as contract stubs (P1 implementation pending); their schemas + the `import_ready_writers` list are introspectable today.
49
+ - `review.bundle` registered as a contract stub (P1 implementation pending); the input/output Pydantic schemas including `bundle_hash` are introspectable today.
50
+ - CLI emits NDJSON for list tools (`tt resolve pending`) with one envelope per record plus a summary line per [`docs/architecture/contracts.md`](./docs/architecture/contracts.md) §1.2; exit code mapping: `VALIDATION_ERROR`→2, `INVARIANT_VIOLATION`→3, other errors→1.
51
+ - A registration-time + startup CLI-name-collision check ensures two MCP tool names can never map to the same `tt` invocation; the runtime check emits a `STORAGE_ERROR` envelope rather than a Python traceback.
52
+ - UTC timestamps validated at the boundary: naive timestamps rejected, non-UTC offsets converted, sub-millisecond digits truncated.
53
+ - Outbound network is unconditionally off by default: `tests/security/test_no_network_default.py` monkeypatches `socket.connect`/`getaddrinfo` to refuse any outbound attempt and exercises the full ledger flow without a single call escaping.
54
+ - Credential-shaped args (api_key, wallet_seed, private_key, mnemonic, broker_token, etc.) are silently ignored by every write tool and never persist in any column or `metadata_json` blob; verified by `tests/security/test_no_credentials.py`.
55
+
56
+ Design artifacts:
57
+
58
+ - [`VISION.md`](./VISION.md) — north star
59
+ - [`PRD.md`](./PRD.md) — working PRD and MVP scope
60
+ - [`docs/architecture/memory-layer.md`](./docs/architecture/memory-layer.md) — memory layer spec (node taxonomy, retrieval, bi-temporal validity, embeddings posture)
61
+ - [`docs/architecture/scoring.md`](./docs/architecture/scoring.md) — forecast scoring (Brier, log score, ECE, sharpness, reliability bins, lifecycle, `failure_reason` enum)
62
+ - [`docs/architecture/persistence.md`](./docs/architecture/persistence.md) — events, outbox, idempotency (incl. §5.2.1 per-event-type structural-field registry)
63
+ - [`docs/architecture/contracts.md`](./docs/architecture/contracts.md) — CLI/MCP envelope and error codes
64
+ - [`docs/architecture/operability.md`](./docs/architecture/operability.md) — timezone, multi-process, migrations, logging, blob caps, JSONL on-disk format
65
+ - [`docs/architecture/reports.md`](./docs/architecture/reports.md) — `ReportFilter` / `ReportResult` / drill-down / `review.bundle`
66
+ - [`docs/architecture/imports.md`](./docs/architecture/imports.md) — JSONL/CSV local-import contract
67
+ - [`docs/architecture/risk-units.md`](./docs/architecture/risk-units.md) — P1 risk-unit / R-multiple analytics design
68
+ - [`docs/architecture/opportunity-analysis.md`](./docs/architecture/opportunity-analysis.md) — P1 path-dependent process diagnostics
69
+ - [`docs/architecture/dogfood-protocol.md`](./docs/architecture/dogfood-protocol.md) — MVP loop-usefulness protocol and provenance policies
70
+
71
+ ## Install
72
+
73
+ Today (development):
74
+
75
+ ```bash
76
+ pip install -e .
77
+ tt journal init
78
+ ```
79
+
80
+ The published package (`pip install trade-trace`) ships once the MVP M1–M4
81
+ write surface lands. Requirements today: Python 3.11+, SQLite with FTS5.
82
+ The base wheel will ship `sqlite-vec` and `sentence-transformers` as runtime
83
+ dependencies once M3 lands.
84
+
85
+ **Vectors are off by default in MVP**: a fresh `journal.init` makes zero
86
+ outbound network calls (verified by `tests/security/test_no_network_default.py`).
87
+ MVP recall runs with FTS5 + graph + temporal retrieval. Opt in to semantic
88
+ recall via `tt config set embeddings.provider local` (one-time model-weight
89
+ download, ~130 MB; lands in M3) or `tt model import <path>` for air-gapped
90
+ installs. See [`docs/architecture/memory-layer.md`](./docs/architecture/memory-layer.md)
91
+ §8.
92
+
93
+ Trade Trace never fetches trading data, broker data, market prices, order books, or outcomes. The agent calling it supplies all market data through the structured ingestion APIs. The single opt-in outbound path (embedding model download) carries no trading data; the optional API-embeddings path is separately opt-in and warned about at configure time. See [`PRD.md`](./PRD.md) §2.4.1.
94
+
95
+ ## MVP vertical slice
96
+
97
+ The MVP proves a complete learning-loop slice with narrow breadth:
98
+
99
+ 1. `journal.init`
100
+ 2. manual `instrument.add` / `snapshot.add` / `thesis.add` / binary `forecast.add` / `decision.add` — with optional `strategy_id` linkage to a named strategy
101
+ 3. optional `strategy.create` to group decisions/theses/reviews under a named edge thesis (M3; nullable FK column is reserved in M1)
102
+ 4. `outcome.add`
103
+ 5. binary Brier scoring
104
+ 6. deterministic reports and `report.coach` — all accept an optional `strategy_id` filter
105
+ 7. agent-written `memory.reflect`, including reflections targeted at a strategy
106
+ 8. `playbook.propose_version` with advisory/manual override tracking
107
+ 9. `memory.recall` during the next thesis, optionally scoped to a strategy
108
+
109
+ Deferred or optional after the manual loop: JSONL/CSV import implementations (the write schemas are import-ready in MVP), `sqlite-vec` semantic recall, multi-class/scalar scoring, trading-native edge/market reports (forecast-vs-market, calibration-by-liquidity-bucket), `report.compare`, `report.strategy_performance`, `report.risk` (see [`docs/architecture/risk-units.md`](./docs/architecture/risk-units.md)), `report.opportunity` (see [`docs/architecture/opportunity-analysis.md`](./docs/architecture/opportunity-analysis.md)), `review.bundle` implementation, exact ForecastBench compatibility, sync, HTTP/SSE, websockets, and a web viewer.
110
+
111
+ ## Quickstart for an agent (MCP, planned)
112
+
113
+ ```jsonc
114
+ {"tool": "journal.init"}
115
+
116
+ {"tool": "instrument.add", "args": {
117
+ "venue": "manual",
118
+ "asset_class": "prediction_market",
119
+ "title": "Will X happen by 2026-06-30?",
120
+ "currency_or_collateral": "USDC",
121
+ "actor_id": "agent:default"
122
+ }}
123
+
124
+ {"tool": "strategy.create", "args": {"name": "Thin-liquidity prediction markets", "slug": "thin-liquidity-prediction-markets", "hypothesis": "Markets with < $5K ADV near resolution are systematically mispriced; favor skips when spread > expected edge.", "actor_id": "agent:default"}}
125
+
126
+ {"tool": "snapshot.add", "args": {"instrument_id": "...", "price": 0.37, "bid": 0.36, "ask": 0.39, "actor_id": "agent:default"}}
127
+ {"tool": "thesis.add", "args": {"instrument_id": "...", "side": "yes", "body": "...", "falsification_criteria": "...", "strategy_id": "...", "actor_id": "agent:default"}}
128
+ {"tool": "forecast.add", "args": {"thesis_id": "...", "kind": "binary", "outcomes": [{"label": "YES", "probability": 0.48}, {"label": "NO", "probability": 0.52}], "actor_id": "agent:default"}}
129
+ {"tool": "decision.add", "args": {"instrument_id": "...", "thesis_id": "...", "type": "skip", "reason": "Estimated edge < spread + resolution risk", "strategy_id": "...", "tags": ["liquidity-ignored", "good-skip"], "actor_id": "agent:default"}}
130
+
131
+ {"tool": "outcome.add", "args": {"instrument_id": "...", "outcome_label": "NO", "outcome_value": 0.0, "status": "resolved_final", "resolved_at": "2026-06-30T00:00:00Z", "actor_id": "agent:default"}}
132
+
133
+ {"tool": "report.coach", "args": {"horizon_days": 30, "strategy_id": "..."}}
134
+
135
+ {"tool": "memory.reflect", "args": {
136
+ "target": {"kind": "decision", "id": "..."},
137
+ "insight": "Skip was correct here; spread compression never materialized.",
138
+ "strength_tags": ["good-skip", "good-liquidity-discipline"],
139
+ "actor_id": "agent:default"
140
+ }}
141
+
142
+ {"tool": "memory.recall", "args": {"context": {"kind": "strategy", "id": "..."}, "node_types": ["observation", "reflection", "playbook_rule"], "k": 10}}
143
+ ```
144
+
145
+ ## CLI dogfood surface
146
+
147
+ The CLI mirrors the MCP tool catalog. Stdout is JSON only by default;
148
+ `--human` may add prose to stderr without changing stdout semantics.
149
+
150
+ Working today (M0 + M1):
151
+
152
+ ```bash
153
+ # Foundation
154
+ tt journal init # idempotent SQLite bootstrap
155
+ tt journal status # version + capability report
156
+ tt journal schema --tool Decision # Pydantic JSON schema for a model
157
+
158
+ # Manual ledger write path (M1)
159
+ tt venue add --name "Polymarket" --kind prediction_market --actor-id agent:default
160
+ tt instrument add --venue-id ven_... --asset-class prediction_market \
161
+ --title "Will X happen by 2026-06-30?" --currency-or-collateral USDC \
162
+ --actor-id agent:default
163
+ tt snapshot add --instrument-id ins_... --captured-at 2026-05-18T14:00:00Z \
164
+ --price 0.37 --bid 0.36 --ask 0.39 --actor-id agent:default
165
+ tt thesis add --instrument-id ins_... --side yes --body "..." --actor-id agent:default
166
+ tt forecast add --thesis-id th_... --kind binary \
167
+ --outcomes-json '[{"outcome_label":"YES","probability":0.48},{"outcome_label":"NO","probability":0.52}]' \
168
+ --resolution-at 2026-06-30T00:00:00Z --actor-id agent:default
169
+ tt decision add --instrument-id ins_... --type skip \
170
+ --reason "Estimated edge < spread + resolution risk" --actor-id agent:default
171
+ tt outcome add --instrument-id ins_... --resolved-at 2026-06-30T00:00:00Z \
172
+ --outcome-label NO --status resolved_final --actor-id agent:default
173
+ # (auto-scoring fires; forecast_scores row appears)
174
+
175
+ # Source / evidence (M1)
176
+ tt source add --kind research_doc --title "Liquidity profile" --stance supports \
177
+ --actor-id agent:default
178
+ tt source attach_to_thesis --source-id src_... --target-id th_... --actor-id agent:default
179
+
180
+ # Resolution helpers (M1)
181
+ tt resolve pending # NDJSON stream of forecasts awaiting resolution
182
+ tt resolve record ... # alias for `tt outcome add`
183
+ ```
184
+
185
+ Shipped (M2–M4):
186
+
187
+ ```bash
188
+ tt report calibration # M2: Brier/log/ECE/sharpness panel + integrity diagnostics
189
+ tt report calibration_integrity # M2: 6 anti-goodhart hygiene diagnostics
190
+ tt report source_quality # M2: 5 provenance hygiene diagnostics
191
+ tt report mistakes / strengths # M2: tag-aggregated patterns
192
+ tt report pnl / watchlist # M2: position roll-up + stale-watch list
193
+ tt report unscored_forecasts # M2: time-passed unscored detection
194
+ tt report decision_velocity # M2: daily/weekly decision bucketing
195
+ tt report playbook_adherence # M4: per-version followed/overridden counts
196
+ tt report coach # M2-M4: synthesized signal packet (no LLM)
197
+ tt memory retain / reflect / link # M3: typed memory graph with bi-temporal validity
198
+ tt memory recall --query "..." # M3: BM25+temporal+graph recall (RRF combined)
199
+ tt strategy create / list / show / update # M3: first-class strategies
200
+ tt playbook create / propose_version / adherence # M4: versioned playbooks
201
+ tt decision record_adherence # M4: normalized adherence rows
202
+ tt reflection prompt_for_outcome # M3: deterministic prompt packet
203
+ tt journal backup / restore # MVP-hardening: SHA-256-verified roundtrip
204
+ tt journal config_set # MVP-hardening: persisted config keys
205
+ tt journal fixture_seed --target=mvp-eval # Deterministic eval-harness dataset
206
+ ```
207
+
208
+ Still planned (P1+):
209
+
210
+ ```bash
211
+ tt review bundle ... # P1 (contract is M1-locked; impl in P1)
212
+ tt import validate / import commit # P1 (contract is M1-locked; impl in P1)
213
+ tt config set embeddings.provider local # P1: sqlite-vec + bge-small (bead trade-trace-a4p)
214
+ tt model import / model warm # P1: air-gap embedding model staging (bead a4p)
215
+ tt memory reindex --confirm # P1: re-embed on provider change (bead a4p)
216
+ ```
217
+
218
+ ## License
219
+
220
+ MIT. See [`LICENSE`](./LICENSE).
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "trade-trace"
7
+ version = "0.0.1rc2"
8
+ description = "Local, open-source, AI-only journal, memory, and calibration substrate for LLM trading agents."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.11"
12
+ authors = [{ name = "Trade Trace contributors" }]
13
+ dependencies = [
14
+ "pydantic>=2.7,<3",
15
+ ]
16
+
17
+ [project.optional-dependencies]
18
+ mcp = ["mcp>=1.0"]
19
+ dev = [
20
+ "pytest>=8",
21
+ "ruff>=0.5",
22
+ "mypy>=1.10",
23
+ ]
24
+
25
+ [project.scripts]
26
+ tt = "trade_trace.cli:main"
27
+ trade-trace = "trade_trace.cli:main"
28
+
29
+ [tool.setuptools.packages.find]
30
+ where = ["src"]
31
+
32
+ [tool.ruff]
33
+ line-length = 100
34
+ target-version = "py311"
35
+
36
+ [tool.ruff.lint]
37
+ select = ["E", "F", "I", "B", "UP"]
38
+ ignore = ["E501"]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
42
+ addopts = "-ra"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """Trade Trace package — local AI-only journal, memory, and calibration substrate."""
2
+
3
+ from trade_trace.version import __version__
4
+
5
+ __all__ = ["__version__"]