agent-trading-guardrails
The brakes for autonomous trading agents. A read-only, dependency-free pre-trade safety gate + audit ledger + kill switch you drop in front of any bot or LLM agent that can place real orders.
Everyone selling into the "AI agent that trades" space sells alpha — strategies that decay. This sells the opposite: the thing that stops your agent from blowing up the account. A safety layer's credibility compounds with every incident it prevents, instead of decaying like an edge. It is the picks-and-shovels play on the whole autonomous-trading gold rush.
It decides; it never trades.
check()is pure and side-effect-free — it returns a verdict and a risk-sized dollar stake. Your code still places the order.
This engine is extracted from a real-money trading system's pre-trade rule checker — the same gate that runs in front of live prediction-market and brokerage execution.
Why it exists
An LLM wired to Robinhood / Kalshi / Polymarket / Alpaca will, eventually:
- fat-finger an order size,
- revenge-trade straight into a drawdown,
- chase a longshot at 3¢,
- or silently die mid-session with an open position and no stop.
These are not strategy problems; they are safety problems, and they are the same across every venue. This package encodes the boring, battle-tested controls that catch them — as configuration, not code you have to write.
Install
pip install -e . # from this directory
python -m guardrails.selftest
Stdlib-only. No numpy, no pandas, nothing to audit or pin.
Quick start
from guardrails import Guardrails, GuardrailConfig, AuditLedger, KillSwitch
gate = Guardrails(GuardrailConfig.conservative())
ledger = AuditLedger("audit/trades.jsonl")
halt = KillSwitch("audit/HALT")
verdict = gate.check({
"side": "YES", # YES = "this resolves true / goes up"
"market_price": 0.52, # the ask, in (0, 1)
"model_prob": 0.66, # your model's probability of YES
"balance": 1000.0,
"peak_balance": 1200.0, # enables the drawdown breaker
})
ledger.record_decision(verdict, venue="kalshi", symbol="KXFED-26JUL", side="YES")
if not halt.is_engaged() and verdict.passed:
place_order(dollars=verdict.size) # <- your code
else:
print(verdict.blocking_rules, verdict.reasons)
The rules
Every threshold is a field on GuardrailConfig — set your own without touching
engine code. Stable rule codes (R-0xx) are what your ledger and dashboards key
on.
| Code | Guardrail | Blocks? |
|---|---|---|
| R-001 | Drawdown-aware fractional-Kelly position sizing | sizes (never negative) |
| R-006 | Minimum daily volume floor (skip thin markets) | ✅ when volume supplied |
| R-008 | Capital guardrail — open cost + new size ≤ cap% of balance | ✅ |
| R-009 | Portfolio guardrail — remaining balance after trade | advisory |
| R-014 | Price floor / ceiling — no YES < 0.35, no NO > 0.65 (anti-longshot) | ✅ |
| R-017 | Extreme-divergence cap — edge > 50pt ⇒ size capped (possible model error) | caps + advisory |
| R-025 | Consecutive-losing-day circuit breaker — tightens the capital cap | ✅ |
| R-039 | Absolute-drawdown breaker — freeze ≥ 40%, halt ≥ 60% | ✅ |
| R-040 | Daily-loss budget — block once today's loss exceeds % of day-start | ✅ |
| R-EDGE | Non-positive edge — nothing to trade | ✅ |
edge_pt = (win_prob − market_price) × 100, where win_prob is model_prob
for a YES buy and 1 − model_prob for a NO buy.
Trade dict — keys
Required: side ("YES"/"NO"), market_price (0–1), model_prob (0–1),
balance ($).
Optional (each enables a rule; absent ⇒ that rule is skipped, logged as an
advisory): edge_pt, open_position_cost, bankroll, market_volume,
peak_balance, recent_daily_pnl (most-recent-first), today_pnl_dollars,
starting_balance_dollars, strategy. Unknown keys are ignored, so you can pass
your own trade objects through untouched.
Works on any venue
- Prediction markets (Kalshi, Polymarket) — native;
market_priceis the contract price. Seeexamples/kalshi_example.py. - Brokerage (Robinhood, Alpaca) — map a directional thesis onto a win
probability and a break-even "price" from your reward-to-risk;
verdict.sizeis dollars-to-risk, convert to shares with your stop distance. Disable the R-014 anti-longshot floor for this mapping (it's a prediction-market rule) — seeexamples/robinhood_example.py.
The audit ledger
AuditLedger writes an append-only JSONL row for every decision and every fill —
the compliance artifact that makes an autonomous strategy defensible. Writes
never raise: a logging failure returns False instead of blocking your order
path.
The kill switch
KillSwitch is a file-based, out-of-band halt. Any human or monitor can create
the halt file and the next is_engaged() refuses new entries — no process, no
network, no coordination with the agent. Keep your exit path unconditional:
halt entries, never exits.
Testing
python -m guardrails.selftest # zero-dependency smoke path
python -m pytest tests/ # full unittest suite
License
MIT. Not financial advice — a risk-control tool, not a guarantee against loss.
Release files for agent-trading-guardrails 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_trading_guardrails-0.1.1.tar.gz | 17.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_trading_guardrails-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.6 kB
Release files / agent_trading_guardrails-0.1.1.tar.gz
| Download URL | agent_trading_guardrails-0.1.1.tar.gz |
|---|---|
| Size | 17.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
318898901d10551ba295d3a2b286bf0bdd17b5598f830311b39d12a69a0d509c
|
|
BLAKE2b-256 checksum How to use checksums |
9d515c698d5069e2959116a05ca2b78885303dcc96610ae3b41b391989f16fba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logRelease files / agent_trading_guardrails-0.1.1-py3-none-any.whl
| Download URL | agent_trading_guardrails-0.1.1-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
282fdeb5ad310ea7329f4aaf65adb293c43841abbb5386382bf43ad37a4100b9
|
|
BLAKE2b-256 checksum How to use checksums |
cf33166c48cf60183bb39583e37a026ace9f9c222fb1401681496fefc803f711
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency log