Skip to content

NEO Config Wiring Reference

Owner: Orion Produced: 2026-04-18 (Branch #5 audit/config-wiring-pass, Commit 3) Scope: Every runtime-critical YAML key and where it manifests.


Purpose

This is the audit output for Atlas Pre-7.3 Review §2B: prove that every critical YAML key → Config dataclass field → loader line → runtime consumer → observable metric. Any value that does not manifest in behavior is a wiring failure and would be listed here in the "Verified" column as a dash.

This reference is workspace-only. The table belongs to the team's operating context, not the codebase. A one-line pointer comment at the top of neo_engine/config.py points here so a code reader who needs it can find it. Kept out of the repo by Katja's Q3 ruling on Branch #5.

How to read this

  • YAML key — the dotted path in config/config.yaml or config/config.example.yaml.
  • Config field — the dataclass attribute in neo_engine/config.py. Frozen dataclass; Config.strategy.foo means StrategyConfig.foo.
  • Loader site — the line in load_config() that plumbs the YAML value into the dataclass. Format neo_engine/config.py:NNN.
  • Runtime consumer — the module + line that reads the field on each tick or at startup. "Startup" = read once; "Tick" = re-read per _tick().
  • Observable metric — where you can see the value's effect externally (DB column, log field, engine_state key, or dashboard cell).
  • Verified — ✓ if the chain was walked and confirmed on this branch; ✗ if the chain is broken and a wiring bug was filed.

Rows are ordered to match how they appear in config.yaml.

XRPL node

YAML key Config field Loader site Runtime consumer Observable metric Verified
xrpl_node.rpc_url XRPLNodeConfig.rpc_url config.py:350 xrpl_gateway.py — JsonRpcClient constructor (startup) engine_state live.endpoint_rpc (if set)
xrpl_node.websocket_url XRPLNodeConfig.websocket_url config.py:351 xrpl_gateway.py — WebsocketClient constructor (startup) engine_state live.endpoint_ws (if set)
xrpl_node.rpc_timeout_seconds XRPLNodeConfig.rpc_timeout_seconds config.py:352 Gateway request timeout per call gateway log field timeout_s on errors
xrpl_node.rpc_max_attempts XRPLNodeConfig.rpc_max_attempts config.py:353 Gateway retry loop in _request_with_retry gateway log attempt=N/max
xrpl_node.rpc_backoff_base XRPLNodeConfig.rpc_backoff_base config.py:354 Exponential backoff base (seconds) gateway log backoff_s

Trading pair

YAML key Config field Loader site Runtime consumer Observable metric Verified
pair.base_currency PairConfig.base_currency config.py:359 xrpl_gateway.get_book_offers takerPays fills row base_currency
pair.base_issuer PairConfig.base_issuer config.py:360 Gateway issuer field on orders orders row issuer
pair.quote_currency PairConfig.quote_currency config.py:361 Gateway takerGets when BUY fills row quote_currency

Engine

YAML key Config field Loader site Runtime consumer Observable metric Verified
engine.tick_interval_seconds EngineConfig.tick_interval_seconds config.py:367 Startup invariant check (must equal strategy.requote_interval_seconds) engine log requote_interval_seconds at startup ✓ (Branch #5 Commit 2)
engine.dry_run EngineConfig.dry_run config.py:368 Paper/live branching in _tick() and order submission engine_state config.dry_run
engine.db_path EngineConfig.db_path config.py:369 StateManager.__init__ startup log db_path

Spread

YAML key Config field Loader site Runtime consumer Observable metric Verified
spread.base_spread_pct SpreadConfig.base_spread_pct config.py:374 strategy_engine.py spread calc (tick) — combined with vol mult orders row intended_bid_offset_bps, intended_ask_offset_bps
spread.volatility_multiplier SpreadConfig.volatility_multiplier config.py:375 Multiplies vol into dynamic spread (tick) tick log dynamic_spread_bps
spread.min_spread_pct SpreadConfig.min_spread_pct config.py:376 Clamp floor on computed spread tick log spread_clamped_low
spread.max_spread_pct SpreadConfig.max_spread_pct config.py:377 Clamp ceiling on computed spread tick log spread_clamped_high

Order replacement

YAML key Config field Loader site Runtime consumer Observable metric Verified
order_replacement.drift_pct OrderReplacementConfig.drift_pct config.py:381 Replace-trigger in _should_replace_order (tick) replace-decision log drift_pct, drift_threshold
order_replacement.refresh_interval_seconds OrderReplacementConfig.refresh_interval_seconds config.py:382 Age-based replace in _should_replace_order (tick) replace-decision log age_s, refresh_interval_s

Order size

YAML key Config field Loader site Runtime consumer Observable metric Verified
order_size.base_size_rlusd OrderSizeConfig.base_size_rlusd config.py:386 Base size for every quote (tick) orders row intended_size_rlusd
order_size.min_size_rlusd OrderSizeConfig.min_size_rlusd config.py:387 Skew/scale clamp floor tick log size_clamped_low
order_size.max_size_rlusd OrderSizeConfig.max_size_rlusd config.py:388 Skew/scale clamp ceiling tick log size_clamped_high
order_size.inventory_scale_factor OrderSizeConfig.inventory_scale_factor config.py:389 Inventory-responsive size scaling tick log size_scale_inventory
order_size.max_size_pct_of_portfolio OrderSizeConfig.max_size_pct_of_portfolio config.py:390 Portfolio-relative size cap tick log size_clamped_portfolio_pct

Inventory

YAML key Config field Loader site Runtime consumer Observable metric Verified
inventory.target_xrp_pct InventoryConfig.target_xrp_pct config.py:394 Drift measurement in inventory_manager.get_snapshot() fills row drift_pct_at_fill, valuation_snapshots xrp_pct
inventory.skew_multiplier InventoryConfig.skew_multiplier config.py:395 Base drift→skew conversion in strategy tick log skew_bps

Risk

YAML key Config field Loader site Runtime consumer Observable metric Verified
risk.max_xrp_exposure RiskConfig.max_xrp_exposure config.py:399 main_loop.py:801 risk gate (tick); also startup invariant >0 engine_state halt.reason=risk_xrp_exposure when tripped ✓ (Branch #1 + #5 Commit 2)
risk.max_rlusd_exposure RiskConfig.max_rlusd_exposure config.py:400 main_loop.py:803 risk gate (tick); also startup invariant >0 engine_state halt.reason=risk_rlusd_exposure when tripped ✓ (Branch #1 + #5 Commit 2)
risk.volatility_lookback_candles RiskConfig.volatility_lookback_candles config.py:401 Vol history window size tick log vol_window_size
risk.connectivity_timeout_seconds RiskConfig.connectivity_timeout_seconds config.py:402 Gateway healthcheck cutoff alert log gateway_unhealthy_s

Fees

YAML key Config field Loader site Runtime consumer Observable metric Verified
fees.max_fee_drops FeeConfig.max_fee_drops config.py:406 Gateway submission cap tx submission log fee_drops
fees.fee_padding_multiplier FeeConfig.fee_padding_multiplier config.py:407 Safety pad over network-suggested fee tx submission log fee_padding

Strategy (RUNTIME CRITICAL)

YAML key Config field Loader site Runtime consumer Observable metric Verified
strategy.requote_interval_seconds StrategyConfig.requote_interval_seconds config.py:424 main_loop.run() sleep between ticks; startup invariant == engine.tick_interval_seconds startup log requote_interval_seconds ✓ (Branch #5 Commit 2)
strategy.anchor_mode StrategyConfig.anchor_mode config.py:425 Anchor selection in strategy_engine._select_anchor (tick) engine_state config.anchor_mode; tick log quote_anchor_source
strategy.anchor_max_divergence_bps StrategyConfig.anchor_max_divergence_bps config.py:426 Capped-AMM anchor clamp (tick) engine_state config.anchor_max_divergence_bps; tick log last_cap_applied ✓ (Branch #1)
strategy.clob_switch_threshold_bps StrategyConfig.clob_switch_threshold_bps config.py:427 Binary CLOB/anchor switch in strategy_engine.calculate_quote (tick); startup invariant >0 tick log reference_source=clob_mid_phase7_switch/amm ✓ (Branch #5 Commit 1)
strategy.spread_multiplier StrategyConfig.spread_multiplier config.py:428 Global spread mult in strategy (tick) tick log spread_multiplier
strategy.bid_spread_multiplier StrategyConfig.bid_spread_multiplier config.py:429 Per-side BID mult orders row intended_bid_offset_bps
strategy.ask_spread_multiplier StrategyConfig.ask_spread_multiplier config.py:430 Per-side ASK mult orders row intended_ask_offset_bps
strategy.bid_offset_bps StrategyConfig.bid_offset_bps config.py:437 strategy_engine.py:227 base BID offset orders row intended_bid_offset_bps
strategy.ask_offset_bps StrategyConfig.ask_offset_bps config.py:438 strategy_engine.py:228 base ASK offset orders row intended_ask_offset_bps
strategy.post_fill_markout_trigger_bps StrategyConfig.post_fill_markout_trigger_bps config.py:441 Toxic-fill cooldown trigger fills row toxic, tick log post_fill_pause
strategy.post_fill_pause_seconds StrategyConfig.post_fill_pause_seconds config.py:442 Cooldown duration tick log pause_until_ts
strategy.participation_filter_enabled StrategyConfig.participation_filter_enabled config.py:445 Phase 4A gate toggle tick log pf_suppressed counter

Accounting

YAML key Config field Loader site Runtime consumer Observable metric Verified
accounting.valuation_snapshot_interval_seconds AccountingConfig.valuation_snapshot_interval_seconds config.py:458 _maybe_write_valuation_snapshot cadence gate valuation_snapshots table row cadence

Recovery

YAML key Config field Loader site Runtime consumer Observable metric Verified
recovery.enabled RecoveryConfig.enabled config.py:463 Session-runner outer loop gate engine_state recovery.restart_count
recovery.restart_on_gateway_unhealthy RecoveryConfig.restart_on_gateway_unhealthy config.py:464 Session-runner gateway-health branch log recovery.reason=gateway_unhealthy
recovery.restart_delay_seconds RecoveryConfig.restart_delay_seconds config.py:465 Sleep between restarts log recovery.delay_s
recovery.max_restarts_per_session RecoveryConfig.max_restarts_per_session config.py:466 Cap the outer loop engine_state recovery.restart_count
recovery.require_preflight RecoveryConfig.require_preflight config.py:467 Block restart on preflight fail log recovery.preflight_ok

Paper

YAML key Config field Loader site Runtime consumer Observable metric Verified
paper.starting_balances.xrp PaperStartingBalancesConfig.xrp config.py:472 _seed_paper_inventory_if_needed (startup, fresh dry-run only) engine_state paper.starting_balance_xrp
paper.starting_balances.rlusd PaperStartingBalancesConfig.rlusd config.py:473 Same as above engine_state paper.starting_balance_rlusd

Alerts

YAML key Config field Loader site Runtime consumer Observable metric Verified
alerts.discord_webhook_url AlertsConfig.discord_webhook_url config.py:412 monitoring_alerts.send target alert send log webhook
alerts.alert_on_engine_failure AlertsConfig.alert_on_engine_failure config.py:413 Alert gate in run() exception handler alert log reason=engine_failure
alerts.alert_on_large_drift AlertsConfig.alert_on_large_drift config.py:414 Alert gate in drift watcher alert log reason=large_drift
alerts.no_fill_warning_minutes AlertsConfig.no_fill_warning_minutes config.py:415 No-fill watchdog threshold alert log no_fill_min
alerts.inventory_drift_warning_pct AlertsConfig.inventory_drift_warning_pct config.py:416 Drift alert threshold alert log drift_pct
alerts.max_submission_failures_before_critical AlertsConfig.max_submission_failures_before_critical config.py:417 Submission-failure escalation alert log submission_failures
alerts.max_stale_order_minutes AlertsConfig.max_stale_order_minutes config.py:418 Stale-order watchdog alert log stale_order_min

Out of scope for this pass

Parameters under parameters.* (ladder, skew buckets, refresh_jitter, spread_regimes, circuit_breakers) are tested in their own suite (test_parameters_v11_*). They're flipped via feature flags in StrategyConfig and are documented as knobs — flip-flag changes in behavior are visible in that coverage. Audit Item 1 for Phase 7.2/7.3 was the anchor/CLOB reference chain, which this table captures.

Notes

  • Loader line numbers reflect config.py as of this commit. They'll drift if the loader is rewritten; when that happens, refresh this table in the same branch.
  • The four invariants checked at startup (Branch #5 Commit 2) are marked "✓ (Branch #5 Commit 2)" above. Those four cross-checks are what make the wiring self-enforcing rather than merely documented.
  • Where a key appears in config.example.yaml but not config.yaml, the consumer path falls back to the dataclass default. All such paths were walked during the audit — none were found to produce divergent behavior between example and current.

— Orion