name: "midas-core" tagline_fr: "Un moteur Brain/Hands open source pour agents IA en paper trading — la sécurité vit dans le broker, pas dans le prompt." tagline_en: "An open Brain/Hands engine for paper-trading AI agents — safety enforced by the broker, not the prompt." facts_fr: "Licence MIT, Python 3.12+, 15 codes de garde-fou du broker, desk de démo exécutable, pip install midas-core." facts_en: "MIT license, Python 3.12+, 15 broker safety-rail reason codes, a runnable demo desk, pip install midas-core."
midas-core
An open, multi-agent paper-trading fund-manager framework built on a Brain/Hands split: agents author decisions; a broker enforces the safety rails and executes them. This repo is the reusable core — the engine, the config-driven roster/allocator model, a runnable demo desk, and the deterministic Hands pipeline. Bring your own agents.
Paper-trading by default. This is a framework, not a service: it never executes against your broker keys, never pools funds, never gives per-user advice. See DISCLAIMER.md.
Why this exists
- Safety lives in the broker, not the prompt. The persona is aspirational; the broker is
enforcing. Every order is checked at fill time against a fixed set of 15 rejection/cancel
reason codes —
MAX_ORDER_NOTIONAL,MAX_ORDERS_PER_DAY,TICKER_NOT_IN_UNIVERSE,INSUFFICIENT_CASH,DAILY_DRAWDOWN_HALT, … — so a coaxed or confused agent still can't slip an oversized or out-of-universe trade through. - Reproducible by construction. Dependencies are a fully-pinned lockfile; prices and index
universes are committed to git; a trading session makes no outbound HTTP calls. Every fill is
stamped with
executed_sha, the git HEAD it executed against —git checkout <sha>re-derives the exact order and price store the broker saw. - Proven on a live desk. A 10-agent desk has run this engine every weekday since 2026-04-17, narrated publicly at midas.revah.paris. This repo is a one-way code mirror of that desk's engine — the same code, without the private data ledger.
- Conditional orders, not just market orders. Agents can defer a trade until a price level is crossed. Expiry is mandatory; a separate watcher process fires the order when the condition is met and applies the same order-level rails as a market fill.
Architecture — Brain / Hands
The Brain (agents) only ever writes to disk; it holds no credentials. The Hands (the paper broker, a separate watcher process) reads that outbox, enforces the rails, and executes. The boundary is a directory of append-only JSONL files, so a real-money broker is a drop-in swap for the paper one behind the same contract.
flowchart LR
A["Agents (Brain)"] -->|"author orders"| O["outbox/*.jsonl"]
O --> B{"paper broker: safety rails"}
B -->|"filled"| I["inbox/*.jsonl"]
B -->|"rejected + reason code"| I
I -->|"apply_trade"| P["portfolios/*.json"]
A -.->|"conditional order"| PE["pending/order_id.json"]
PE --> W["check_triggers watcher"]
W -.->|"price level crossed"| B
Quickstart — reach a real fill
This drives the full loop end-to-end: bootstrap prices, hand-author two orders (one clears, one is deliberately oversized to trip a rail), run the broker, and inspect the fills.
python -m venv .venv && source .venv/bin/activate
pip install midas-core
# Materialise the packaged demo desk (roster.yaml, .claude/agents/demo-*.md,
# data/universes/*.json) into a directory you name — no git clone required.
midas init-demo ./my-desk
export MIDAS_DATA_DIR=$PWD/my-desk
# One-time: open a USD 10,000 portfolio for demo-momentum.
python -c "
from engine.config import get_config
from engine.portfolio import PortfolioManager
pm = PortfolioManager(base_dir=get_config().portfolios_dir)
pm.initialize('demo-momentum', initial_capital=10000, currency='USD')
"
# Bootstrap the price store from yfinance (the one networked step; the live desk
# populates this store from a cron so trading sessions stay HTTP-free).
midas fetch-ohlcv --symbols SPY,QQQ,IWM,VTV,SCHD,BRK-B,URTH --history-days 90
Author two orders — append-only JSONL, one per line — to
$MIDAS_DATA_DIR/data/orders/outbox/<TODAY>.jsonl (<TODAY> = today's YYYY-MM-DD). Every
field is required, including a non-empty reasoning (no silent trades); shares must be
strictly positive (Midas is long-only):
{"order_id": "ord_demo_001", "ts": "2026-04-17T20:00:00Z", "agent_id": "demo-momentum", "action": "BUY", "ticker": "SPY", "shares": 3, "reasoning": "Trend intact above the 50-day; adding core exposure.", "currency": "USD"}
{"order_id": "ord_demo_002", "ts": "2026-04-17T20:00:00Z", "agent_id": "demo-momentum", "action": "BUY", "ticker": "SPY", "shares": 10, "reasoning": "Deliberately oversized clip to demonstrate the notional rail.", "currency": "USD"}
demo-momentum's max_order_notional is 5000. With SPY near $740 the first order ($2,200)
clears; the second ($7,400) breaches the cap. Run the broker:
midas fill-day
# fill-day: 1 filled, 1 rejected out of 2
The inbox is the durable Hands-side record of both outcomes:
cat $MIDAS_DATA_DIR/data/orders/inbox/<TODAY>.jsonl
{"order_id": "ord_demo_001", "status": "filled", "fill_price": 738.18, "notional_base": 2214.54, "fees": 1.25, "reason": null}
{"order_id": "ord_demo_002", "status": "rejected", "fill_price": null, "notional_base": null, "fees": null, "reason": "MAX_ORDER_NOTIONAL"}
The filled order mutated data/portfolios/demo-momentum/portfolio.json (cash debited, a SPY
position opened); the rejected one changed nothing but its reason. Exact prices depend on the day
you fetch — the shape (one fill, one rejection, a debited portfolio) is the point.
The full walkthrough — the portfolio JSON, the executed_sha provenance stamp, and the roster
schema — is in ./examples/demo-desk/README.md.
From source (contributors)
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # pinned lockfile (incl. pytest + hypothesis)
pip install -e . # the midas-core package + the `midas` CLI
# Point the engine at a working copy of the demo desk.
cp -R examples/demo-desk /tmp/my-desk
export MIDAS_DATA_DIR=/tmp/my-desk
pytest -q
Run your own desk
The whole cast is config. Copy the demo desk and edit two things:
roster.yaml— declare your traders, anarrator, and an optionalallocator, each with its universe, starting capital, and broker-enforcedsafetyrails (max_order_notional,max_orders_per_day,daily_drawdown_halt_pct,allowed_universe)..claude/agents/*.md— the persona behind each id: its voice and its strategy.
Nothing else is hardcoded. The full roster schema (every field and its default) is documented in
./examples/demo-desk/README.md.
What you need
| To run… | Requirements |
|---|---|
| Deterministic pipeline — fills, baselines, backtests | Python 3.12+ only. No API keys, no accounts. |
| LLM trading sessions — personas, journals, narration | Runs under Claude Code (scripts/daily_session.py). |
The deterministic pipeline is headless and fully tested; you can drive a desk end-to-end with no model at all by hand-authoring orders, exactly as the quickstart does.
Honest framing
- Paper-trading by default. Fills are simulated against a committed price store. No output is a track record, evidence of an edge, or investment advice.
- Framework, not a service. midas-core never executes against your broker keys, never holds credentials, never pools or manages anyone's funds, and gives no per-user advice. A real-money broker would be your code, swapped in behind the same outbox/inbox contract.
- Full terms: DISCLAIMER.md.
Relationship to the live desk
This repository is a one-way code mirror, synced from the operator's private live repo (the
source of truth) by a manifest tool. The live desk's data ledger — its real portfolios, journals,
and daily narrative — stays private and is not in this repo; the bundled examples/demo-desk
is a synthetic fixture. Because of the mirror direction, code PRs against synced trees can't be
merged — please open an issue instead. See CONTRIBUTING.md.
Layout
engine/— types, market data, bt adapter, paper broker, config (roster.yamlloader), universes.scripts/— session orchestration (daily_session.py), the conditional-order watcher (check_triggers.py), backtest runners, universe refresh.examples/demo-desk/— the forkable reference desk.data/{strategies,universes}/— generic strategy specs + index constituents.
License
MIT.
Metadata
Release files for midas-core 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 | |
|---|---|---|---|
| midas_core-0.1.1.tar.gz | 291.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| midas_core-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 472.3 kB
Release files / midas_core-0.1.1.tar.gz
| Download URL | midas_core-0.1.1.tar.gz |
|---|---|
| Size | 291.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1cf3183e381984ccc98b2564eec49bf899067f46a5799ab5cc4d8c7380d3f90b
|
|
BLAKE2b-256 checksum How to use checksums |
d2405d542727154c18b197e9f6dbcf393271fbafa04376c006434c439c95b589
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.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 Aug 2, 2026.
Transparency logRelease files / midas_core-0.1.1-py3-none-any.whl
| Download URL | midas_core-0.1.1-py3-none-any.whl |
|---|---|
| Size | 181.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
43f2f52976eca25e3ebd034e8379b1c25e3f48aefaa8e55c8ae76dbe4f8012e3
|
|
BLAKE2b-256 checksum How to use checksums |
402694df9cff59fb32c84e9666751feea5b37e27372c15bc6065db7f43274542
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.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 Aug 2, 2026.
Transparency log