Files
cross-chain-pmm-lps/docs/14-phase0-knob-tuning.md
2026-03-02 12:14:07 -08:00

4.8 KiB
Raw Blame History

Phase 0 Knob Tuning Reference

Based on scorecard interpretation: which levers to pull first and what patterns confirm the right move. See 12-sim-scorecard.md for gates.


1. Hub-only: capture too high (PMM-heavy)

Signals: capture_mean near 1; churn < 1; intervention mostly inject.

First lever: Raise feeBps (not k). USD default: 25 → 3550 bps on public-routing pools.

Then if still high: k 0.10 → 0.15.

Success: capture_mean toward 1030%; churn similar or better; arb_volume_total and intervention_cost_total fall.


2. Full-quote: path concentration high + inject/withdraw by chain

Signals: Higher path_concentration_index; 56/137 show withdraw (mesh reflexivity).

First lever: Topology / controls: keep hub-only default; full-quote only where tolerable with maxTradeSizeUnits lower and/or publicRoutingEnabled=false on optional pools.

Second: Two-tier design: defense pool (tighter k, maybe no public routing) vs public_routing pool (looser k, higher fee). Deployment-status schema supports roles.

Success: path_concentration_index drops; drain_half_life improves; intervention more one-directional.


3. Bridge shock: peak deviation at circuit-break level

Signals: peak_deviation_bps_* ~1000+ bps (e.g. 1015).

First lever: Inventory / depth: increase inventoryTargetUnits on impacted chains by 1.52×; keep D₀ = 0.751.0 × I*.

Second: Bot speed: BOT_MAX_FRACTION_OF_TARGET 0.25 → 0.4 (e.g. shock-scenario override).

Third: Corridor: low-water 0.5 → 0.75, high-water 1.5 → 1.25.

Success: peak_deviation_bps_post_arb and _post_bot drop; intervention_cost rises but deviation stays under circuit-break.


4. “Capture high” vs background AMM

Background AMM is 5 bps + infinite depth. If PMM still dominates:

  • Option A: Raise PMM feeBps (recommended first).
  • Option B: Raise AMM fee to 2030 bps if modeling Uni-style; keep 5 bps only if modeling Curve-style stable rails (then PMM should be defense, not venue → higher PMM fee/k).

Quick checklist

Issue First move Then
Hub capture too high Done: default feeBps 35; chains 56/137 at 50 bps (sink chains); chain 1 at 35 k 0.10 → 0.15 if needed
Full-quote concentration high Disable/cap optional pools; hub-only default Role split: defense vs public_routing
Shock peak deviation too high Increase I* and D₀ on 1/56/137 Done: corridor 0.75/1.25, speed 0.40 in script


5. Deviation probe fix (marginal vs average)

Problem: With a finite probe (e.g. 500), implied price was an average over that size; the PMM curve always shows a discount at finite size, so peak_deviation_bps_* stayed high and arb churned volume.

Fix: Use analytical marginal for implied price: at x=0 the derivative is (1fee)·P, so pHat = (1 s.fee) * s.P. This avoids the (1k) bias from a finite sell probe (which gave ~1014 bps for EUR with k=0.2). At equilibrium, deviation = fee (e.g. 35 bps). DELTA_ARB_BPS is set to 40 so equilibrium doesnt trigger arb.

After fix: peak_deviation_* ≈ fee (e.g. 35 bps); arb_volume_total and intervention drop; worst_pool_diagnostic is no longer dominated by EUR.



6. Worst-pool diagnostic (scorecard)

When peak_deviation_bps_pre_arb ≈ post_arb ≈ post_bot, the worst pool may be rotating or not moving. The scorecard now includes (last epoch):

  • worst_pool_diagnostic: { pre_arb, post_arb, post_bot }, each { key, deviation_bps, I_T_ratio, D_effective }.

Interpretation:

  • Same pool worst all three phases + low I_T_ratio → depth problem (raise I*/D₀ or tighten corridor).
  • Same pool + I_T_ratio ≈ 1 → curve/fee or routing pressure (raise feeBps / k).
  • Rotating worst pool → routing re-creating deviation; fee/k/controls to reduce demand.

Diagnostic now includes oracle_P and p_hat: If you see p_hat ≈ 1.10 and oracle_P = 1.00 for EUR pools, the bug is EUR reference price (see §7).


7. EUR oracle reference (P for cWEUR* vs USDC)

Problem: EUR pools (cWEURC, cWEURT) were using P = 1 (USD) so deviation looked ~812% (8001200 bps) even at target inventory.

Fix: Oracle P in “quote per base” (USDC per cWEUR*):

  • USD-pegged: P = 1.0.
  • EUR-pegged vs USDC: P = EURUSD (e.g. 1.10).

Config: simulation-params.jsoneurUsd: 1.10 (USDC per 1 EUR). If missing, eurPegMultiplier is used; if that is 1.0, fallback 1.1 so EUR isnt treated as USD. Optional later: scenario.oracleModel.eurUsd to override per run.

After fix: EUR pools drop out of worst_pool_diagnostic; peak_deviation_bps falls; arb volume and intervention reflect true routing pressure.


Last updated from Phase 0 scorecard interpretation.