Per-wallet bet sizing already exists in pmv2 as pmv2_wallets.size_scale (a per-wallet global multiplier), so scaling crypto’s bet needs no crypto code and no new schema. CORRECTION (2026-07-06): an earlier version of this note claimed the executor “reads size_scale live” — that is WRONG. size_scale is captured once at position_manager boot and held as a static value for the process lifetime; a DB write does nothing until position_manager is restarted. Verified from code + a live DB experiment on 2026-07-06.
CORRECTION — size_scale is NOT hot-read (do not rely on a live DB write)
pmv2_wallets.size_scaleis loaded ONCE at position_manager boot and passed as a staticDecimalinto each wallet’s consumer task. That task runs for the whole process lifetime with the boot-time scale. Writingpmv2_wallets.size_scalein the DB has NO effect on the running executor until it is restarted.Where the earlier “reads live” claim came from:
size_scalesits in the samepmv2_walletstable asmode, and the sourcemodetoggle is hot-read per directive — so the note wrongly assumed the adjacent column behaves the same. The executor code paths differ:modeis re-read per directive;size_scaleis snapshotted at boot.
For Agents — binding facts (corrected)
pmv2_wallets.size_scale NUMERIC NOT NULL DEFAULT 1.0— a per-wallet GLOBAL size multiplier. It is loaded once at position_manager boot; a DB change requires a position_manager RESTART to take effect (NOT hot-read).- There is NO per-source scale.
pmv2_source_wallets(source_id,wallet_id) only maps sources → wallets; it carries no scale column. So sizing is per wallet, not per source/lane.- Scaling crypto’s bet = writing one DB column + a position_manager restart. No crypto code, no migration — but the DB write alone is a silent no-op on the running process. A command surface was requested as babylon
pmv2#1065 (and it MUST force a registry reload — see below).- CONTRAST: source
mode(off/dry_run/live, onpmv2_autotrade_sources) IS hot-read per directive — which is why toggling a lane’s mode takes effect live without a restart. Walletsize_scaleis the exception.- GOTCHA: a
size_scalebump must also be matched by that wallet’sdaily_spend_cap_usdor the cap silently clips the larger bets (the cap is a reject-gate, not a resizer).
Where it is boot-loaded (code)
In position_manager/crates/position_manager/src/bin/position-manager.rs:
main()builds ascale_by_walletHashMap (~line 204) from thepmv2_walletsrows.- It then spawns one consumer task per wallet, passing that wallet’s scale as a static
Decimal:consumer::run_wallet(pm, clob, client, wallet_id, scale)(~line 322). - That task runs for the process lifetime with the boot-time scale — it never re-reads
pmv2_wallets.size_scale.
So the value is frozen at process start. A DB update to pmv2_wallets.size_scale does nothing until position_manager is restarted.
Evidence — the 2026-07-06 live experiment
On 2026-07-06, @deploy set pmv2_wallets.size_scale from 1.0 → 2.0 for both wallets (DB confirmed at 2.0). But live fills were unchanged:
pmv2_autotrade_orderscontinued to showfilled_size = 10shares /size_usd ≈ $8.- If the
2.0had applied, fills would be ~20 shares / ~$16.
The running position_manager kept the boot-time 1.0. This is the direct confirmation that size_scale is boot-loaded, not hot-read — a restart is required to apply the new value.
The full sizing formula (two compounding levers)
For crypto’s Limit orders:
size_usd = limit_price × size_shares × size_scale
size_shares = ceil(min_size) × EMIT_SIZE_MULTIPLIER
With EMIT_SIZE_MULTIPLIER = 2 (our crypto emit env var) → size_shares = 10 shares currently. There are TWO size levers that compound, each with a different deploy requirement:
| Lever | Where it lives | To change it you must… |
|---|---|---|
EMIT_SIZE_MULTIPLIER | crypto emit env var (producer-side, per-trade size_shares) | redeploy the emit container |
pmv2_wallets.size_scale | pmv2 DB (PM-side, per-wallet global) | restart position_manager (boot-loaded — a DB write alone does nothing) |
limit_price is break-even-priced by emit (see crypto-shortterm-emit-guardrails / project CLAUDE.md observe::fire_limit), not a size lever you tune. The two size levers are EMIT_SIZE_MULTIPLIER and size_scale; both take effect only after their respective deploy step.
The schema (already exists)
position_manager/supabase/migrations/20260701000000_pmv2_wallets.sql gives each wallet, on pmv2_wallets:
| Column | Meaning |
|---|---|
size_scale NUMERIC NOT NULL DEFAULT 1.0 | per-wallet global bet-size multiplier — boot-loaded; a DB change needs a position_manager restart |
mode (off / dry_run / live) | per-wallet arm state (command-controlled, with a ledger) |
daily_spend_cap_usd | per-wallet daily spend reject-gate |
total_exposure_cap_usd | per-wallet total-exposure reject-gate |
pmv2_source_wallets (source_id, wallet_id) maps sources → wallets and has no scale column — confirming size_scale is the only sizing knob and it is per wallet, global.
No crypto code, no new schema (but not “just a command”)
“Per-wallet bet sizing for crypto” is a solved capability on the pmv2 side — the lever exists and crypto writes nothing. What’s missing is an operator-facing command to write it AND make the running executor pick it up: because size_scale is boot-loaded, a bare DB write is a silent no-op until restart.
How this composes with the producer-side lever
This is a PM-side, per-wallet, global multiplier — distinct from the producer-side, per-trade lever
size_sharesdocumented in crypto-shortterm-phase1-bet-sizing (which @positionmanager honors directly,pricing.rs).size_scale(migration dated 2026-07-01) scales on top of whateversize_sharesthe directive carries. Two multiplicative layers: producer sets per-tradesize_shares(viaEMIT_SIZE_MULTIPLIER, emit redeploy); PM multiplies by the wallet’ssize_scale(DB + position_manager restart).
The requested command (babylon pmv2 #1065)
Requested from @positionmanager as the sibling of the existing mode command:
- Writes
pmv2_wallets.size_scale. - Ledgered — same pattern as the mode command’s
mode_control_ledger(auditable history of who set what). - Clamped to
[0.5, 3]. - MUST force a reload — this is the binding requirement. Writing
pmv2_wallets.size_scalealone does nothing to the running executor (it captured the scale at boot). The command must EITHER (a) trigger a position_manager wallet-registry reload / restart, OR (b) be shipped alongside an executor change that re-readssize_scaleper order. Without one of these, the command writes the DB and the running process ignores it — the exact failure observed on 2026-07-06.
Gotcha: bump size_scale AND the daily cap together
daily_spend_cap_usd is a reject-GATE, not a resizer — it rejects orders that would breach the cap, it does not shrink them to fit (the exact mechanic established in crypto-shortterm-phase1-bet-sizing for the source-level cap). So a bigger size_scale burns a fixed daily cap faster → fewer fills, silently. Any size_scale bump must be paired with a matching daily_spend_cap_usd bump on that wallet, or the intended larger bets get clipped and you just get fewer trades at the old effective spend.
Use case: de-risk the ~2026-07-09 week-read 2× decision
Around 2026-07-09 there is a week-read decision on whether to double the bet. The per-wallet global size_scale turns that into a clean control experiment instead of an all-or-nothing flip:
- Set
wallet1.size_scale = 2.0and keepwallet2.size_scale = 1.0as the control. - Both wallets are crypto-dedicated and trade the same windows/sides (wallet1 =
0xAdAc17C0…aEb2“bandiboss”, wallet2 =0x7D39B0e5…8ee6“Balu” — see crypto-shortterm-pnl-onchain-cash-truth-2026-07-06). Because the scale is per-wallet global,wallet1.size_scale=2.0= 2× across ALL crypto lanes for wallet1, with wallet2 as a matched 1× baseline running identical signals. - Remember the two gotchas:
- The DB write requires a position_manager restart to take effect (boot-loaded — the 2026-07-06 experiment proved a bare write is ignored by the running process).
- Bump
wallet1.daily_spend_cap_usdto match the 2× or the doubled bets get cap-clipped and the A/B is confounded.
Related
- crypto-shortterm-phase1-bet-sizing — the producer-side sibling lever (
size_sharesviaEMIT_SIZE_MULTIPLIER, per-trade) + the “daily cap is a reject-GATE not a resizer” finding that is the exact reason the cap-clip gotcha bites. - crypto-shortterm-pnl-onchain-cash-truth-2026-07-06 — establishes both wallets are crypto-dedicated (wallet1 bandiboss / wallet2 Balu), the fact that makes a per-wallet global scale a clean 2× across all crypto.
- crypto-shortterm-emit-guardrails — the producer-side spend bound (
EMIT_MAX_FIRES) and break-evenlimit_price;size_scaleis the orthogonal PM-side per-wallet size lever. - crypto-shortterm-multi-asset-status-babylon-2026-07-02 — the babylon
pmv2hub where #1065 (the requested command) lives, and the lane lineup a 2× would scale. - crypto-shortterm — project index.