Adversarial quality loop for trading decisions
Project description
Crucible — Player-Coach
An adversarial quality loop for LLM-based trading decisions.
▶ Live dashboard · ▶ Watch the demo · PyPI
A PlayerAgent proposes trading actions; a CoachAgent evaluates every proposal mechanically against a formal constraint schema and rejects with a specific critique if any constraint is violated. The Player revises and resubmits for up to three rounds. The result is a structured artifact — every proposal, rejection, revision, and approval recorded, validated, and queryable.
Installation
# Core infrastructure
pip install player-coach-core
# With LLM agents
pip install player-coach-core[llm]
# With Streamlit dashboard
pip install player-coach-core[dashboard]
Requires ANTHROPIC_API_KEY for LLM agents.
Dashboard
A five-page Streamlit app for running and reviewing player-coach exchanges.
Live demo: https://crucible-player-coach.streamlit.app
streamlit run dashboard/app.py
Trade Review — Run a live exchange. Player and Coach characters animate with streaming speech bubbles. Round cards show proposals, verdicts, violations, and critique.
Constraints — Configure the Coach's constraint schema. Load presets, adjust sliders, export JSON, or push directly to the Trade Review page.
History — Browse past exchanges from SQLite. Filter by outcome. Select any row to inspect rounds and replay with animation.
Settings — BYOK API key entry and validation. Key lives in session memory only, never stored.
Backtest — Compare two constraint presets over historical data side by side. Approval rate, average rounds, days aborted, total return, and max drawdown with winner highlighted per metric.
API key and database
API key: The dashboard uses a bring-your-own-key model. Enter your Anthropic API key in the Settings page. The key is stored in session memory only — it is never written to disk, logged, or shared between users. Each browser session is fully isolated.
Database: All exchanges are written to a shared SQLite database on the Streamlit Cloud instance. The History page shows exchanges from all users of the live demo. For private use, run the dashboard locally:
git clone https://github.com/MaverickHQ/crucible-player-coach
pip install player-coach-core[dashboard]
streamlit run dashboard/app.py
Constraint schema
{
"max_position_pct": 0.15,
"max_single_trade_pct": 0.05,
"max_leverage": 1.5,
"max_drawdown_pct": 0.10,
"max_daily_loss_pct": 0.02,
"consistency_rule_pct": 0.50,
"trading_cutoff_time": "16:20",
"allowed_symbols": ["AMZN", "MSFT", "TSLA", "BTC-USD"],
"max_open_positions": 3,
"min_risk_reward": 1.5,
"max_rounds": 3,
"abort_on_violations": ["max_leverage", "max_drawdown_pct"]
}
Five presets in examples/constraints/:
conservative, moderate, aggressive,
strict, futures_compatible.
Running locally
from player_coach.agents.player import PlayerAgent
from player_coach.agents.coach import CoachAgent
from player_coach.artifacts.writer import ArtifactWriter
from player_coach.constraints.schema import ConstraintSchema
from player_coach.loop.coach_loop import CoachLoop
import json
from pathlib import Path
constraints = ConstraintSchema.from_dict(
json.loads(Path("examples/constraints/moderate.json").read_text())
)
loop = CoachLoop(
player=PlayerAgent(),
coach=CoachAgent(),
artifact_writer=ArtifactWriter("artifacts"),
)
artifact = loop.run(
world_state={
"symbol": "AMZN", "price": 185.0,
"sma5": 183.0, "sma10": 180.0,
"volume": 45_000_000, "position": "flat",
"volatility_regime": "medium", "session": "NY_open",
},
constraints=constraints,
)
print(f"Outcome: {artifact['outcome']}")
print(f"Rounds: {artifact['rounds_taken']}")
Essays
Each essay is paired with a working implementation.
| # | Title | Link |
|---|---|---|
| 8 | The Adversarial Quality Loop | Read → |
| 9 | Building the Player-Coach Loop | Read → |
| 10 | Closing the Evidence Loop | Coming soon |
| 11 | The Quality of Reasoning | Coming soon |
Part of the Executable World Models series on harveygill.substack.com.
Demo
Architecture
| Component | Role |
|---|---|
PlayerAgent |
Proposes 1–3 actions given world state. Claude Haiku, max_tokens=1024. |
CoachAgent |
Evaluates proposals against constraint schema. max_tokens=1024. |
CoachLoop |
Orchestrates exchange. Up to 3 rounds. Writes artifact to disk and SQLite. |
circuit_breakers |
MLL, daily loss limit, consistency rule, trading cutoff — pure functions. |
ConstraintDeriver |
Derives constraint schema from ewm-core evidence policy. |
BacktestRunner |
Replays CoachLoop over historical trading days via yfinance. |
DatabaseStore |
SQLite persistence for exchanges, rounds, strategies, portfolio snapshots. |
Circuit breakers
Four hard stops checked before every round, in priority order:
- MLL breached — peak drawdown exceeded, account terminated
- Daily loss limit — today's loss too large, skip today
- Consistency rule — today's gain exceeds fraction of cumulative, skip today
- Trading cutoff — market hours ended, skip today
Related
| Repo | What |
|---|---|
| crucible-ewm | Observable agent trajectories, evidence policy, ewm-core |
| beyond-tokens | Constrained LLM planning on AWS Bedrock |
Project status
v1.1.0 — complete. Backend, dashboard, tests, and PyPI package all shipped.
Backlog: AWS AgentCore deployment — PlayerAgent and CoachAgent as separate Lambda functions, Step Functions orchestration, artifacts to S3.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file player_coach_core-2.0.0-py3-none-any.whl.
File metadata
- Download URL: player_coach_core-2.0.0-py3-none-any.whl
- Upload date:
- Size: 66.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a88f650c474dd5e00cfb014896c1f59c6543162c4fca643d64dd867751d7bb34
|
|
| MD5 |
909cea3e8b8a938d0ae69dfd5e5bbcf4
|
|
| BLAKE2b-256 |
0a06b70f4385f0dc83d064876743258c6d81393a5daea2ef94faff6b66f506e9
|