Skip to content

Kuru quoter

Kuru quoter is a single-venue vault market maker. It is the strategy to read if you want to see three things Dyson does nowhere else: a pure quoting kernel separated from its venue boundary, whole-book vault quoting, and state that survives a restart.

Shape

flowchart TD
    DB["MongoDB deployment<br/>actor with strategy_type = kuru-quoter"]
    N["NATS<br/>every configured feed"]
    K["Quote kernel<br/>pure, deterministic per instrument"]
    PL["Portfolio / risk planner<br/>QuoteSet → executable levels"]
    VB["Kuru venue runtime boundary"]
    V["Kuru vault<br/>complete quote set"]
    F["Kuru passive fills applied"]
    S["InfluxDB<br/>position-bias state + quote decisions"]

    DB --> K
    N --> K
    K --> PL --> VB --> V
    V --> F --> K
    K --> S

    classDef store fill:#2e7d32,stroke:#1b5e20,color:#fff
    classDef pure fill:#2e7d32,stroke:#1b5e20,color:#fff
    class DB,N,S store
    class K pure

The kernel is a deterministic pure actor for one Kuru instrument: given an input, it returns a QuoteSet. It reads no clock and touches no venue, so it is directly testable. The planner then converts that pure quote set into venue-independent executable levels, and only the venue boundary knows about Kuru.

Execution model

The quoter places complete vault quote sets rather than individual orders. Each decision replaces the whole owned book in one operation, which is the same model the Kuru leg of the multi-venue strategy uses.

Fills arrive as Kuru passive fills and are applied back into the kernel's view of position.

Persisted state

This is the one strategy that checkpoints its own learned state (strategies/kuru-quoter/src/state.rs):

Persisted Not persisted
Position-bias learner (PositionBiasState) Balances
Quote decisions, for Grafana and post-incident work Fill cursors
Open orders
Full restart reconciliation

PositionBiasState carries the learner's average_position, position_adjustment_bps, and the block of its last position update. Recovery matches on a stable state_scope shared across runs rather than on run_id, and revisions must increase — see State management for the store's guarantees.

Persistence is narrower than it sounds

Only the position-bias learner is checkpointed. Balances, fill cursors, open orders, and full restart reconciliation are not. A restart resumes a learned bias, not a trading position.

Quote decisions are stamped with decided_at_ns — when the decision was made, not when it was written. Persistence is asynchronous and can lag well behind the strategy, so stamping at write time would make a stale decision indistinguishable from a current one.

On startup the quoter creates the strategy_state and strategy_quote_decision measurements if they do not already exist.

Configuration

The deployment's native actor parameters must include the strategy-owned fields:

Field
strategy_type Must be kuru-quoter — how the binary finds its actor
base_asset, quote_asset The pair
bid_signal, ask_signal Signals driving each side
edge_bps_to_tvl_bps Edge scaling against vault TVL
prop_skew_entry, prop_skew_exit, prop_maintain Inventory skew behavior
rebate_in_bps Rebate assumption
max_position Hard inventory cap

Position-bias parameters may be nested under position_bias or kept as the legacy flat names.

Environment

MONGODB_URI            KURU_RPC_URL          KURU_ENTRY_POINT
MONGODB_DATABASE       KURU_WS_URL           KURU_VAULT
NATS_URL               KURU_L2_WS_URL (opt)  KURU_ORDERBOOK
PRIVATE_KEY

The live binary additionally requires INFLUX_HOST, INFLUX_DATABASE, KURU_QUANTITY_STEP, and KURU_MINIMUM_QUANTITY. INFLUX_TOKEN is optional against an unauthenticated server. Tick size comes from the native Kuru config when present, otherwise from KURU_PRICE_TICK.

Running it

cargo run -p dyson-kuru-quoter -- <deployment_id>

For local development:

docker compose up -d nats influxdb grafana
INFLUX_HOST=http://127.0.0.1:8181 INFLUX_DATABASE=dyson

Grafana is at http://127.0.0.1:3003 (admin / admin) with the Dyson InfluxDB datasource provisioned automatically.

Testnet execution test

cargo test -p dyson-kuru-quoter --test kuru_testnet -- --ignored

This places real orders

The test is ignored by default because it places actual Kuru testnet orders. Run it only with a testnet vault and testnet credentials. It cancels all working quotes during cleanup.