QuantLab is a CLI-first research system.
main.py is the public entrypoint and routes requests into the specialized CLI modules under src/quantlab/cli/.
This guide documents the current repository behavior, grouped by command family.
python main.py --helpPrints the available flags and exits.
python main.py --versionPrints the current QuantLab version string.
python main.py --checkPrints a deterministic JSON health summary for runtime validation.
Machine-facing request entrypoint for:
runsweepforwardportfolio
Example:
python main.py --json-request "{\"schema_version\":\"1.0\",\"request_id\":\"req_demo_001\",\"command\":\"run\",\"params\":{\"ticker\":\"ETH-USD\",\"start\":\"2023-01-01\",\"end\":\"2023-12-31\"}}"Optional lifecycle signalling:
python main.py --json-request "{\"schema_version\":\"1.0\",\"request_id\":\"req_demo_002\",\"command\":\"sweep\",\"params\":{\"config_path\":\"configs/experiments/eth_2023_grid.yaml\"}}" --signal-file logs/quantlab-signals.jsonlPlain run:
python main.py --ticker ETH-USD --start 2022-01-01 --end 2023-12-31 --reportSuccessful plain runs write canonical artifacts under:
outputs/runs/<run_id>/
Canonical files:
metadata.jsonconfig.jsonmetrics.jsonreport.json
Paper-backed run:
python main.py --ticker ETH-USD --start 2022-01-01 --end 2023-12-31 --paper --reportPaper execution is currently still entered through the run command surface, but it writes a dedicated paper-session artifact set under:
outputs/paper_sessions/<session_id>/
session_metadata.json
session_status.json
config.json
metrics.json
report.json
trades.csv
run_report.md
Important contract note:
- externally, a JSON request still uses
command: "run" - lifecycle signals still emit
mode = "run"for compatibility - internally, the result is a paper session and
report.json.machine_contract.contract_typeisquantlab.paper.result
For the formal artifact contract, see run-artifact-contract.md.
List runs under a root:
python main.py --runs-list outputs/runsShow one run:
python main.py --runs-show outputs/runs/20260324_005008_run_a468850Rank runs by a metric:
python main.py --runs-best outputs/runs --metric sharpe_simpleShared index artifacts are refreshed automatically after successful:
runsweepforward
Paper sessions do not currently refresh outputs/runs/runs_index.*.
Index files:
outputs/runs/runs_index.csvoutputs/runs/runs_index.jsonoutputs/runs/runs_index.md
List paper sessions under a root:
python main.py --paper-sessions-list outputs/paper_sessionsShow one paper session:
python main.py --paper-sessions-show outputs/paper_sessions/<session_id>Summarize paper-session health:
python main.py --paper-sessions-health outputs/paper_sessionsThe health summary is operator-facing and currently includes:
- total sessions
- count by status
- latest session id / activity time
- latest non-success session if present
Emit a deterministic alert snapshot for paper sessions:
python main.py --paper-sessions-alerts outputs/paper_sessions --paper-stale-minutes 60The alert snapshot is machine-readable JSON and currently makes these situations explicit:
- latest success visibility
- failed sessions
- aborted sessions
- running sessions that have become stale relative to the chosen threshold
For the recommended operating loop and response guidance, see paper-session-runbook.md.
For the current supervised broker happy path and failure path, see supervised-broker-runbook.md.
Refresh the shared paper-session index:
python main.py --paper-sessions-index outputs/paper_sessionsThis writes:
outputs/paper_sessions/paper_sessions_index.csvoutputs/paper_sessions/paper_sessions_index.json
The index is intentionally separate from outputs/runs/runs_index.* and is meant for repeated paper-session operations.
Emit a broker-promotion report for paper sessions:
python main.py --paper-sessions-promotion outputs/paper_sessionsThe promotion report highlights:
- paper sessions that are ready to move toward the broker boundary
- paper sessions that are still blocked and why
- the latest ready and blocked sessions for operator review
This command is meant to help bridge paper work into the supervised broker boundary without changing execution authority.
Write a deterministic readiness artifact before the first supervised broker evidence pass:
python main.py --broker-evidence-readiness-outdir outputs/broker_evidenceOptional corridor selection:
python main.py --broker-evidence-readiness-outdir outputs/broker_evidence --broker-evidence-corridor kraken
python main.py --broker-evidence-readiness-outdir outputs/broker_evidence --broker-evidence-corridor hyperliquidThis writes:
broker_evidence_readiness.json
The artifact makes these things explicit without printing secret values:
- requested and resolved corridor
- whether the evidence pass is actually ready to run
- which expected secrets are present by source name only
- expected local roots for:
outputs/paper_sessions/outputs/broker_order_validations/outputs/hyperliquid_submits/
- whether the supervised broker runbook is present
If the requested corridor is not ready, QuantLab still writes the artifact but exits with explicit blocking reasons.
Validate a bounded calculadora_riego_trading handoff artifact:
python main.py --pretrade-handoff-validate path/to/quantlab_handoff.jsonOptional output directory:
python main.py \
--pretrade-handoff-validate path/to/quantlab_handoff.json \
--pretrade-handoff-validation-outdir outputs/pretrade_handoff/demoThis writes:
pretrade_handoff_validation.json
The artifact is intentionally local and bounded. It validates:
- handoff contract type/version
- source trade-plan lineage metadata
symbolvenueside- trade-plan contract consistency
If the handoff is incomplete, QuantLab still writes the validation artifact but exits with explicit rejection reasons.
This surface does not yet:
- create pretrade sessions
- bridge into draft
ExecutionIntent - approve or submit anything
Persist a read-only Hyperliquid venue preflight artifact:
python main.py --hyperliquid-preflight-outdir outputs/broker_preflight/hyperliquid_demo --broker-symbol ETH --execution-transport-preference websocketThis writes:
outputs/broker_preflight/hyperliquid_demo/broker_preflight.json
The artifact currently includes:
- adapter name
- generated timestamp
- input and normalized symbol
- market type (
perporspot) - public API reachability
- market support result against Hyperliquid
metaorspotMeta - resolved coin and asset identifiers where available
- mid-price snapshot from
allMidswhere available - resolved execution-context details:
- execution account
- signer identity
- routing target
- transport preference
- nonce scope
- optional user-role lookups when valid addresses are provided
- explicit errors when market or context checks fail
This surface is read-only and does not place or validate orders.
Persist a read-only Hyperliquid account and signer readiness artifact:
python main.py --hyperliquid-account-readiness-outdir outputs/broker_preflight/hyperliquid_account_demo --execution-account-id 0x0000000000000000000000000000000000000000This writes:
outputs/broker_preflight/hyperliquid_account_demo/hyperliquid_account_readiness.json
The artifact currently includes:
- resolved execution account and signer context
- execution account role and signer role where available
- nonce-scope identity
- open-orders visibility over the execution account
frontendOpenOrdersvisibility over the execution account- readiness result plus explicit reasons when the signer/account setup is not yet suitable for supervised personal use
This surface is read-only and does not sign or submit actions.
Persist a local Hyperliquid action and signature-envelope artifact without submitting it:
python main.py --hyperliquid-signed-action-outdir outputs/broker_preflight/hyperliquid_signed_action_demo --broker-symbol ETH --broker-side buy --broker-quantity 0.25 --broker-notional 500 --execution-account-id 0x0000000000000000000000000000000000000000 --execution-nonce 1700000000000This writes:
outputs/broker_preflight/hyperliquid_signed_action_demo/hyperliquid_signed_action.json
The artifact currently includes:
- normalized broker intent
- local policy preflight
- Hyperliquid venue preflight snapshot
- Hyperliquid account/signer readiness snapshot
- resolved nonce and nonce source
- resolved
expiresAfterand how it was interpreted - a local order action payload using resolved Hyperliquid asset identifiers
- a signature envelope with signing payload hash and signer metadata
- optional real local signature data when a signing key is available
Signer backend options:
--hyperliquid-private-key <HEX_KEY>--hyperliquid-private-key-env <ENV_NAME>
Current limitation:
- this command itself does not submit anything to Hyperliquid
- if no signing key is present, the artifact keeps
signature_state = pending_signer_backend
Example with signer backend enabled through environment:
python main.py --hyperliquid-signed-action-outdir outputs/broker_preflight/hyperliquid_signed_action_demo --broker-symbol ETH --broker-side buy --broker-quantity 0.25 --broker-notional 500 --execution-account-id 0x0000000000000000000000000000000000000000 --execution-signer-id 0xSIGNER_ADDRESS --hyperliquid-private-key-env HYPERLIQUID_PRIVATE_KEY- on success, the artifact moves to
signature_state = signed - if the derived signer address does not match
execution-signer-id, the artifact reportssignature_state = signer_identity_mismatch
Submit a previously signed Hyperliquid artifact through the first supervised remote-submit path:
python main.py --hyperliquid-submit-signed-action outputs/broker_preflight/hyperliquid_signed_action_demo/hyperliquid_signed_action.json --hyperliquid-submit-reviewer marce --hyperliquid-submit-confirm --hyperliquid-submit-note "first supervised submit"Required flags:
--hyperliquid-submit-reviewer--hyperliquid-submit-confirm
Optional:
--hyperliquid-submit-note
This writes:
outputs/broker_preflight/hyperliquid_signed_action_demo/hyperliquid_submit_response.json
The artifact currently includes:
- source signed-action path
- source signer identity and payload hash
- final submit payload sent to Hyperliquid
- explicit reviewer and optional note
- remote-submit state
- exchange response snapshot
- response type where present
- explicit errors when submission is rejected or the signed artifact is not ready
Important safety notes:
- this path only accepts
hyperliquid_signed_action.json - the source artifact must already be
signature_state = signed - this is a narrow supervised submit surface, not yet a full session/reconciliation framework
- no websocket execution or cancel flow exists yet
Submit a previously signed Hyperliquid artifact into a canonical local session:
python main.py --hyperliquid-submit-session outputs/broker_preflight/hyperliquid_signed_action_demo/hyperliquid_signed_action.json --hyperliquid-submit-reviewer marce --hyperliquid-submit-confirm --hyperliquid-submit-sessions-root outputs/hyperliquid_submitsOptional root override:
--hyperliquid-submit-sessions-root <ROOT_DIR>
This writes a canonical session under:
outputs/hyperliquid_submits/<session_id>/
session_metadata.json
session_status.json
hyperliquid_signed_action.json
hyperliquid_submit_response.json
It also refreshes:
outputs/hyperliquid_submits/hyperliquid_submits_index.csvoutputs/hyperliquid_submits/hyperliquid_submits_index.json
List canonical Hyperliquid submit sessions:
python main.py --hyperliquid-submit-sessions-list outputs/hyperliquid_submitsShow one canonical Hyperliquid submit session:
python main.py --hyperliquid-submit-sessions-show outputs/hyperliquid_submits/<session_id>Refresh the shared Hyperliquid submit index:
python main.py --hyperliquid-submit-sessions-index outputs/hyperliquid_submitsRefresh normalized post-submit order status for one canonical Hyperliquid submit session:
python main.py --hyperliquid-submit-sessions-status outputs/hyperliquid_submits/<session_id>Run the first Hyperliquid reconciliation step for one canonical submit session:
python main.py --hyperliquid-submit-sessions-reconcile outputs/hyperliquid_submits/<session_id>This writes:
hyperliquid_reconciliation.json
The reconciliation step is conservative:
- it checks direct
orderStatusfirst - it falls back to
historicalOrders,openOrders,frontendOpenOrders, anduserFillsmatching byoidorcloid - it leaves the session in
unknownwith explicit reasons when no safe match is found
Refresh a richer fill summary for one canonical Hyperliquid submit session:
python main.py --hyperliquid-submit-sessions-fills outputs/hyperliquid_submits/<session_id>This writes:
hyperliquid_fill_summary.json
The fill summary keeps reconciliation separate from fill accounting and aggregates:
- matched fill count
- filled and remaining size
- average fill price
- total fee and builder fee
- total closed PnL when present
Run bounded continuous supervision over one canonical Hyperliquid submit session:
python main.py --hyperliquid-submit-sessions-supervise outputs/hyperliquid_submits/<session_id>Useful modifiers:
--hyperliquid-supervision-polls--hyperliquid-supervision-interval-seconds
This writes:
hyperliquid_supervision.json- refreshed
hyperliquid_order_status.json - refreshed
hyperliquid_reconciliation.json - refreshed
hyperliquid_fill_summary.json
The supervision step is intentionally still pull-based:
- it does not open private Hyperliquid websockets yet
- it does carry websocket-aware monitoring metadata when the execution context prefers websocket transport
- it gives operators a bounded local monitoring pass without introducing daemon-style runtime complexity
Submit a supervised cancel request for one canonical Hyperliquid submit session:
python main.py --hyperliquid-submit-sessions-cancel outputs/hyperliquid_submits/<session_id> --hyperliquid-cancel-reviewer marce --hyperliquid-cancel-confirmThis writes:
hyperliquid_cancel_response.json
The cancel step is intentionally narrow:
- it requires an existing signed-action artifact and submit-response artifact
- it signs a fresh cancel action with the current Hyperliquid signer backend
- it prefers
oidand falls back tocloidwhen needed - it records cancel acceptance separately from remote order-state confirmation
- it does not claim the order is canceled until later status/reconciliation confirms that state
Summarize Hyperliquid submission health across canonical submit sessions:
python main.py --hyperliquid-submit-sessions-health outputs/hyperliquid_submitsThis prints a compact operator summary with:
- total sessions
- submit-response coverage
- cancel-response coverage
- submitted session count
- sessions with known order state
- sessions with reconciliation artifacts
- sessions with an effective known order state after reconciliation
- latest submit id/state
- latest notable issue id/code/time
Emit a deterministic alert snapshot for notable Hyperliquid submit-session states:
python main.py --hyperliquid-submit-sessions-alerts outputs/hyperliquid_submitsAlert output stays local and read-only. It is meant to highlight states such as:
- submitted sessions missing a persistent
hyperliquid_order_status.json - submitted sessions whose remote order state is still unknown
- rejected or canceled remote order states
- submit attempts that failed or remain in a non-ready state
This writes:
outputs/hyperliquid_submits/<session_id>/hyperliquid_order_status.json
The status surface currently:
- queries Hyperliquid
orderStatususing session-derivedoidorcloid - persists the raw order-status snapshot
- normalizes local state into
open,filled,canceled,rejected, orunknown - updates
session_status.jsonso session inspection reflects the latest known order state
Current limitation:
- no Hyperliquid reconciliation flow exists yet beyond the direct
orderStatusquery - no websocket supervision or cancel path exists yet
Persist a read-only Kraken public preflight artifact:
python main.py --kraken-preflight-outdir outputs/broker_preflight/demo --broker-symbol ETH-USDThis writes:
outputs/broker_preflight/demo/broker_preflight.json
The artifact currently includes:
- adapter name
- generated timestamp
- input and normalized symbol
- public API reachability
- server time snapshot
- pair support result against Kraken public asset-pair metadata
- matched pair identifiers where available
- explicit errors when support or reachability checks fail
This surface is read-only and does not use private Kraken authentication.
Persist a read-only Kraken authenticated preflight artifact:
python main.py --kraken-auth-preflight-outdir outputs/broker_preflight/auth_demoBy default this reads credentials from:
KRAKEN_API_KEYKRAKEN_API_SECRET
Optional overrides:
--kraken-api-key--kraken-api-secret--kraken-api-key-env--kraken-api-secret-env
This writes:
outputs/broker_preflight/auth_demo/broker_auth_preflight.json
The artifact currently includes:
- whether credentials were present
- whether private authentication succeeded
- key name where available
- permissions snapshot where available
- restrictions snapshot where available
- created/updated timestamps where available
- explicit auth or credential errors
This surface is read-only and does not place or cancel orders.
Persist a read-only Kraken account snapshot and intent readiness artifact:
python main.py --kraken-account-readiness-outdir outputs/broker_preflight/account_demo --broker-symbol ETH-USD --broker-side buy --broker-quantity 0.25 --broker-notional 500 --broker-account-id acct_demoBy default this reads credentials from:
KRAKEN_API_KEYKRAKEN_API_SECRET
It reuses the existing broker intent flags:
--broker-symbol--broker-side--broker-quantity--broker-notional--broker-account-id--broker-max-notional--broker-allowed-symbols--broker-kill-switch--broker-allow-missing-account-id
This writes:
outputs/broker_preflight/account_demo/broker_account_snapshot.json
The artifact currently includes:
- public pair support and matched Kraken pair identifiers
- base / quote asset mapping for the chosen pair
- pair minimums such as
orderminandcostminwhere available - authenticated preflight summary
- extended balance snapshot where authentication and permissions allow it
- local preflight result for the provided
ExecutionIntent - balance-aware readiness result for that intent
- explicit reasons such as:
private_auth_not_readyaccount_snapshot_unavailablefunding_asset_missinginsufficient_available_balancebelow_pair_orderminbelow_pair_costmin
This surface is read-only and does not place or cancel orders.
Persist a validate-only Kraken order probe artifact:
python main.py --kraken-order-validate-outdir outputs/broker_preflight/validate_demo --broker-symbol ETH-USD --broker-side buy --broker-quantity 0.25 --broker-notional 500 --broker-account-id acct_demoBy default this reads credentials from:
KRAKEN_API_KEYKRAKEN_API_SECRET
It reuses the existing broker intent flags:
--broker-symbol--broker-side--broker-quantity--broker-notional--broker-account-id--broker-max-notional--broker-allowed-symbols--broker-kill-switch--broker-allow-missing-account-id
This writes:
outputs/broker_preflight/validate_demo/broker_order_validate.json
The artifact currently includes:
- authenticated preflight summary
- local policy preflight result
- Kraken validate-only payload
- whether the remote validate call was attempted
- whether Kraken accepted the validate-only order probe
- explicit validation reasons from local or exchange-side rejection
- raw exchange response where available
Important note:
- this does not place an order
- but it still uses Kraken's order-validation path and therefore may require order-related API permissions
Persist a canonical broker order-validation session:
python main.py --kraken-order-validate-session --broker-symbol ETH-USD --broker-side buy --broker-quantity 0.25 --broker-notional 500 --broker-account-id acct_demoThis writes a canonical session under:
outputs/broker_order_validations/<session_id>/
broker_order_validate.json
session_metadata.json
session_status.json
And refreshes the shared registry:
outputs/broker_order_validations/broker_order_validations_index.csvoutputs/broker_order_validations/broker_order_validations_index.json
List broker order-validation sessions:
python main.py --broker-order-validations-list outputs/broker_order_validationsShow one broker order-validation session:
python main.py --broker-order-validations-show outputs/broker_order_validations/<session_id>Refresh the shared broker order-validation registry explicitly:
python main.py --broker-order-validations-index outputs/broker_order_validationsPersist a local approval decision for one broker order-validation session:
python main.py --broker-order-validations-approve outputs/broker_order_validations/<session_id> --broker-approval-reviewer marce --broker-approval-note "Approved after validate-only review"This writes:
outputs/broker_order_validations/<session_id>/approval.json
The approval artifact currently includes:
status = approvedreviewed_byreviewed_at- optional
note - validation context fields carried forward from the reviewed session
Important note:
- this is a local human approval gate only
- it does not place an order
- it does not imply broker submission has happened
Generate a pre-submit bundle from an approved broker order-validation session:
python main.py --broker-order-validations-bundle outputs/broker_order_validations/<session_id>This writes:
outputs/broker_order_validations/<session_id>/broker_pre_submit_bundle.json
The bundle currently includes:
- source
session_metadata.json - source
session_status.json - source
broker_order_validate.json - source
approval.json - source session id
- generation timestamp
bundle_state = ready_for_supervised_submit
Important note:
- this command fails if the source validation session is not approved
- it still does not place an order
- it is the final local handoff artifact before any future supervised submit path
Generate a supervised submit gate artifact from a session that already has a pre-submit bundle:
python main.py --broker-order-validations-submit-gate outputs/broker_order_validations/<session_id> --broker-submit-reviewer marce --broker-submit-confirm --broker-submit-note "Ready for supervised submit review"This writes:
outputs/broker_order_validations/<session_id>/broker_submit_gate.json
The submit gate currently includes:
- source session id
- generation timestamp
submit_state = ready_for_supervised_submit_gate- reviewer identity
- optional reviewer note
- embedded source
broker_pre_submit_bundle.json
Important note:
- this command fails if the source session does not already have a pre-submit bundle
--broker-submit-confirmis required- it still does not place an order
- it is the final local supervised gate before any future submit implementation
Generate a supervised submit stub artifact from a session that already has a submit gate:
python main.py --broker-order-validations-submit-stub outputs/broker_order_validations/<session_id>This writes:
outputs/broker_order_validations/<session_id>/broker_submit_attempt.json
The submit stub currently includes:
- source session id
- generation timestamp
submit_mode = stubwould_submit = true- final submit payload derived from the validated session
- embedded source
broker_submit_gate.json
Important note:
- this command fails if the source session does not already have a submit gate
- it still does not place an order
- it is the first operational shape of a future supervised submit path, but still entirely local
Perform a first tightly gated real Kraken submit from a session that already has a submit gate:
python main.py --broker-order-validations-submit-real outputs/broker_order_validations/<session_id> --broker-submit-reviewer marce --broker-submit-confirm --broker-submit-live --broker-submit-note "First supervised live submit"This writes:
outputs/broker_order_validations/<session_id>/broker_submit_response.json
The submit response currently includes:
- source session id
- generation timestamp
- authenticated preflight summary
- final submit payload with stable
userref - a pre-remote local artifact write before the real submit call path
- whether the remote submit call was attempted
- whether the order was submitted successfully
- returned
txidvalues where available - raw exchange response
- explicit errors
- local reviewer identity and optional note
- embedded source
broker_submit_gate.json
Important notes:
- this command fails if the source session does not already have a submit gate
- this command fails if the source validation session was not previously accepted by Kraken validate-only
- both
--broker-submit-confirmand--broker-submit-liveare required - this is the first path that can hit Kraken's real order endpoint
- it is intentionally narrow and currently meant for supervised market-order submission only
- the session will persist
broker_submit_response.jsoneven when the remote submit is rejected or auth is not ready
Reconcile an existing broker submit response against Kraken order state:
python main.py --broker-order-validations-reconcile outputs/broker_order_validations/<session_id>This command:
- requires an existing
broker_submit_response.json - uses the stable session-derived
userref - checks Kraken order state through authenticated account-data endpoints
- updates the existing submit response artifact in place with reconciliation details
The reconciliation update currently includes:
- whether reconciliation was attempted
- whether any matching order was found
- matched sources such as
openorclosed - matched
txidvalues - matched order statuses
- explicit reconciliation errors
Important notes:
- this command is meant for ambiguous or post-submit review states, not for ordinary preflight
- it does not place a new order
- it is the current safety path before any future auto-retry or broader live routing logic
Refresh normalized post-submit order status for a submitted broker validation session:
python main.py --broker-order-validations-status outputs/broker_order_validations/<session_id>This writes:
outputs/broker_order_validations/<session_id>/broker_order_status.json
The order-status artifact currently includes:
- query mode (
txidoruserref_fallback) - whether status lookup was attempted
- whether status is known
- normalized local state
- matched
txidvalues - raw exchange statuses
- matched order payloads where available
- explicit errors
Normalized local state currently maps to:
openclosedcanceledexpiredunknown
Important notes:
- this command requires an existing
broker_submit_response.json - it does not place a new order
- it is the first persistent post-submit status surface for supervised broker sessions
Summarize broker submission health across broker order-validation sessions:
python main.py --broker-order-validations-health outputs/broker_order_validationsThis command currently summarizes:
- total broker validation sessions
- how many sessions reached local approval
- how many reached submit-gate
- how many have submit responses
- how many were actually submitted
- how many already have known persistent order status
- latest submit session and latest notable issue
This surface is operator-facing and read-only.
Emit a deterministic alert snapshot for notable broker submission states:
python main.py --broker-order-validations-alerts outputs/broker_order_validationsThe alert snapshot currently highlights:
- submitted sessions with missing order-status artifacts
- submitted sessions whose order state is still unknown
- rejected or not-ready submit states
- expired or canceled remote order states when known
The output is machine-readable JSON intended for local operator review and future low-coupling automation.
Persist a local Kraken dry-run audit artifact:
python main.py --kraken-dry-run-outdir outputs/broker_dry_runs/demo --broker-symbol ETH-USD --broker-side buy --broker-quantity 0.25 --broker-notional 500 --broker-account-id acct_demo --broker-max-notional 1000 --broker-allowed-symbols ETH/USD,BTC/USDThis writes:
outputs/broker_dry_runs/demo/broker_dry_run.json
The artifact currently includes:
- adapter name
- generated timestamp
- normalized execution intent
- execution policy
- preflight allow/reject result
- translated Kraken-style payload if preflight passes
If preflight rejects the intent, the artifact is still written with explicit rejection reasons and payload = null.
Persist a canonical Kraken dry-run session:
python main.py --kraken-dry-run-session --broker-symbol ETH-USD --broker-side buy --broker-quantity 0.25 --broker-notional 500 --broker-account-id acct_demo --broker-max-notional 1000 --broker-allowed-symbols ETH/USD,BTC/USDThis writes a canonical session under:
outputs/broker_dry_runs/<session_id>/
broker_dry_run.json
session_metadata.json
session_status.json
And refreshes the shared registry:
outputs/broker_dry_runs/broker_dry_runs_index.csvoutputs/broker_dry_runs/broker_dry_runs_index.json
List broker dry-run sessions:
python main.py --broker-dry-runs-list outputs/broker_dry_runsShow one broker dry-run session:
python main.py --broker-dry-runs-show outputs/broker_dry_runs/<session_id>Refresh the shared broker dry-run registry explicitly:
python main.py --broker-dry-runs-index outputs/broker_dry_runsLaunch a forward session from a prior candidate-producing run directory:
python main.py --forward-eval outputs/runs/<grid_or_walkforward_run_id> --forward-start 2024-01-01 --forward-end 2024-06-01 --forward-outdir outputs/forward_runs/fwd_demoResume a prior forward session:
python main.py --resume-forward outputs/forward_runs/<session_id>Typical forward session artifacts:
outputs/forward_runs/<session_id>/
portfolio_state.json
forward_trades.csv
forward_equity_curve.csv
forward_returns_series.csv
report.json
forward_report.json
forward_report.md
Aggregate forward sessions:
python main.py --portfolio-report outputs/forward_runsSelection/weighting example:
python main.py --portfolio-report outputs/forward_runs --portfolio-mode custom_weight --portfolio-weights path/to/weights.json --portfolio-top-n 5 --portfolio-rank-metric total_returnCompare allocation modes on the same forward-session universe:
python main.py --portfolio-compare outputs/forward_runsPortfolio report artifacts are written in the target root, for example:
outputs/forward_runs/
report.json
portfolio_report.json
portfolio_report.md
portfolio_compare.json
portfolio_compare.md
Flag-driven sweep:
python main.py --sweep configs/experiments/eth_2023_grid.yaml --sweep_outdir outputs/stepbitMachine-facing sweep:
python main.py --json-request "{\"schema_version\":\"1.0\",\"request_id\":\"req_sweep_001\",\"command\":\"sweep\",\"params\":{\"config_path\":\"configs/experiments/eth_2023_grid.yaml\",\"out_dir\":\"outputs/stepbit\"}}"report.json.machine_contract is the canonical machine-facing result surface for automated sweep consumption.
These remain accepted for backward compatibility, but should not be expanded further in docs or integrations:
--list-runs-> legacy alias of--runs-list--best-from-> legacy alias of--runs-best
Legacy read-compatible artifacts also remain in the codebase:
meta.jsonrun_report.jsonforward_report.jsonportfolio_report.json
The preferred public surface is the canonical contract documented in run-artifact-contract.md.
main.pyandsrc/quantlab/cli/should remain orchestration-only- domain and quantitative logic belong outside the entrypoint
- new public behavior must be documented with executable examples
- new machine-facing behavior should prefer canonical artifacts over legacy outputs