trench-core 0.8.0__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.
- trench_core-0.8.0/LICENSE +21 -0
- trench_core-0.8.0/PKG-INFO +203 -0
- trench_core-0.8.0/README.md +161 -0
- trench_core-0.8.0/pyproject.toml +95 -0
- trench_core-0.8.0/setup.cfg +4 -0
- trench_core-0.8.0/setup.py +12 -0
- trench_core-0.8.0/tests/test_calibration.py +356 -0
- trench_core-0.8.0/tests/test_cycle_outcomes.py +166 -0
- trench_core-0.8.0/tests/test_markets.py +269 -0
- trench_core-0.8.0/tests/test_ontology.py +364 -0
- trench_core-0.8.0/tests/test_registry.py +354 -0
- trench_core-0.8.0/tests/test_replay.py +259 -0
- trench_core-0.8.0/tests/test_smoke.py +47 -0
- trench_core-0.8.0/tests/test_sources_rss.py +203 -0
- trench_core-0.8.0/tests/test_sources_seismic.py +174 -0
- trench_core-0.8.0/tests/test_tournament.py +264 -0
- trench_core-0.8.0/trench_core/__init__.py +20 -0
- trench_core-0.8.0/trench_core/calibration/__init__.py +99 -0
- trench_core-0.8.0/trench_core/calibration/brier.py +239 -0
- trench_core-0.8.0/trench_core/calibration/cycles.py +66 -0
- trench_core-0.8.0/trench_core/calibration/report.py +122 -0
- trench_core-0.8.0/trench_core/calibration/trades.py +258 -0
- trench_core-0.8.0/trench_core/cycle_outcomes/__init__.py +39 -0
- trench_core-0.8.0/trench_core/cycle_outcomes/logger.py +105 -0
- trench_core-0.8.0/trench_core/cycle_outcomes/parser.py +127 -0
- trench_core-0.8.0/trench_core/markets/__init__.py +31 -0
- trench_core-0.8.0/trench_core/markets/kalshi.py +206 -0
- trench_core-0.8.0/trench_core/markets/manifold.py +200 -0
- trench_core-0.8.0/trench_core/ontology/__init__.py +60 -0
- trench_core-0.8.0/trench_core/ontology/_extract.py +136 -0
- trench_core-0.8.0/trench_core/ontology/_schema.py +115 -0
- trench_core-0.8.0/trench_core/ontology/store.py +723 -0
- trench_core-0.8.0/trench_core/registry/__init__.py +61 -0
- trench_core-0.8.0/trench_core/registry/_canonical.py +29 -0
- trench_core-0.8.0/trench_core/registry/verify.py +135 -0
- trench_core-0.8.0/trench_core/registry/writer.py +253 -0
- trench_core-0.8.0/trench_core/replay/__init__.py +70 -0
- trench_core-0.8.0/trench_core/replay/bundles.py +192 -0
- trench_core-0.8.0/trench_core/replay/diff.py +74 -0
- trench_core-0.8.0/trench_core/replay/replay.py +145 -0
- trench_core-0.8.0/trench_core/sources/__init__.py +29 -0
- trench_core-0.8.0/trench_core/sources/rss.py +239 -0
- trench_core-0.8.0/trench_core/sources/seismic.py +183 -0
- trench_core-0.8.0/trench_core/tournament/__init__.py +41 -0
- trench_core-0.8.0/trench_core/tournament/leaderboard.py +179 -0
- trench_core-0.8.0/trench_core/tournament/registry.py +113 -0
- trench_core-0.8.0/trench_core.egg-info/PKG-INFO +203 -0
- trench_core-0.8.0/trench_core.egg-info/SOURCES.txt +49 -0
- trench_core-0.8.0/trench_core.egg-info/dependency_links.txt +1 -0
- trench_core-0.8.0/trench_core.egg-info/requires.txt +22 -0
- trench_core-0.8.0/trench_core.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TrenchSignals
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trench-core
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: Plumbing for calibrated AI trading agents — capture, score, instrument, anchor.
|
|
5
|
+
Author-email: TrenchSignals <hello@trenchsignals.io>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://trenchsignals.io
|
|
8
|
+
Project-URL: Documentation, https://trenchsignals.io/api
|
|
9
|
+
Project-URL: Repository, https://github.com/trenchsignals/trench-core
|
|
10
|
+
Project-URL: Changelog, https://github.com/trenchsignals/trench-core/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: llm-agents,calibration,brier-score,prediction-markets,trading,ai,anthropic,claude
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Provides-Extra: calibration
|
|
27
|
+
Requires-Dist: pandas>=2.0; extra == "calibration"
|
|
28
|
+
Requires-Dist: numpy>=1.24; extra == "calibration"
|
|
29
|
+
Provides-Extra: replay
|
|
30
|
+
Provides-Extra: sources
|
|
31
|
+
Requires-Dist: feedparser>=6.0; extra == "sources"
|
|
32
|
+
Provides-Extra: markets
|
|
33
|
+
Provides-Extra: ontology
|
|
34
|
+
Provides-Extra: all
|
|
35
|
+
Requires-Dist: trench-core[calibration,markets,ontology,replay,sources]; extra == "all"
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
39
|
+
Requires-Dist: pdoc>=14.0; extra == "dev"
|
|
40
|
+
Requires-Dist: ruff>=0.1; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# trench-core
|
|
44
|
+
|
|
45
|
+
> Plumbing for calibrated AI trading agents.
|
|
46
|
+
> Capture, score, instrument, anchor.
|
|
47
|
+
|
|
48
|
+
[](https://pypi.org/project/trench-core/)
|
|
49
|
+
[](https://pypi.org/project/trench-core/)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
|
|
52
|
+
`trench-core` is the open-source framework that powers
|
|
53
|
+
[TrenchSignals](https://trenchsignals.io) — an autonomous AI paper-trading
|
|
54
|
+
geopolitical conflict markets in public, with every prediction Brier-scored
|
|
55
|
+
and every loss publicly post-mortemed.
|
|
56
|
+
|
|
57
|
+
This package is the **plumbing**: capture, score, instrument, anchor. It is
|
|
58
|
+
deliberately *not* the agent itself — TrenchSignals' specific ontology,
|
|
59
|
+
prompts, brand voice, and operating record stay private.
|
|
60
|
+
|
|
61
|
+
If you want to:
|
|
62
|
+
|
|
63
|
+
- **Capture every LLM call** with full input/output for later replay through a
|
|
64
|
+
different model
|
|
65
|
+
- **Score predictions** against actual market settlements (Brier, calibration
|
|
66
|
+
curves, threshold backtests, P&L attribution)
|
|
67
|
+
- **Anchor predictions** into a public hash chain so anyone can verify them
|
|
68
|
+
without trusting your server
|
|
69
|
+
- **Instrument every loop iteration** with a single structured outcome line so
|
|
70
|
+
failure modes are observable in production
|
|
71
|
+
- **Run a multi-variant tournament** of decision policies on the same
|
|
72
|
+
intelligence pipeline
|
|
73
|
+
|
|
74
|
+
…then `trench-core` gives you the building blocks.
|
|
75
|
+
|
|
76
|
+
## Status
|
|
77
|
+
|
|
78
|
+
> **Alpha (`0.x`).** All eight modules are shipped (`0.8.0`). API may break
|
|
79
|
+
> between minor versions until `1.0.0`. Pin exactly if you depend on it.
|
|
80
|
+
|
|
81
|
+
See [the changelog](CHANGELOG.md) for what's landed.
|
|
82
|
+
|
|
83
|
+
## Install
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install trench-core # core + most modules (stdlib only)
|
|
87
|
+
pip install 'trench-core[sources]' # adds feedparser for RSS polling
|
|
88
|
+
pip install 'trench-core[all]' # everything
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Six of the eight modules need only the standard library. Only `sources`
|
|
92
|
+
(RSS polling, via `feedparser`) declares an optional runtime dependency.
|
|
93
|
+
|
|
94
|
+
## Quickstart
|
|
95
|
+
|
|
96
|
+
A minimal end-to-end loop: capture a Claude call, log its outcome,
|
|
97
|
+
register the bundle's hash on a public chain, and score the prediction
|
|
98
|
+
once the market settles. No `requests`, no Anthropic SDK — the framework
|
|
99
|
+
stays provider-agnostic; you wire your own model caller.
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from pathlib import Path
|
|
103
|
+
|
|
104
|
+
from trench_core.replay import BundleWriter, load_bundles, replay_bundle, diff_signals
|
|
105
|
+
from trench_core.cycle_outcomes import OutcomeLogger
|
|
106
|
+
from trench_core.registry import RegistryWriter, verify_chain
|
|
107
|
+
from trench_core.calibration import calibration_report
|
|
108
|
+
|
|
109
|
+
# 1. Capture: at the moment of generation
|
|
110
|
+
writer = BundleWriter(
|
|
111
|
+
path="bundles.jsonl",
|
|
112
|
+
system_prompt="You are an analyst...", # auto-hashed for grouping
|
|
113
|
+
)
|
|
114
|
+
my_prompt = "Will Iran sign a deal by June 2027?"
|
|
115
|
+
my_raw = your_llm_call(my_prompt, model="sonnet-4-6") # caller-supplied
|
|
116
|
+
my_parsed = your_parser(my_raw)
|
|
117
|
+
writer.write(prompt=my_prompt, response_raw=my_raw,
|
|
118
|
+
parsed=my_parsed, model="sonnet-4-6")
|
|
119
|
+
|
|
120
|
+
# 2. Instrument: emit one structured outcome line per loop iteration
|
|
121
|
+
outcomes = OutcomeLogger("/var/log/agent.log")
|
|
122
|
+
outcomes.emit("traded", confidence=my_parsed["confidence"], side="NO")
|
|
123
|
+
|
|
124
|
+
# 3. Pre-register: anchor today's bundles in a public hash chain
|
|
125
|
+
chain = RegistryWriter(
|
|
126
|
+
bundle_paths={"baseline": "bundles.jsonl"},
|
|
127
|
+
registry_root="registry/",
|
|
128
|
+
summary_fields=("direction", "confidence"),
|
|
129
|
+
)
|
|
130
|
+
chain.update() # appends today's record
|
|
131
|
+
verify_chain("registry/") # raises ChainBroken if anything tampered
|
|
132
|
+
|
|
133
|
+
# 4. Score: when the market settles, run a calibration report
|
|
134
|
+
trades = [...] # your closed-trade dicts
|
|
135
|
+
evals = [...] # your per-market evaluation dicts
|
|
136
|
+
report = calibration_report(trades, evaluations=evals)
|
|
137
|
+
print(report["brier"]["mean_brier"], report["trade_summary"]["roi_pct"])
|
|
138
|
+
|
|
139
|
+
# 5. Replay: re-run a captured cycle through a different model
|
|
140
|
+
bundles = load_bundles("bundles.jsonl")
|
|
141
|
+
res = replay_bundle(
|
|
142
|
+
bundle=bundles[-1],
|
|
143
|
+
model="haiku-4-5",
|
|
144
|
+
model_caller=your_llm_call,
|
|
145
|
+
parser=your_parser,
|
|
146
|
+
)
|
|
147
|
+
print(diff_signals(res.bundle.parsed, res.candidate_parsed))
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Each module is independently usable — pick the ones you need. Per-module
|
|
151
|
+
quickstarts live in their `__init__.py` docstrings (also rendered in the
|
|
152
|
+
generated API docs).
|
|
153
|
+
|
|
154
|
+
## Modules
|
|
155
|
+
|
|
156
|
+
| Module | What it does | Status |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| `trench_core.calibration` | Brier scoring, calibration curves, threshold backtests, P&L attribution | ✅ shipped (0.3.0) |
|
|
159
|
+
| `trench_core.replay` | Capture-then-replay + diff harness for LLM agents | ✅ shipped (0.4.0) |
|
|
160
|
+
| `trench_core.cycle_outcomes` | Structured "one outcome line per loop iteration" instrumentation | ✅ shipped (0.2.0) |
|
|
161
|
+
| `trench_core.registry` | Public hash-chain pre-registration of agent outputs | ✅ shipped (0.2.0) |
|
|
162
|
+
| `trench_core.ontology` | Generic typed entity graph + alias resolver, SQLite-backed | ✅ shipped (0.5.0) |
|
|
163
|
+
| `trench_core.sources` | RSS poller + USGS seismic poller (Twitter/Telegram/financial deferred) | ✅ shipped (0.6.0) |
|
|
164
|
+
| `trench_core.markets` | Public-data clients — Kalshi (read-only), Manifold (Polymarket trading deferred) | ✅ shipped (0.7.0) |
|
|
165
|
+
| `trench_core.tournament` | Multi-variant runner pattern — same intel, different policies | ✅ shipped (0.8.0) |
|
|
166
|
+
|
|
167
|
+
## What's deliberately not in scope
|
|
168
|
+
|
|
169
|
+
- ❌ A backtesting engine (use [zipline](https://zipline.ml4trading.io/) or
|
|
170
|
+
[vectorbt](https://vectorbt.dev/) for historical sim)
|
|
171
|
+
- ❌ A strategy library (no canned signals)
|
|
172
|
+
- ❌ A managed/SaaS version (you run it yourself)
|
|
173
|
+
- ❌ Brokerage integration (the framework provides data, not execution glue)
|
|
174
|
+
- ❌ A multi-provider AI abstraction layer (Anthropic-first by design; wrap
|
|
175
|
+
your own analyzer for OpenAI)
|
|
176
|
+
|
|
177
|
+
## Examples
|
|
178
|
+
|
|
179
|
+
The [`examples/`](examples/) directory has runnable demos for every
|
|
180
|
+
module. All of them run offline (network calls are mocked):
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
python examples/01_cycle_outcomes.py
|
|
184
|
+
python examples/02_registry.py
|
|
185
|
+
python examples/03_calibration.py
|
|
186
|
+
python examples/04_replay.py
|
|
187
|
+
python examples/05_ontology.py
|
|
188
|
+
python examples/06_sources.py
|
|
189
|
+
python examples/07_markets.py
|
|
190
|
+
python examples/08_tournament.py
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Contributing
|
|
194
|
+
|
|
195
|
+
The project is alpha — issues and PRs welcome, but expect API churn
|
|
196
|
+
until `1.0.0`. See [CONTRIBUTING.md](CONTRIBUTING.md) for the
|
|
197
|
+
development setup and the discipline that's kept the extraction
|
|
198
|
+
clean (audit before code, ruff + pytest pre-flight, byte-identical
|
|
199
|
+
proof for refactors).
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# trench-core
|
|
2
|
+
|
|
3
|
+
> Plumbing for calibrated AI trading agents.
|
|
4
|
+
> Capture, score, instrument, anchor.
|
|
5
|
+
|
|
6
|
+
[](https://pypi.org/project/trench-core/)
|
|
7
|
+
[](https://pypi.org/project/trench-core/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
`trench-core` is the open-source framework that powers
|
|
11
|
+
[TrenchSignals](https://trenchsignals.io) — an autonomous AI paper-trading
|
|
12
|
+
geopolitical conflict markets in public, with every prediction Brier-scored
|
|
13
|
+
and every loss publicly post-mortemed.
|
|
14
|
+
|
|
15
|
+
This package is the **plumbing**: capture, score, instrument, anchor. It is
|
|
16
|
+
deliberately *not* the agent itself — TrenchSignals' specific ontology,
|
|
17
|
+
prompts, brand voice, and operating record stay private.
|
|
18
|
+
|
|
19
|
+
If you want to:
|
|
20
|
+
|
|
21
|
+
- **Capture every LLM call** with full input/output for later replay through a
|
|
22
|
+
different model
|
|
23
|
+
- **Score predictions** against actual market settlements (Brier, calibration
|
|
24
|
+
curves, threshold backtests, P&L attribution)
|
|
25
|
+
- **Anchor predictions** into a public hash chain so anyone can verify them
|
|
26
|
+
without trusting your server
|
|
27
|
+
- **Instrument every loop iteration** with a single structured outcome line so
|
|
28
|
+
failure modes are observable in production
|
|
29
|
+
- **Run a multi-variant tournament** of decision policies on the same
|
|
30
|
+
intelligence pipeline
|
|
31
|
+
|
|
32
|
+
…then `trench-core` gives you the building blocks.
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
> **Alpha (`0.x`).** All eight modules are shipped (`0.8.0`). API may break
|
|
37
|
+
> between minor versions until `1.0.0`. Pin exactly if you depend on it.
|
|
38
|
+
|
|
39
|
+
See [the changelog](CHANGELOG.md) for what's landed.
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install trench-core # core + most modules (stdlib only)
|
|
45
|
+
pip install 'trench-core[sources]' # adds feedparser for RSS polling
|
|
46
|
+
pip install 'trench-core[all]' # everything
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Six of the eight modules need only the standard library. Only `sources`
|
|
50
|
+
(RSS polling, via `feedparser`) declares an optional runtime dependency.
|
|
51
|
+
|
|
52
|
+
## Quickstart
|
|
53
|
+
|
|
54
|
+
A minimal end-to-end loop: capture a Claude call, log its outcome,
|
|
55
|
+
register the bundle's hash on a public chain, and score the prediction
|
|
56
|
+
once the market settles. No `requests`, no Anthropic SDK — the framework
|
|
57
|
+
stays provider-agnostic; you wire your own model caller.
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from pathlib import Path
|
|
61
|
+
|
|
62
|
+
from trench_core.replay import BundleWriter, load_bundles, replay_bundle, diff_signals
|
|
63
|
+
from trench_core.cycle_outcomes import OutcomeLogger
|
|
64
|
+
from trench_core.registry import RegistryWriter, verify_chain
|
|
65
|
+
from trench_core.calibration import calibration_report
|
|
66
|
+
|
|
67
|
+
# 1. Capture: at the moment of generation
|
|
68
|
+
writer = BundleWriter(
|
|
69
|
+
path="bundles.jsonl",
|
|
70
|
+
system_prompt="You are an analyst...", # auto-hashed for grouping
|
|
71
|
+
)
|
|
72
|
+
my_prompt = "Will Iran sign a deal by June 2027?"
|
|
73
|
+
my_raw = your_llm_call(my_prompt, model="sonnet-4-6") # caller-supplied
|
|
74
|
+
my_parsed = your_parser(my_raw)
|
|
75
|
+
writer.write(prompt=my_prompt, response_raw=my_raw,
|
|
76
|
+
parsed=my_parsed, model="sonnet-4-6")
|
|
77
|
+
|
|
78
|
+
# 2. Instrument: emit one structured outcome line per loop iteration
|
|
79
|
+
outcomes = OutcomeLogger("/var/log/agent.log")
|
|
80
|
+
outcomes.emit("traded", confidence=my_parsed["confidence"], side="NO")
|
|
81
|
+
|
|
82
|
+
# 3. Pre-register: anchor today's bundles in a public hash chain
|
|
83
|
+
chain = RegistryWriter(
|
|
84
|
+
bundle_paths={"baseline": "bundles.jsonl"},
|
|
85
|
+
registry_root="registry/",
|
|
86
|
+
summary_fields=("direction", "confidence"),
|
|
87
|
+
)
|
|
88
|
+
chain.update() # appends today's record
|
|
89
|
+
verify_chain("registry/") # raises ChainBroken if anything tampered
|
|
90
|
+
|
|
91
|
+
# 4. Score: when the market settles, run a calibration report
|
|
92
|
+
trades = [...] # your closed-trade dicts
|
|
93
|
+
evals = [...] # your per-market evaluation dicts
|
|
94
|
+
report = calibration_report(trades, evaluations=evals)
|
|
95
|
+
print(report["brier"]["mean_brier"], report["trade_summary"]["roi_pct"])
|
|
96
|
+
|
|
97
|
+
# 5. Replay: re-run a captured cycle through a different model
|
|
98
|
+
bundles = load_bundles("bundles.jsonl")
|
|
99
|
+
res = replay_bundle(
|
|
100
|
+
bundle=bundles[-1],
|
|
101
|
+
model="haiku-4-5",
|
|
102
|
+
model_caller=your_llm_call,
|
|
103
|
+
parser=your_parser,
|
|
104
|
+
)
|
|
105
|
+
print(diff_signals(res.bundle.parsed, res.candidate_parsed))
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Each module is independently usable — pick the ones you need. Per-module
|
|
109
|
+
quickstarts live in their `__init__.py` docstrings (also rendered in the
|
|
110
|
+
generated API docs).
|
|
111
|
+
|
|
112
|
+
## Modules
|
|
113
|
+
|
|
114
|
+
| Module | What it does | Status |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `trench_core.calibration` | Brier scoring, calibration curves, threshold backtests, P&L attribution | ✅ shipped (0.3.0) |
|
|
117
|
+
| `trench_core.replay` | Capture-then-replay + diff harness for LLM agents | ✅ shipped (0.4.0) |
|
|
118
|
+
| `trench_core.cycle_outcomes` | Structured "one outcome line per loop iteration" instrumentation | ✅ shipped (0.2.0) |
|
|
119
|
+
| `trench_core.registry` | Public hash-chain pre-registration of agent outputs | ✅ shipped (0.2.0) |
|
|
120
|
+
| `trench_core.ontology` | Generic typed entity graph + alias resolver, SQLite-backed | ✅ shipped (0.5.0) |
|
|
121
|
+
| `trench_core.sources` | RSS poller + USGS seismic poller (Twitter/Telegram/financial deferred) | ✅ shipped (0.6.0) |
|
|
122
|
+
| `trench_core.markets` | Public-data clients — Kalshi (read-only), Manifold (Polymarket trading deferred) | ✅ shipped (0.7.0) |
|
|
123
|
+
| `trench_core.tournament` | Multi-variant runner pattern — same intel, different policies | ✅ shipped (0.8.0) |
|
|
124
|
+
|
|
125
|
+
## What's deliberately not in scope
|
|
126
|
+
|
|
127
|
+
- ❌ A backtesting engine (use [zipline](https://zipline.ml4trading.io/) or
|
|
128
|
+
[vectorbt](https://vectorbt.dev/) for historical sim)
|
|
129
|
+
- ❌ A strategy library (no canned signals)
|
|
130
|
+
- ❌ A managed/SaaS version (you run it yourself)
|
|
131
|
+
- ❌ Brokerage integration (the framework provides data, not execution glue)
|
|
132
|
+
- ❌ A multi-provider AI abstraction layer (Anthropic-first by design; wrap
|
|
133
|
+
your own analyzer for OpenAI)
|
|
134
|
+
|
|
135
|
+
## Examples
|
|
136
|
+
|
|
137
|
+
The [`examples/`](examples/) directory has runnable demos for every
|
|
138
|
+
module. All of them run offline (network calls are mocked):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
python examples/01_cycle_outcomes.py
|
|
142
|
+
python examples/02_registry.py
|
|
143
|
+
python examples/03_calibration.py
|
|
144
|
+
python examples/04_replay.py
|
|
145
|
+
python examples/05_ontology.py
|
|
146
|
+
python examples/06_sources.py
|
|
147
|
+
python examples/07_markets.py
|
|
148
|
+
python examples/08_tournament.py
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Contributing
|
|
152
|
+
|
|
153
|
+
The project is alpha — issues and PRs welcome, but expect API churn
|
|
154
|
+
until `1.0.0`. See [CONTRIBUTING.md](CONTRIBUTING.md) for the
|
|
155
|
+
development setup and the discipline that's kept the extraction
|
|
156
|
+
clean (audit before code, ruff + pytest pre-flight, byte-identical
|
|
157
|
+
proof for refactors).
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# pyproject.toml — trench-core
|
|
2
|
+
#
|
|
3
|
+
# This is the alpha (`0.1.x`) of trench-core. The API will break between minor
|
|
4
|
+
# versions until we hit `1.0.0`. Pin exactly if you depend on it in production.
|
|
5
|
+
|
|
6
|
+
[build-system]
|
|
7
|
+
requires = ["setuptools>=68", "wheel"]
|
|
8
|
+
build-backend = "setuptools.build_meta"
|
|
9
|
+
|
|
10
|
+
[project]
|
|
11
|
+
name = "trench-core"
|
|
12
|
+
version = "0.8.0"
|
|
13
|
+
description = "Plumbing for calibrated AI trading agents — capture, score, instrument, anchor."
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
license = { text = "MIT" }
|
|
16
|
+
requires-python = ">=3.10"
|
|
17
|
+
authors = [
|
|
18
|
+
{ name = "TrenchSignals", email = "hello@trenchsignals.io" },
|
|
19
|
+
]
|
|
20
|
+
keywords = [
|
|
21
|
+
"llm-agents",
|
|
22
|
+
"calibration",
|
|
23
|
+
"brier-score",
|
|
24
|
+
"prediction-markets",
|
|
25
|
+
"trading",
|
|
26
|
+
"ai",
|
|
27
|
+
"anthropic",
|
|
28
|
+
"claude",
|
|
29
|
+
]
|
|
30
|
+
classifiers = [
|
|
31
|
+
"Development Status :: 3 - Alpha",
|
|
32
|
+
"Intended Audience :: Developers",
|
|
33
|
+
"Intended Audience :: Science/Research",
|
|
34
|
+
"License :: OSI Approved :: MIT License",
|
|
35
|
+
"Operating System :: OS Independent",
|
|
36
|
+
"Programming Language :: Python :: 3",
|
|
37
|
+
"Programming Language :: Python :: 3.10",
|
|
38
|
+
"Programming Language :: Python :: 3.11",
|
|
39
|
+
"Programming Language :: Python :: 3.12",
|
|
40
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
41
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
42
|
+
]
|
|
43
|
+
# Empty by design at 0.1.0. We add deps only as modules genuinely require them
|
|
44
|
+
# during their extraction phase — see marketing/07-trench-core-spec.md
|
|
45
|
+
# (in the private TrenchSignals repo) for the staging plan.
|
|
46
|
+
dependencies = []
|
|
47
|
+
|
|
48
|
+
[project.optional-dependencies]
|
|
49
|
+
# Each extras group is a SUPERSET of what one module's consumer needs. We
|
|
50
|
+
# split them so a user who wants only the calibration utilities doesn't have
|
|
51
|
+
# to install Telethon. As modules land, their deps move from in-source TODO
|
|
52
|
+
# comments into the appropriate group here.
|
|
53
|
+
calibration = ["pandas>=2.0", "numpy>=1.24"]
|
|
54
|
+
replay = [] # provider-agnostic; users wire their own model_caller
|
|
55
|
+
sources = ["feedparser>=6.0"] # seismic poller is stdlib-only
|
|
56
|
+
markets = [] # public-data clients use stdlib urllib only
|
|
57
|
+
ontology = [] # uses stdlib sqlite3 only
|
|
58
|
+
|
|
59
|
+
# Convenience meta-extras
|
|
60
|
+
all = [
|
|
61
|
+
"trench-core[calibration,replay,sources,markets,ontology]",
|
|
62
|
+
]
|
|
63
|
+
dev = [
|
|
64
|
+
"pytest>=7.0",
|
|
65
|
+
"pytest-cov>=4.0",
|
|
66
|
+
"pdoc>=14.0",
|
|
67
|
+
"ruff>=0.1",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[project.urls]
|
|
71
|
+
Homepage = "https://trenchsignals.io"
|
|
72
|
+
Documentation = "https://trenchsignals.io/api"
|
|
73
|
+
Repository = "https://github.com/trenchsignals/trench-core"
|
|
74
|
+
Changelog = "https://github.com/trenchsignals/trench-core/blob/main/CHANGELOG.md"
|
|
75
|
+
|
|
76
|
+
[tool.setuptools.packages.find]
|
|
77
|
+
where = ["."]
|
|
78
|
+
include = ["trench_core*"]
|
|
79
|
+
exclude = ["tests*", "examples*"]
|
|
80
|
+
|
|
81
|
+
[tool.pytest.ini_options]
|
|
82
|
+
minversion = "7.0"
|
|
83
|
+
testpaths = ["tests"]
|
|
84
|
+
python_files = ["test_*.py"]
|
|
85
|
+
addopts = "-ra -q --strict-markers"
|
|
86
|
+
filterwarnings = ["error"]
|
|
87
|
+
|
|
88
|
+
[tool.ruff]
|
|
89
|
+
line-length = 100
|
|
90
|
+
target-version = "py310"
|
|
91
|
+
|
|
92
|
+
[tool.ruff.lint]
|
|
93
|
+
# Conservative defaults; we'll tighten as the codebase stabilizes
|
|
94
|
+
select = ["E", "F", "I", "B", "UP"]
|
|
95
|
+
ignore = ["E501"] # let line length be soft-enforced; long URLs in docstrings happen
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Compatibility shim — only here for older pip versions (<21.3) that don't
|
|
2
|
+
fully support PEP 660 editable installs from pyproject.toml alone.
|
|
3
|
+
|
|
4
|
+
All real configuration lives in pyproject.toml. Modern pip and PyPI consumers
|
|
5
|
+
never read this file; it exists so `pip install -e .` works on the long tail
|
|
6
|
+
of Python environments.
|
|
7
|
+
|
|
8
|
+
If you're reading this and your pip is recent (>=23.x), this file is a no-op.
|
|
9
|
+
"""
|
|
10
|
+
from setuptools import setup
|
|
11
|
+
|
|
12
|
+
setup()
|