coreytrading
A US-equity trading operations system built around domain agents, interchangeable model runtimes, and executable trading rules. Codex and Claude collaborate on research; a host controller validates their outputs and applies reviewed card updates. Orders are placed manually.
中文版 · Agent operations · Code architecture · Scheduled tasks · Trading data · AI bootstrap
The project contract for every model is AGENTS.md (read natively by Codex and Claude Code ≥ 2.1.277); CLAUDE.md is a one-line @AGENTS.md import shim for older Claude Code runtimes.
Trading covers US equities and the existing US equity-options workflow. Cross-asset macro data supplies context and research inputs only; it never becomes an additional trading market.
Architecture
The unit of responsibility is a domain role. Its methods, evidence requirements and output permissions live separately from its model assignment. Changing a role from Codex to Claude changes its route; the role contract and trading rules continue to apply.
flowchart TD
Trigger["Scheduled tasks / interactive requests"] --> Jobs["Host controller: jobs and pipeline"]
Sources["Broker and market caches / optional intelligence / valuation ledgers"] --> Inputs["Frozen evidence and domain views"]
Rules["Canonical structure, sizing and exit rules"] --> Inputs
Inputs --> Jobs
Routes["Role-to-model routing: Codex / Claude"] --> Jobs
Jobs --> Workflow["Technical → risk → bounded follow-ups"]
Lens["Macro lens (code-rendered, no model)"] --> Inputs
Workflow --> Reports["Research reports, disagreements and unknowns"]
ValTask["Independent valuation task"] --> ValFlow["Refresh and freeze → valuation calculations and research"]
ValFlow --> ValReport["Independent valuation report"]
Jobs --> Card["Single-card technical proposal"]
Card --> Review["Independent review by the other runtime"]
Review --> Submit["Policy, freshness, revision and write checks"]
Rules --> Submit
Submit --> Writer["Controlled card writer"]
Writer --> State["Updated card and submission receipt"]
State --> Plan["Mechanical entry and exit plans"]
Reports --> Human["Operator review and manual execution"]
Plan --> Human
The model handles interpretation and collaboration. Python owns data ingestion, numerical calculations, process limits, validation and state mutation. Workers receive frozen evidence and return structured JSON; they cannot access the workspace, call the broker, send messages or place orders.
Default agent assignments
| Agent | Runtime (when it runs) | Independent reviewer runtime | Responsibility |
|---|---|---|---|
| Technical analysis | Claude (the only daily model role; reused for the same close and card revisions) | Codex CLI | Read price structure, gates and zones; propose individual card updates |
| Risk and position management | Daily: code-rendered receipt (quant/report/risk_receipt.py); weekly: Claude |
Codex CLI | Review whole-book exposure, buying power, stops and sizing receipts |
| Valuation | Claude (independent daily job) | Codex CLI | Interpret financial statements, the compact EPS package, research targets and implied expectations |
Macro is not a model role: the macro lens is rendered by code after every close — six risk lights (they forecast volatility and drawdown depth, not direction), the strongest macro driver over the last 40 days and how the market reads it (a description, not a persistence claim), what the market is trading, and forward scenarios with estimated betas. It makes no model calls and carries no trading authority; see quant/core/macro_lens.py and the publisher quant/journal/macro_lens_log.py. Its compact prior rides in every frozen capture for the technical and valuation views.
agents/routing.json is the configuration source of truth. A role, runtime, model provider and model ID are separate concepts: valuation is a role, Codex CLI is a runtime, OpenAI is a provider, and a particular GPT version is a model. Routing v2 defines explicit model_profiles; each role selects a primary profile and an independent reviewer profile.
| Model profile | Primary model | Secondary model | Explicit effort |
|---|---|---|---|
| Anthropic / Claude Code | claude-fable-5-1 |
claude-opus-5 |
xhigh (extra high) |
| OpenAI / Codex CLI | gpt-6-astra |
gpt-5.6-sol |
high |
Primary, fallback and reviewer calls all carry explicit model and effort parameters. These settings do not inherit the desktop conversation's model. Receipts distinguish requested settings from model IDs actually reported by CLI metadata; absent or multiple reported models remain explicit rather than being replaced with the requested ID. A reviewer is invoked when review is requested; whether card submissions require independent approval is set by autopaint.review.
A valid abstention is retained. The current production configuration disables model fallbacks and independent review; failures remain failures with the assigned provider. The controller retains configurable failover and review support for an explicit re-enable. An explicit session quota error skips remaining models on that runtime for the current run. Review selects the runtime opposite the actual research provider; if it is unavailable, research is retained as needs_review and cannot be submitted. Refusal to approve does not trigger another model. Model upgrades follow the documented model maintenance policy, with explicit versions and validation before activation.
How agents collaborate
- Capture evidence. The host reads existing state and caches, records their owners, timestamps and hashes, and freezes a shared snapshot with a view for each role. Capturing data does not refresh it; missing or stale evidence stays visible.
- Domain research. The technical agent analyzes its assigned view in the trading workflow (the macro prior comes from the code-rendered macro lens). The separate valuation workflow runs host calculations and valuation research in sequence. Outputs distinguish observations, hypotheses, risks and unknowns, with references bound to the captured evidence.
- Review the portfolio. The risk agent receives its original inputs and the current technical report. Its view includes all managed holdings, including option-specific exit rules and available Greeks. Amounts come from the existing mechanical calculations.
- Resolve focused questions. Automatic follow-ups are disabled in the production budget profile (
max_followup_rounds=0); the controller can support at most one round when explicitly configured. Unresolved questions remain in the record. Repeating a claim through another model does not create independent evidence.
The current configuration allows two parallel calls and eight calls per workflow, with no automatic follow-up round. A shared host limit also caps concurrent native calls at two and calls within a rolling hour at 12. Fallbacks consume the same budget; concurrency waits are bounded. These limits control this system's workload, not either provider's account quota or billing.
With execution_transport = desktop the host does not start model CLIs: packets are written under var/agent-runs/desktop/, and each runtime's desktop session claims, answers and completes them under tasks/desktop-research.md. Orchestration, frozen evidence, controlled submission and applied receipts stay with the host. The daily loop runs only the technical role; risk receipts are code-rendered and the technical + risk workflow runs only in the weekly review.
Reviewed automatic card updates
The current configuration enables autopaint.enabled and autopaint.apply with autopaint.review=false. Technical proposals pass the host evidence, revision and mechanical-policy checks before writing, without a second model review. New run records bind that review policy; older records still require review by default. Receipts mark model review as not required, rather than approved. Eligible missing or stale cards can enter the automatic update flow. Portfolio reports themselves do not write cards; each target gets a separate technical proposal, and independent model review is controlled by the host policy.
The host checks the original evidence, result and policy bindings, expiry, permitted arguments and the target's current revision. It saves a before-image backup and a prepared submission receipt before invoking the existing card writer. Broker-owned fields, lots, pending orders and binding constraints remain protected.
| Result | Meaning |
|---|---|
succeeded |
A model result passed the research contract; it does not prove a card was written |
needs_review |
Evidence, review or submission checks require attention |
partial |
A job finished with failed or pending work recorded |
applied |
The target card update has a confirmed submission receipt |
Setting autopaint.apply to false returns automatic card work to research and preview. The switch is checked again before an automatic commit, including for work already in progress. It does not undo completed writes. Explicit selection of a single proposal through submit --apply is a separate manual submission path, documented in the operations manual.
An uncertain write is reconciled against its prepared before/after hashes. Recovery updates the receipt; it does not blindly repeat a card write. Run artifacts, card backups and health events retain the evidence needed to investigate a case.
Daily operation
Any scheduler that can run a prompt with a coding agent (a desktop task runner, cron with a CLI agent) can trigger the six trading tasks and the macro-lens publisher. The Python controller chooses the domain runtimes independently of that scheduler.
| Task | Domain work |
|---|---|
heartbeat |
Broker/state reconciliation, mechanical risk and exit alerts, health checks and nonblocking missing-card dispatch |
overnight-briefing |
Refresh daily inputs, run the technical role (reused when the close and cards are unchanged) with the code-rendered risk receipt, include the macro-lens lines, process the repaint queue and prepare entry plans |
postclose-transition |
Evaluate exits, apply completed-session transitions, render transition receipts, run technical research with the code-rendered risk receipt and process repaints |
gate-ladder-report |
Wait for the same session's postclose job to settle, then render the mechanical gate ladder |
macro-lens |
30 minutes after the actual close, without waiting for postclose: refresh cross-asset daily data, publish the code-rendered macro lens (reading, ledger, full text) and push it as its own message; publishes nothing if the session's bars are missing |
chart-read |
Code-rendered list of the two tradable setups (bottom, trend confirmation) that have formed or are forming; no model call |
weekly-portfolio-review |
Portfolio risk review using existing performance and technical evidence plus the weekly macro-lens review, with the NAV change net of external cash flows |
The independent valuation-daily task (tasks/claude/valuation-daily.md; a Codex-runner variant lives in tasks/codex/valuation-daily.md) refreshes inputs and runs the valuation chain — including the unvalidated research-grade 12-month targets — for its own report under var/valuation-daily/. Briefing and weekly review do not run the valuation role.
For briefing and postclose, the critical pipeline order is:
Refresh broker and market inputs
→ evaluate exits against the existing card
→ apply mechanical regime transitions
→ run domain research and reviewed card updates
→ refresh reminders and entry-authorization groups
→ produce entry plans
The synchronous repaint stage handles at least five targets per run, or ⌈N/2⌉ of a longer queue so any queue drains in two runs, and records the remainder. Missing-card detection can also dispatch background work through the same single-card controller and shared limits.
market_sessions.py uses the XNYS calendar for holidays, early closes and daylight saving. Every prompt starts with quant/ops/agent_jobs.py due --kind <kind>; postclose, ladder and chart windows open 10, 20 and 35 minutes after the actual close and all close 60 minutes after it. Calendar gating and upstream completion are separate checks. The pinned calendar currently covers 2000–2028; unavailable or unsupported calendar data stops the decision instead of falling back to a weekday guess.
Prompts in tasks/ are versioned sources. Live prompt copies, application registration and completed-run receipts are distinct evidence. Schedule details and synchronization procedures live in tasks/README.md.
Trading rules and ownership
The strategy remains technical-first trend following. A gate marks a structural state transition; a zone describes participation within a state; a cap is an authorization ceiling. These have different meanings and are enforced by code.
| Decision or data | Source of truth |
|---|---|
| Structure, regime and binding stops | structure.py and regime_transition.py |
| Gate budgets, exposure and executable position capacity | sizing.py and book.py |
| Entry plans and mechanical exits | entry_guard.py and exit_guard.py |
| Broker quantities, fills and open orders | quant/sync/; agents do not write broker truth |
| Technical card proposals | Technical role, independent review and the controlled writer |
| Macro and valuation evidence | Informational context; neither overrides structural authorization or an exit |
| NAV change and external cash flows | nav_report.py over the cash-flow ledger kept by cash_flow_sync.py; deposits and withdrawals are not performance |
| Research and rule changes | Strategy schemas (private rules are the ignored copies), the research scaffold and the applicable validation study |
Risk agents interpret mechanical receipts rather than inventing another sizing formula. Candidate capacities share portfolio limits and cannot be added together as a batch budget. Unknown buying power, instrument identity or evidence remains unknown. News and macro collection belongs to an optional, separately maintained intelligence workflow; its published data lives under trade/intelligence/ (this repository ships only the README and a synthetic example), and trading roles consume the existing archives read-only and degrade gracefully when they are absent.
Repository map
| Location | Contents |
|---|---|
| AGENTS.md | Project contract for every model (Codex and Claude Code ≥ 2.1.277 read it natively); CLAUDE.md is a one-line @AGENTS.md import shim kept for older Claude Code runtimes |
| AI_BOOTSTRAP.md / AI_BOOTSTRAP_CN.md | Fresh-clone setup guide for a coding agent |
| agents/ | Domain methods, role contracts, routing and operating manual |
| quant/ | Host controllers, data/sync, mechanical decisions, valuation and reports |
| tests/ | Synthetic mechanics, contract, isolation and repository checks |
| tasks/ | Versioned scheduled-task prompts and deployment instructions |
| trade/ | AI bootstrap contract: READMEs and synthetic *.example.* schemas for the six data domains below; private cards, holdings, events, caches, intelligence data and rules are ignored copies |
var/ |
Ignored private runtime state: the portfolio lock, intelligence claims and delivery receipts, agent runs, quotas and leases, and daily valuation runs |
tmp/ |
Ignored temporary output and the heartbeat cooldown state |
.claude/ |
Rules, skills and host integration |
The six domains sit directly under trade/. quant/core/paths.py defines their canonical paths:
| Directory | Contents |
|---|---|
trade/portfolio/ |
Positions, candidates, fills/NAV/cash-flow ledgers, scores, journals and derived observations |
trade/market/ |
Prices, financial statements and raw market inputs; refreshable caches and historical snapshots have distinct retention needs |
trade/intelligence/ |
Optional news sources and report archive, plus macro-lens readings / ledger / full reports |
trade/valuation/ |
Manual valuation inputs, compact EPS packages and release records |
trade/strategy/ |
Trading rules and method contracts |
trade/knowledge/ |
Knowledge materials and frozen, read-only research |
Derived portfolio judgments live in portfolio/observations/; the shared writer lock lives in var/portfolio/.state.lock. Readers support historical Git positions and old intelligence references while published evidence retains its original bytes. Future macro/event research keeps raw evidence, point-in-time features, outcome labels and experiments separate; no empty research subsystem is prebuilt.
Python dependencies remain layered: ops orchestrates lower layers; shared contracts and math live in core; research stays outside the live import path. See quant/README.md for the complete dependency rules. Private state and model artifacts are not reusable examples or public-release material.
Getting started
Python requirements and dependency pins live in pyproject.toml:
python3 -m venv .venv && . .venv/bin/activate
python -m pip install -e '.[dev]'
python -m pytest -q
The reference deployment uses macOS, authenticated Claude Code and Codex CLIs, Moomoo OpenD for broker/data synchronization and an isolated Python environment. The current Codex runner's isolation implementation requires macOS. Environment details are in tools-environment.md; credentials stay in .env and local credential stores. The complete setup procedure, including the private workspace built from the examples under trade/, is AI_BOOTSTRAP.md.
Run these commands from the repository root to inspect configuration, input metadata, scheduling eligibility and health without calling a model:
python3 quant/ops/agent_runtime.py roles
python3 quant/ops/agent_inputs.py --scope portfolio --json
python3 quant/ops/agent_jobs.py due --kind postclose
python3 quant/ops/agent_health.py
python3 quant/ops/agent_doctor.py --json
For an in-session cached brief, use the read-only pipeline:
python3 quant/ops/pipeline.py --mode briefing --read-only --json
This renders cached output. It skips synchronization, transitions, notifications, journals, agent calls and the entry stage; it is not a data refresh.
To request a technical and risk review from existing inputs:
python3 quant/ops/agent_jobs.py run --kind weekly --json
This command calls models and saves private research artifacts. It does not apply card updates. For single-card research, submission previews, explicit writes and uncertain-result recovery, use the agent operations manual.
Verification and extension
python -m pytest -q
python -m pytest --collect-only -q
Tests cover role/provider interchange, contract boundaries, evidence binding, expiry, concurrent work, independent review, controlled writes and recovery. Repository checks also enforce dependency direction, module coverage, valid documentation references, the trade/ scaffold and public sanitization.
Default tests skip explicitly marked private-data and host-state audits. Skipped audits are not evidence of success, and pytest alone does not provide network isolation. Model agreement and passing tests do not establish research quality or investment returns.
To change the system:
- Change a model assignment: edit routing.json and validate it with
agent_runtime.py roles. - Change a domain method: update the role definition and its evidence contract without duplicating mechanical rules in prompts.
- Add a provider: implement its runner and routing validation, then verify the same contracts and isolation boundaries.
- Add a role or permission: update the explicit role schema, workflow and tests; a new Markdown file alone does not register a role.
- Change trading mechanics: follow AGENTS.md and the applicable research validation requirements.
Disclaimer
This repository is software and research infrastructure, not investment advice or an advisory service. Trading can result in substantial or total loss; historical or backtested results do not guarantee future outcomes, and the public scaffold intentionally contains neither a performance claim nor a recommendation to trade any instrument. Anyone connecting the framework to real money is responsible for independent validation, local legal and tax requirements, broker terms and every execution decision.
License
MIT. This repository documents a trading process; its research and plans are not investment advice or a performance guarantee.