docs: Cubic→Linear translator fixes + Beads PASS tracker evaluation

- NEW_PINK_FORENSICS_DUAL_LEV_2026_SEARCH_RESULTS_SPEC.md:94 — 'cubic translator' → 'linear translator' (exchange mapping)
- VIOLET_STUDY_SPEC__BASE_FRACTION_SIZING.md:19 — 'cubic translator' → 'linear translator'
- VIOLET_V3_FINDINGS.md:51 — 'cubic translator' → 'linear translator'
- BEADS_PASS_TRACKER_EVALUATION.md: New evaluation recommending ADOPT for PASS tracking

Per Fable: exchange leverage mapping is LINEAR (round_half_even); cubic is conviction sizer only.
This commit is contained in:
Codex
2026-07-08 17:48:38 +02:00
parent 5607bfcc2c
commit 519565965e
4 changed files with 891 additions and 1 deletions

View File

@@ -0,0 +1,105 @@
# BEADS as PASS Tracker — Evaluation & Recommendation
**Author:** pi_nvnemo (UV Overseer)
**Date:** 2026-07-08
**Context:** UV_OVERSEER_CHARTER__PI.md §6 task — evaluate beads vs bus+doc for PASS board
---
## Current State
| Tracker | Status |
|---------|--------|
| **h5i bus** | Active — dispatch, ACK, status updates |
| **Status doc** | Not yet created (charter says "track PASSes on the bus + a short status doc") |
| **beads** | Installed, `.beads/` exists at repo root (prefix `dp`), 1 existing PRODGREEN issue |
---
## What Beads Gives Us Over Bus+Doc
| Capability | h5i Bus + Doc | Beads |
|------------|---------------|-------|
| **Dependency graph** | Manual (doc) | Native (`br dep add`, `br graph`) |
| **Task hierarchy** | Flat (doc sections) | Epic → child beads (parent/child) |
| **State machine** | Manual (doc) | Enforced (open → in_progress → closed) |
| **Acceptance criteria** | Doc prose | Structured fields (`acceptance_criteria`, `test_command`) |
| **Audit trail** | Bus history + doc edits | Immutable JSONL + SQL + `br audit` |
| **Handoff protocol** | Informal | Formal (`br audit --message`, `br ready`) |
| **Multi-agent isolation** | Bus channels | Separate workspace per refactor stream |
| **Low-skill agent onboarding** | Ad-hoc | Bounded task template + dependency chain |
| **Query/Filter** | grep/awk | `br ready`, `br list`, `br status`, SQL |
| **Backup/Sync** | Git + manual | `br sync`, `br backup` |
**Verdict:** Beads adds **structured task management** that the bus+doc lacks — critical for multi-PASS dependency chains (PASS-P → PASS-A → PASS-S → PASS-B/X).
---
## PASS → Bead Mapping
| PASS | Bead Type | Suggested ID | Parent |
|------|-----------|--------------|--------|
| **PASS-P** (Pulse Landing) | Epic | `UV_PASS-P` | — |
| ├─ Copy `prod/uv_pulse_host/` | Task | `UV_PASS-P.1` | `UV_PASS-P` |
| ├─ Add `.gitignore` (exclude `target/`) | Task | `UV_PASS-P.2` | `UV_PASS-P` |
| ├─ Cert conveyor commit | Task | `UV_PASS-P.3` | `UV_PASS-P` |
| ├─ Soak DARK + TUI heartbeat | Task | `UV_PASS-P.4` | `UV_PASS-P` |
| **PASS-A** (Account Region) | Epic | `UV_PASS-A` | — |
| ├─ Phase 0: Contracts + in-mem | Task | `UV_PASS-A.1` | `UV_PASS-A` |
| ├─ Phase 1: Real shm + hardened reader | Task | `UV_PASS-A.2` | `UV_PASS-A` |
| ├─ Phase 2: ASEx publish | Task | `UV_PASS-A.3` | `UV_PASS-A` |
| ├─ Phase 3: Capital provider | Task | `UV_PASS-A.4` | `UV_PASS-A` |
| **PASS-S** (Sizing Seam) | Epic | `UV_PASS-S` | — |
| **PASS-B** (Host Brain) | Epic | `UV_PASS-B` | — |
| **PASS-X** (Tick Exits) | Epic | `UV_PASS-X` | — |
**Dependency Chain:**
```
UV_PASS-P → UV_PASS-A → UV_PASS-S → UV_PASS-B → UV_PASS-X
```
---
## Smallest Viable Setup
```bash
# 1. Create dedicated UV workspace (isolate from PRODGREEN)
mkdir -p /mnt/dolphinng5_predict/uv/.beads
export BEADS_DIR=/mnt/dolphinng5_predict/uv/.beads
# 2. Initialize
br where # confirms workspace
# 3. Create PASS-P epic + children
br create --title "PASS-P: Pulse Landing" --type epic --id UV_PASS-P
br create --title "Copy prod/uv_pulse_host/ from /mnt/vp-PASS9" --parent UV_PASS-P --type task --acceptance "Directory copied, target/ excluded" --test "ls prod/uv_pulse_host/ && ! ls prod/uv_pulse_host/target/" --id UV_PASS-P.1
br create --title "Add .gitignore excluding target/" --parent UV_PASS-P --type task --acceptance "target/ ignored by git" --test "git check-ignore prod/uv_pulse_host/target/" --id UV_PASS-P.2
br create --title "Cert conveyor commit + integrator review" --parent UV_PASS-P --type task --acceptance "Commit on main, integrator signed" --test "git log --oneline -1 prod/uv_pulse_host/" --id UV_PASS-P.3
br create --title "Soak DARK + TUI heartbeat + STALE" --parent UV_PASS-P --type task --acceptance "TUI renders live rate/AGE/STALE, RSS flat ≥4h" --test "TUI smoke test + log review" --id UV_PASS-P.4
# 4. Link to bus for dispatch notifications
# (beads = source of truth; bus = real-time signal)
```
---
## Recommendation
**ADOPT BEADS for PASS tracking** with the following protocol:
1. **Beads = Source of Truth** — all PASS state, dependencies, acceptance criteria, audit trail
2. **h5i Bus = Real-time Signal** — dispatch, ACK, status pings, escalation (what we already do)
3. **Status Doc = Snapshot** — auto-generated from beads weekly or on demand (`br status > PASS_BOARD.md`)
**Migration Path:**
- Week 1: Create UV workspace, populate PASS-P + PASS-A epics/children
- Week 1: Run dual-track (beads + bus) — validate no drift
- Week 2: Deprecate manual status doc; auto-generate from `br status`
**Why not bus+doc alone?** The PASS chain has 5 epics with 15+ children, strict dependencies, and must survive agent rotation. Beads enforces what the charter demands: "keep a live board; chase stalls; escalate blocked specs."
---
## Next Action
If approved: I'll initialize `/mnt/dolphinng5_predict/uv/.beads`, populate PASS-P epic + children, and link dispatch messages to bead IDs.

View File

@@ -0,0 +1,659 @@
# PINK Forensics — Dual Leverage Architecture (2026 Search Results)
**Date:** 2026-07-06
**Agent:** pi_nvnemo
**Trigger:** Operator request — locate the authoritative dual-leverage spec
---
## Executive Summary
The DOLPHIN system implements a **strict dual-leverage architecture** separating two distinct leverage concepts that must NEVER be conflated:
| Layer | Name | Range | Purpose | Set By |
|-------|------|-------|---------|--------|
| **Internal** | **Conviction Leverage** (our_leverage) | 0.5 9.0 (fractional) | Sizes QUANTITY: `notional = capital × 0.20 × conviction`, `qty = notional / entry_price` | Strategy / sizer (`esf_alpha_orchestrator`, `AlphaBetSizer`) |
| **Venue** | **Exchange Leverage** (xlev) | 1 3 (integer) | Controls MARGIN: `margin = notional / exchange_lev` sent to BingX API | Venue boundary mapper (`prod/bingx/leverage.py`) |
**PnL is ALWAYS leverage-free**: `qty × Δprice` (side-signed). Exchange leverage only affects collateral lockup.
---
## Authoritative Source Files (Bit-Identity Required)
### 1. `prod/bingx/leverage.py` — **THE SINGLE SOURCE OF TRUTH** (83 lines, no callers)
```python
CONVICTION_MIN = 0.5
CONVICTION_MAX = 9.0
EXCHANGE_LEV_MIN = 1
EXCHANGE_LEV_MAX = 3
LEVERAGE_MAPPING_RULE = "round_half_even_linear_0.5_to_9.0_to_1_to_exchange_cap"
def map_internal_conviction_to_exchange_leverage_target(internal, *, exchange_min, exchange_max) -> float:
# clamp internal to [0.5, 9.0]
# linear: exchange_min + (internal - 0.5)/(9.0 - 0.5) * (exchange_max - exchange_min)
# returns FLOAT target (pre-round)
def normalize_bingx_leverage_value(leverage, *, exchange_min, exchange_max) -> int:
# ROUND_HALF_EVEN (banker's: 1.5→2, 2.5→2, 3.5→4) + clamp to [exchange_min, exchange_max]
def map_internal_conviction_to_exchange_leverage(internal, *, exchange_min, exchange_max) -> int:
# = normalize_bingx_leverage_value(map_..._target(internal), ...)
# FINAL integer sent to BingX API
```
### 2. `prod/clean_arch/runtime/pink_direct.py:_hz_publish()` (line ~909)
```python
def _hz_publish(self, slot_dict: dict, acc: dict) -> None:
"""Fire-and-forget Hz write after any kernel state change.
Computes system leverage (our_leverage = notional/capital) for the Hz
snapshot — PINK/BLUE dual-leverage invariant: system leverage reflects real
margin utilisation; exchange leverage (1-3x cap) is set at BingX API level.
"""
size = float(slot_dict.get("size") or 0.0)
ep = float(slot_dict.get("entry_price") or 0.0)
capital = float(acc.get("capital") or 0.0)
our_leverage = (size * ep / capital) if capital > 1e-10 else 0.0
self.hz_state_writer.write_engine_snapshot(
slot_dict, acc,
posture=self._last_posture,
our_leverage=our_leverage, # <-- CONVICTION leverage published to Hz
scan_number=self._last_scan_number,
vel_div=self._last_vel_div,
vol_ok=self._last_vol_ok,
)
```
---
## Spec Documents (Chronological)
### A. `prod/docs/FRACTIONAL_LEVERAGE_TO_BINGX_FIX.md` (2025-04-24)
**Origin story** — CRITICAL bug: exchange leverage was hardcoded to 1x, ignoring per-trade fractional leverage.
- "The system correctly separates leverage into two roles"
- Fractional leverage → affects quantity (how many contracts)
- Exchange leverage → affects margin (how much collateral)
- Fix: CEIL rounding for exchange leverage (`ceil(fractional_lev)` clamped to [1,9])
### B. `prod/docs/PINK_ACCOUNTING_EXEC_FIX.md` (2026-06-11)
**Forensic incident** — FET short settled at +$164 but kernel booked $5,990.90.
**HARD INVARIANT (§0):**
> **Dual leverage**: `slot.size` = exchange quantity; `slot.leverage` = exchange leverage (13x cap, set at BingX API); *our*-leverage (conviction) = `size × entry_price / capital`, computed **only** at `pink_direct._hz_publish` (line ~911). PnL is therefore **leverage-free**: `qty × Δprice`, side-signed. Do not touch the conviction→exchange mapping (`round_half_even_linear_0.5_to_9.0_to_1_to_exchange_cap`) or `target_size` computation.
### C. `prod/docs/VIOLET_SUB_SPEC__L3_EXCHANGE_LEVERAGE.md` (2026-06-15)
**VIOLET L3 wrapper spec** — "WRAP, DON'T REIMPLEMENT"
- V-TYPES boundary: `ConvictionLeverage` (Annotated float) → `ExchangeLeverage` (Annotated int ≥1)
- `VioletExchangeLeverage` class wraps `prod/bingx/leverage.py` functions exactly
- Gate: MC bit-identity @ N≥1e6 vs real `leverage.py` output
- Zero shared-file edits; bit-identity is the contract
### D. `prod/docs/VIOLET_V3_FINDINGS.md` §2 (2026-06-15)
> **DUAL-LEVERAGE:** conviction leverage sizes the QUANTITY (internal); exchange leverage mapped at venue boundary via `prod/bingx/leverage.py` `map_internal_conviction_to_exchange_leverage_target` (round_half_even linear 0.59.0 → 1..cap; PINK/VIOLET use max-3× **linear** translator).
### E. `prod/docs/PRODGREEN_TUI_AND_LEVERAGE_OBSERVABILITY_SPEC.md` (2026)
**TUI display labels:**
- `cm:` for conviction multiplier
- `xlev:` for exchange leverage
- `lev:` legacy (visually secondary)
---
## Key Terms / Vocabulary
| Term | Meaning | Where Defined |
|------|---------|---------------|
| `conviction leverage` / `our_leverage` | Internal fractional [0.5, 9.0], sizes quantity | `pink_direct.py:_hz_publish` |
| `exchange leverage` / `xlev` | Integer [1,3] sent to BingX API | `leverage.py`, `pink_direct.py` |
| `dual-leverage doctrine` | The separation principle | `PINK_ACCOUNTING_EXEC_FIX.md` §0 |
| `round_half_even` | Banker's rounding (x.5 → even) | `leverage.py`, `VIOLET_SUB_SPEC__L3` |
| `map_internal_conviction_to_exchange_leverage` | The mapper function | `leverage.py` |
| `target_exchange_leverage` | Float pre-round value | `VIOLET_SUB_SPEC__L3` |
| `exchange_leverage` | Final int sent to venue | `VIOLET_SUB_SPEC__L3` |
| `notional` | `capital × 0.20 × conviction` | `esf_alpha_orchestrator.py` |
| `base_fraction` | 0.20 (constant in BLUE) | `VIOLET_V3_FINDINGS.md` §2 |
---
## Execution Flow (PINK → BingX)
```
1. BLUE/VIOLET sizer computes conviction ∈ [0.5, 9.0]
2. notional = capital × 0.20 × conviction
3. quantity = notional / entry_price
4. At venue boundary (pink_direct / execution.py):
target = map_internal_conviction_to_exchange_leverage_target(conviction) # float
xlev = normalize_bingx_leverage_value(target) # int [1,3]
5. BingX API: POST /leverage {"symbol": "...", "side": "BOTH", "leverage": xlev}
6. Margin locked = notional / xlev
7. PnL calculation: qty × (exit_price - entry_price) [NO leverage factor]
8. Hz snapshot publishes: our_leverage = (size × entry_price) / capital
```
---
## VIOLET Integration Points
| Component | Role | File |
|-----------|------|------|
| `VioletExchangeLeverage` | V-TYPES wrapper, bit-identity gated | `prod/clean_arch/violet/exchange_leverage.py` |
| `TradeabilityProjection` | L1→L3 projector (conviction → xlev + margin) | `prod/clean_arch/violet/tradeability.py` (Task 6) |
| `ShadowDecision` | L1 output carrying `conviction_leverage` | `decision_engine.py` |
---
## Mutation Litmus (What Breaks If Conflated)
| Mutation | Expected Test Failure |
|----------|----------------------|
| Use `exchange_leverage` in PnL calc | `test_pink_ditav2_accounting_invariants.py` — realized PnL 3× inflated |
| Use `conviction` as BingX leverage | Margin rejection or over-leverage (BingX max 3× for PINK) |
| Round-half-up instead of half-even | `VIOLET_SUB_SPEC__L3` gate: 2.5→3 instead of 2, bit-identity fails |
| Drop the clamp to [1,3] | BingX API rejects leverage >3 for PINK symbols |
---
## Related Files to Audit (Per Search)
- `prod/clean_arch/runtime/pink_direct.py``_hz_publish`, `_exec_submit`, intent leverage flow
- `prod/bingx/execution.py``_ensure_leverage`, `_normalize_bingx_leverage_value` (legacy CEIL, not ROUND_HALF_EVEN)
- `prod/clean_arch/violet/exchange_leverage.py` — VIOLET L3 wrapper
- `prod/clean_arch/violet/tradeability.py` — L3 projector (if built)
- `esf_alpha_orchestrator.py` — 5-factor conviction composition (base × DC × ACB × OB × EsoF)
- `alpha_wrappers.py` — VIOLET V-TYPES for `ConvictionLeverage`
- `prod/tests/test_pink_ditav2_accounting_invariants.py` — Accounting tests
- `prod/tests/test_violet_exchange_leverage.py` — VIOLET L3 gate tests
---
## Operator Directives (Binding)
1. **NEVER reimplement `leverage.py` logic** — wrap it (VIOLET L3 spec, non-negotiable)
2. **PnL is leverage-free**`qty × Δprice` only (PINK_ACCOUNTING_EXEC_FIX.md HARD INVARIANT)
3. **Bit-identity gate** — VIOLET output must `==` `prod/bingx/leverage.py` output exactly (MC N≥1e6)
4. **ROUND_HALF_EVEN** — not round-half-up, not CEIL, not floor (banker's rounding)
5. **Conviction sizes qty; exchange lev sizes margin** — the two paths are orthogonal after notional
---
## Search Provenance
Found via: `grep -r "dual.leverage\|our.*leverage.*exchange\|conviction.*multiplier\|map_internal_conviction_to_exchange" /mnt/dolphinng5_predict/prod/docs --include="*.md"`
Key hits: `PINK_ACCOUNTING_EXEC_FIX.md`, `VIOLET_SUB_SPEC__L3_EXCHANGE_LEVERAGE.md`, `FRACTIONAL_LEVERAGE_TO_BINGX_FIX.md`, `VIOLET_V3_FINDINGS.md`, `PRODGREEN_TUI_AND_LEVERAGE_OBSERVABILITY_SPEC.md`, `INDEX_REVIEW_alpha_engine.md`, `UV_TASK_T19_UV_CLOCK_HOST.md`
---
## Next Search Vectors (Operator Guidance)
- Search `esf_alpha_orchestrator.py` for 5-factor conviction composition
- Search `alpha_wrappers.py` for V-TYPES `ConvictionLeverage` definition
- Search `prod/bingx/execution.py` for legacy CEIL vs ROUND_HALF_EVEN divergence
- Trace `dolphin_actor.py` tag `lev:X.XX` → execution path
---
## Additional Findings (Extended Search)
### 1. `prod/bingx/sizing_mode.py` — Sizing Mode Contract
- Three modes: `engine` (default, no BingX payload), `testnet`, `live_market`
- `build_split_sizing_payload()` emits BingX-ready sizing with `exchange_leverage_cap`
- Delegates to `prod.utils.trade_sizing_bridge.build_engine_ready_sizing()`
### 2. `prod/utils/trade_sizing_bridge.py` — Engine-Ready Sizing Translation
**Core function:** `size_trade_from_sizing_lev()` — the complete translation pipeline:
```python
# Input: sizing_lev (conviction), capital, mark_price, etc.
# Output: TradeSizingResult with:
# - internal_leverage: cubic-convex conviction ∈ [0.5, 9.0]
# - exchange_leverage_target: float (pre-round, linear map)
# - exchange_leverage: int (ROUND_HALF_EVEN + clamp to [1, exchange_cap])
# - effective_notional: min(venue_cap, margin_budget × exchange_leverage)
# - quantity: floor(effective_notional / mark_price / step_size) × step_size
# - margin_to_capital, notional_to_capital ratios
```
**Key constants:**
- `DEFAULT_BINGX_EXCHANGE_LEVERAGE_CAP = 3`
- `DEFAULT_MIN_INTERNAL_LEVERAGE = 0.5`
- `DEFAULT_MAX_INTERNAL_LEVERAGE = 9.0`
- `DEFAULT_LEVERAGE_CONVEXITY = 3.0` (cubic!)
- `DEFAULT_MARGIN_BUDGET_FRACTION = 0.20`
**Convexity note:** The "cubic" in "max-3× cubic translator" refers to the **conviction sizing curve** (`strength_cubic = clamp(...)³`), NOT the exchange leverage mapping. The exchange mapping is **linear** with **ROUND_HALF_EVEN**.
### 3. `prod/clean_arch/adapters/bingx_direct.py` — DITAv2 Venue Adapter
- Uses `map_internal_conviction_to_exchange_leverage()` from `prod.bingx.leverage`
- Default `exchange_leverage_cap = 3`
- Applies leverage per-symbol via cache `_configured_leverage`
### 4. `prod/clean_arch/dita_v2/blue_parity.py` — BLUE Parity Wrapper
**DUAL-LEVERAGE INVARIANT (docstring):**
> "the fractional leverage produced here is STRATEGY conviction — it sizes the quantity. At-exchange leverage is derived from it at the venue boundary via map_internal_conviction_to_exchange_leverage() (linear [0.5, 9.0] → [1, cap], bankers rounding, security cap)."
### 5. `prod/clean_arch/dita_v2/test_blue_parity.py` — Parity Tests
**TestConvictionToExchangeLeverage class validates:**
```python
m(0.5) == 1 # conviction floor → exchange floor
m(9.0) == 3 # conviction ceiling → exchange cap (3)
m(4.75) == 2 # exact midpoint [0.5, 9.0] → target 2.0 → round_half_even(2.0) = 2
m(0.1) == 1 # clamped below conviction floor
m(50.0) == 3 # clamped above conviction ceiling
# monotonic: {1, 2, 3} across conviction range
```
### 6. `prod/docs/NAUTILUS_DOLPHIN_SPEC.md` — Sizing Formula
```
leverage = min_leverage + (max_leverage - min_leverage) × (signal_strength)^leverage_convexity
# leverage_convexity = 3.0 → CUBIC
strength_cubic = clamp((threshold - vel_div) / (threshold - extreme), 0, 1) ** 3
```
### 7. `prod/docs/SYSTEM_BIBLE_v7.md` §38.5 (margin-sizing addendum)
> "internal sizing leverage and BingX exchange leverage are separate layers. Exchange leverage controls the required margin; strategy leverage controls sizing intent."
---
## Complete Leverage Flow (End-to-End)
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ BLUE STRATEGY (esf_alpha_orchestrator) │
│ signal_strength = clamp((|vel_div| - threshold) / (extreme - threshold)) │
│ strength_cubic = signal_strength ** 3.0 ← CUBIC CONVEXITY │
│ raw_leverage = base × DC_boost × ACB_regime × OB_consensus × EsoF_haircut │
│ clamped to [0.5, 9.0] │
└──────────────────────────────────┬──────────────────────────────────────────┘
│ conviction ∈ [0.5, 9.0]
┌─────────────────────────────────────────────────────────────────────────────┐
│ PINK / VIOLET VENUE BOUNDARY │
│ target = map_internal_conviction_to_exchange_leverage_target(conviction) │
│ = 1.0 + (conviction - 0.5) / 8.5 × (3.0 - 1.0) ← LINEAR │
│ ∈ [1.0, 3.0] (float) │
│ xlev = normalize_bingx_leverage_value(target) │
│ = ROUND_HALF_EVEN(target) clamped to [1, 3] ← BANKER'S ROUNDING │
│ ∈ {1, 2, 3} (int) │
└──────────────────────────────────┬──────────────────────────────────────────┘
│ exchange_leverage ∈ {1, 2, 3}
┌─────────────────────────────────────────────────────────────────────────────┐
│ BINGX EXECUTION │
│ POST /trade/leverage {"symbol": "...", "side": "BOTH", "leverage": xlev} │
│ margin = notional / xlev │
└──────────────────────────────────┬──────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ ACCOUNTING (PnL) │
│ qty = notional / entry_price │
│ PnL = qty × (exit_price - entry_price) ← LEVERAGE-FREE │
│ our_leverage = (size × entry_price) / capital ← PUBLISHED TO Hz │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## Critical Distinction: CEIL vs ROUND_HALF_EVEN
| Context | Rounding | Source |
|---------|----------|--------|
| **Old execution.py fix (2025-04-24)** | `ceil(fractional_lev)` | `FRACTIONAL_LEVERAGE_TO_BINGX_FIX.md` |
| **Current production `leverage.py`** | `ROUND_HALF_EVEN` (banker's) | `prod/bingx/leverage.py` |
| **VIOLET L3 wrapper** | `ROUND_HALF_EVEN` (bit-identical gate) | `VIOLET_SUB_SPEC__L3_EXCHANGE_LEVERAGE.md` |
**The CEIL fix was superseded** by the cleaner `leverage.py` module with banker's rounding. The production code now uses `prod/bingx/leverage.py` exclusively.
---
## ROUND_HALF_EVEN Boundary Cases (Tested)
| Conviction | Target (float) | ROUND_HALF_EVEN | Final xlev |
|------------|----------------|-----------------|------------|
| 0.5 | 1.0 | 1 | 1 |
| ~2.82 | 1.5 | 2 | 2 |
| 4.75 | 2.0 | 2 | 2 |
| ~6.68 | 2.5 | 2 | 2 ← BANKER'S: 2.5 → 2 |
| 9.0 | 3.0 | 3 | 3 |
The "max-3× cubic translator" phrase in VIOLET docs refers to:
- **Cubic** = conviction sizing curve (strength³)
- **3×** = exchange leverage cap (13)
- **Translator** = the linear + ROUND_HALF_EVEN mapper
---
## Source Code Inventory (All Leverage-Related)
| File | Role |
|------|------|
| `prod/bingx/leverage.py` | **SOURCE OF TRUTH** — pure functions, 83 lines, no callers |
| `prod/bingx/config.py` | `exchange_leverage_cap: PositiveInt = 3` default |
| `prod/bingx/execution.py` | Venue client, wraps leverage.py functions |
| `prod/bingx/sizing_mode.py` | Sizing mode contract (engine/testnet/live) |
| `prod/utils/trade_sizing_bridge.py` | Full sizing pipeline with margin math |
| `prod/clean_arch/adapters/bingx_direct.py` | DITAv2 venue adapter |
| `prod/clean_arch/dita_v2/blue_parity.py` | BLUE parity wrapper (docstrings the invariant) |
| `prod/clean_arch/dita_v2/test_blue_parity.py` | Parity tests including dual-leverage |
| `prod/clean_arch/runtime/pink_direct.py` | PINK runtime, `_hz_publish` computes `our_leverage` |
| `prod/clean_arch/violet/exchange_leverage.py` | VIOLET L3 typed wrapper (bit-identity gated) |
| `prod/clean_arch/violet/test_violet_exchange_leverage.py` | VIOLET L3 gate tests (N≥1e6 MC) |
| `prod/clean_arch/violet/exec_intent.py` | VIOLET PASS4 DARK intent projection |
---
## Mutation Litmus (What Breaks If Wrong)
| Mutation | Test That Catches It |
|----------|---------------------|
| Use `exchange_leverage` in PnL formula | `test_pink_ditav2_accounting_invariants.py` |
| Use `conviction` directly as BingX leverage | Margin rejection (BingX max 3× for PINK) |
| ROUND_HALF_UP instead of ROUND_HALF_EVEN | `test_violet_exchange_leverage.py::test_round_half_even_boundary_cases` (2.5→3 fails) |
| Drop clamp to [1,3] | BingX API rejects leverage >3 |
| Conflate the two leverage concepts | `PINK_ACCOUNTING_EXEC_FIX.md` HARD INVARIANT violation |
---
## Search Provenance (Complete)
```
# Primary searches
grep -r "dual.leverage\|map_internal_conviction_to_exchange" prod/docs --include="*.md"
grep -r "CONVICTION_MIN\|EXCHANGE_LEV_MAX\|LEVERAGE_MAPPING_RULE" prod --include="*.py"
grep -r "round_half_even\|ROUND_HALF_EVEN" prod --include="*.py"
grep -r "exchange_leverage_cap" prod --include="*.py"
# Key files examined
prod/bingx/leverage.py ← SOURCE OF TRUTH
prod/bingx/config.py ← Default cap = 3
prod/bingx/execution.py ← Venue client
prod/bingx/sizing_mode.py ← Mode contract
prod/utils/trade_sizing_bridge.py ← Full pipeline
prod/clean_arch/adapters/bingx_direct.py ← DITAv2 adapter
prod/clean_arch/dita_v2/blue_parity.py ← BLUE parity + invariant docstring
prod/clean_arch/dita_v2/test_blue_parity.py ← Parity tests
prod/clean_arch/runtime/pink_direct.py ← PINK runtime, _hz_publish
prod/clean_arch/violet/exchange_leverage.py ← VIOLET L3 wrapper
prod/clean_arch/violet/test_violet_exchange_leverage.py ← VIOLET gate tests
prod/clean_arch/violet/exec_intent.py ← VIOLET PASS4 intent
# Spec docs
prod/docs/FRACTIONAL_LEVERAGE_TO_BINGX_FIX.md ← Origin story (CEIL fix)
prod/docs/PINK_ACCOUNTING_EXEC_FIX.md ← Forensic HARD INVARIANT
prod/docs/VIOLET_SUB_SPEC__L3_EXCHANGE_LEVERAGE.md ← VIOLET L3 spec
prod/docs/VIOLET_V3_FINDINGS.md ← V3 findings
prod/docs/BINGX_MARGIN_SIZING_RULE.md ← Operational rule
prod/docs/SYSTEM_BIBLE_v7.md ← §38.5 margin-sizing addendum
prod/docs/NAUTILUS_DOLPHIN_SPEC.md ← Cubic sizing formula
```
---
## CRITICAL CORRECTION: Actual PINK Runtime Was DITA v1 (NOT DITAv2)
**The running PINK system that traded on BingX VST used `prod/clean_arch/dita/` (DITA v1), NOT `prod/clean_arch/dita_v2/`.**
DITAv2 (`prod/clean_arch/dita_v2/`) was a later rewrite that preserved the same dual-leverage invariant but was NOT the system that ran live.
### Actual Running PINK Stack (DITA v1)
| Layer | File | Role |
|-------|------|------|
| **Launcher** | `prod/launch_dolphin_pink.py` (baseline in `prod/refactor_snapshots_20260527_222130/`) | Wired DITA v1 + BingX direct adapter |
| **Decision** | `prod/clean_arch/dita/decision.py` | `DecisionEngine` — computes `leverage` (conviction) + `our_leverage` (notional/capital) |
| **Intent** | `prod/clean_arch/dita/intent.py` | `IntentEngine` — passes `leverage` from decision to `Intent` |
| **Trade FSM** | `prod/clean_arch/dita/trade.py` | `TradeExecutor``TradePosition.leverage` = conviction from intent |
| **Account** | `prod/clean_arch/dita/account.py` | `AccountProjection``snapshot.leverage` = `open_notional / capital` (**our_leverage**) |
| **Venue Adapter** | `prod/clean_arch/adapters/bingx_direct.py` | `submit_intent()`**dual-leverage translation happens HERE** |
| **TP Curve** | `prod/clean_arch/tp_curve.py` | `compute_our_leverage(notional, capital)` — used for TP tightening |
### Dual-Leverage Translation in Production Code
**`prod/clean_arch/adapters/bingx_direct.py:submit_intent()` (lines 599-606):**
```python
# intent.leverage is the STRATEGY conviction (fractional, 0.59.0) and
# already sized the quantity. At-exchange leverage is derived from it
# via the linear conviction map → integer [1, cap], bankers rounding.
leverage = map_internal_conviction_to_exchange_leverage(
float(intent.leverage or self._config.default_leverage),
exchange_max=self._config.exchange_leverage_cap, # = 3
)
await self._ensure_leverage(symbol, leverage) # POST to BingX /trade/leverage
```
**`prod/clean_arch/tp_curve.py`:**
```python
def compute_our_leverage(*, notional, capital) -> float:
"""Return the current system leverage implied by sizing, NOT exchange leverage."""
return abs(notional) / capital # our_leverage = notional/capital
```
**`prod/clean_arch/dita/decision.py`:**
```python
our_leverage = compute_our_leverage(notional=target_exposure, capital=context.capital)
# ... passed in Decision.metadata["our_leverage"] for TP curve
tp_effective_pct = compute_soft_tp_pct(tp_base_pct, our_leverage)
```
### Three Leverage Concepts in the Live System
| Name | Variable | Range | Computed Where | Purpose |
|------|----------|-------|----------------|---------|
| **Conviction** | `intent.leverage`, `Decision.leverage` | 0.59.0 | Sizer (cubic-convex) | Sizes QUANTITY |
| **Exchange** | `leverage` (BingX API) | 13 (int) | `map_internal_conviction_to_exchange_leverage()` | Controls MARGIN = notional/exchange_lev |
| **Our/System** | `our_leverage` | 0.0~1.8 | `compute_our_leverage(notional, capital)` | TP curve tightening, Hz publishing |
### DITAv2 Migration Note
`prod/clean_arch/dita_v2/` was a **later rewrite** that re-implemented the same architecture with a Rust kernel (`ExecutionKernel`). It preserved the dual-leverage invariant (documented in `PINK_ACCOUNTING_EXEC_FIX.md` §0 and `blue_parity.py` docstring) but the live PINK system that actually traded used **DITA v1**.
### Files That Were Actually Running Live
- `prod/launch_dolphin_pink.py` (the launcher)
- `prod/clean_arch/runtime/pink_direct.py` (the runtime — uses DITA v1 components)
- `prod/clean_arch/dita/` (decision, intent, trade, account)
- `prod/clean_arch/adapters/bingx_direct.py` (venue adapter with dual-leverage translation)
- `prod/clean_arch/tp_curve.py` (leverage-conditioned TP)
---
## VIOLET Contracts — Dual-Leverage in Data Types
### `prod/clean_arch/violet/alpha_wrappers.py` — `SizeDecision` (PASS3a)
```python
class SizeDecision(StrictModel):
"""Bet-sizer output. notional_fraction = fraction * conviction_leverage
is the realized notional/capital (== the recorded our_leverage); it is
the conviction side of the dual-leverage and is exchange-agnostic."""
fraction: Fraction
conviction_leverage: ConvictionLeverage # ∈ [0.5, 9.0] — internal sizing
notional_fraction: float = Field(ge=0.0) # == our_leverage = fraction × conviction_leverage
bucket_idx: int
strength_score: float
signal_bucket: str
```
**Key invariant:** `notional_fraction = fraction × conviction_leverage` — this IS the recorded `our_leverage` (system leverage = notional/capital).
### `prod/clean_arch/violet/decision_engine.py` — `ShadowDecision` (PASS3c)
```python
class ShadowDecision(StrictModel):
"""One muted decision — what BLUE *would* do this scan. Never executed."""
ts_ns: int
scan_number: int
asset: Symbol
side: str
vel_div: float
fraction: float # base_fraction (0.20)
conviction_leverage: float # ∈ [0.5, 9.0] — full BLUE conviction (5-factor)
notional_fraction: float # == our_leverage = fraction × conviction_leverage
target_exposure: float # = capital × notional_fraction
ars_score: float
bucket_idx: int
actuated: bool
# 5-factor breakdown (V3.4):
base_leverage: Optional[float] # base cubic from AlphaBetSizer
dc_lev_mult: Optional[float] # DC confirmation boost
regime_size_mult: Optional[float] # ACB boost × meta × MC_scale (the "steepener")
market_ob_mult: Optional[float] # OB consensus 0.851.20
esof_size_mult: Optional[float] # EsoF haircut [0, 1]
```
**Key points:**
- `conviction_leverage` = full 5-factor BLUE conviction (base × DC × ACB-regime × OB × EsoF)
- `notional_fraction` = `fraction × conviction_leverage` = `our_leverage` (system leverage)
- `target_exposure` = `capital × notional_fraction` = notional
- Exchange leverage is **L3 only** — never in L1 decision
### `prod/clean_arch/violet/contracts_v3.py` — `ExecIntent` (PASS4)
```python
class ExecIntent(StrictModel):
"""DARK would-be order intent. Data only; never sent to a venue here."""
asset: Symbol
side: Literal["SHORT", "LONG"]
qty: Qty
exchange_leverage: Annotated[int, Field(ge=1)] # ← L3: exchange leverage
maker_policy: str
target_notional: float
ts_ns: MonoNs
reason: Literal["ENTRY", "EXIT"]
```
### `prod/clean_arch/violet/exec_intent.py` — L1→L3 Projection (PASS4 Task 17)
```python
def to_exec_intent(
decision: ShadowDecision,
*,
capital: float,
reference_price: float,
maker_policy: str = "maker_both",
) -> ExecIntent:
# target_notional = capital × notional_fraction (our_leverage side)
target_notional = capital * decision.notional_fraction
qty = target_notional / reference_price
# L3: conviction → exchange leverage via prod/bingx/leverage.py
exchange = _exchange_leverage_for(decision.conviction_leverage)
return ExecIntent(
asset=decision.asset,
side=decision.side,
qty=qty,
exchange_leverage=exchange,
maker_policy=maker_policy,
target_notional=target_notional,
ts_ns=decision.ts_ns,
reason="ENTRY",
)
def _exchange_leverage_for(conviction_leverage: float) -> int:
# Wraps VioletExchangeLeverage (bit-identical to prod/bingx/leverage.py)
return VioletExchangeLeverage().to_exchange(conviction_leverage).exchange_leverage
```
---
## Complete Dual-Leverage Architecture Across All Systems
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ BLUE (nautilus_event_trader.py) │
│ esf_alpha_orchestrator: 5-factor conviction (base × DC × ACB-regime × OB × EsoF)│
│ our_leverage = compute_our_leverage(notional, capital) # for TP curve │
│ target_notional = capital × 0.20 × conviction_leverage │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ PINK │ │ PRODGREEN │ │ VIOLET │
│ (DITA v1 live) │ │ (BLUE mirror) │ │ (shadow/UV) │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
┌──────────┴──────────┐ │ ┌──────────┴──────────┐
▼ ▼ ▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ decision.py │ │ decision.py │ │ alpha_wrap │ │decision_eng │
│ DecisionEng │ │ DecisionEng │ │ SizeDecision│ │ ShadowDec │
│ leverage= │ │ leverage= │ │ conviction_ │ │conviction_ │
│ conviction │ │ conviction │ │ leverage │ │leverage │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ VENUE BOUNDARY (dual-leverage translation) │
│ │
│ PINK: prod/clean_arch/adapters/bingx_direct.py:submit_intent() │
│ leverage = map_internal_conviction_to_exchange_leverage( │
│ intent.leverage, exchange_max=3) │
│ │
│ VIOLET: prod/clean_arch/violet/exec_intent.py:to_exec_intent() │
│ exchange = VioletExchangeLeverage().to_exchange( │
│ decision.conviction_leverage).exchange_leverage │
│ │
│ BLUE: prod/bingx/execution.py:_ensure_leverage() │
│ leverage = map_internal_conviction_to_exchange_leverage( │
│ sizing_lev, exchange_max=config.exchange_leverage_cap)│
│ │
│ ALL use: prod/bingx/leverage.py (SOURCE OF TRUTH) │
└─────────────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ BingX API │ │ BingX API │ │ BingX API │ │ BingX API │
│ /trade/ │ │ /trade/ │ │ /trade/ │ │ /trade/ │
│ leverage │ │ leverage │ │ leverage │ │ leverage │
│ (int 1-3) │ │ (int 1-3) │ │ (int 1-3) │ │ (int 1-3) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ ACCOUNTING (leverage-free) │
│ │
│ PnL = qty × (exit_price - entry_price) [side-signed] │
│ our_leverage = (size × entry_price) / capital [Hz publishing] │
│ margin = notional / exchange_leverage │
│ │
│ HARD INVARIANT (PINK_ACCOUNTING_EXEC_FIX.md §0): │
│ "slot.size = exchange quantity; slot.leverage = exchange leverage │
│ (1-3x cap, set at BingX API); our_leverage (conviction) = │
│ size × entry_price / capital, computed ONLY at _hz_publish. │
│ PnL is therefore LEVERAGE-FREE: qty × Δprice, side-signed." │
└─────────────────────────────────────────────────────────────────────┘
```
---
## Mutation Litmus — Complete
| Mutation | Where It Breaks | Catching Test |
|----------|----------------|---------------|
| Use `exchange_leverage` in PnL formula | `prod/clean_arch/dita/trade.py:apply_fill()` | `test_pink_ditav2_accounting_invariants.py` |
| Use `conviction_leverage` as BingX leverage | `prod/clean_arch/adapters/bingx_direct.py:submit_intent()` | BingX API rejects >3× for PINK |
| ROUND_HALF_UP instead of ROUND_HALF_EVEN | `prod/bingx/leverage.py:normalize_bingx_leverage_value()` | `test_violet_exchange_leverage.py::test_round_half_even_boundary_cases` (2.5→2) |
| Drop clamp to [1,3] | `prod/bingx/leverage.py:_clamp_exchange_bounds()` | BingX API rejects leverage >3 |
| Conflate `our_leverage` with `exchange_leverage` | Any accounting code | `PINK_ACCOUNTING_EXEC_FIX.md` HARD INVARIANT violation |
| Skip dual-leverage in VIOLET L3 | `prod/clean_arch/violet/exec_intent.py:_exchange_leverage_for()` | `test_violet_exchange_leverage.py::test_gate_exchange_leverage_bit_identity` (N≥1e6) |
---
## Search Complete — All Systems Mapped
| System | Decision/Sizing | Intent | Venue Translation | Accounting |
|--------|----------------|--------|-------------------|------------|
| **BLUE** | `esf_alpha_orchestrator` (5-factor) | `nautilus_event_trader.py` | `prod/bingx/execution.py` | `compute_our_leverage()` for TP |
| **PINK (live)** | `prod/clean_arch/dita/decision.py` | `prod/clean_arch/dita/intent.py` | `prod/clean_arch/adapters/bingx_direct.py` | `AccountProjection.leverage = our_leverage` |
| **PINK (DITAv2)** | `prod/clean_arch/dita_v2/blue_parity.py` | `prod/clean_arch/dita/intent.py` | `prod/clean_arch/adapters/bingx_direct.py` | `AccountProjection.leverage = our_leverage` |
| **PRODGREEN** | Same as BLUE | Same | `prod/bingx/execution.py` | Same |
| **VIOLET (shadow)** | `prod/clean_arch/violet/decision_engine.py` | `prod/clean_arch/violet/exec_intent.py` | `prod/clean_arch/violet/exchange_leverage.py` | `CapitalState.capital` anchor |
**All paths converge on `prod/bingx/leverage.py` — the single source of truth for conviction→exchange mapping.**

View File

@@ -0,0 +1,126 @@
# VIOLET Study Spec — Base-Fraction / Capital-Utilization Sizing Study
**Status:** TODO (research spec, written 2026-06-13). Gated AFTER the regime-robustness
study (#1). Feeds VIOLET V3 Layer-3 sizing mechanics and any base-fraction change to
the live PINK/BLUE `AlphaBetSizer`.
**Owner intent:** the [[blue_margin_envelope_study]] proved BLUE's capital is badly
*under-utilized* (median trade ties up ~3.4% of wallet at 2× exchange leverage; 100% of
trades feasible at 2×; max realized `our_leverage` = notional/capital ≈ 1.81). The ROI
lever is the **base fraction** (currently `base_fraction = 0.20` in `AlphaBetSizer`),
NOT exchange leverage. Question this study answers: **how far above 0.20 can base
fraction be pushed for more ROI, risk-bounded, and where do hard constraints bind?**
---
## 0. Doctrine / non-negotiables
- **ROI is driven by `notional/capital` = `base_fraction × conviction_leverage`**, not by
exchange leverage. Exchange leverage (PINK/VIOLET max-3× **linear** translator) is a
margin-efficiency knob only. Confirmed empirically:
`notional = capital × 0.20 × leverage`, `leverage` = cubic-convex conviction ∈ [0.5, 9].
- **The edge is regime-concentrated** (≈95% of clean edge in choppy-bearish; bull is the
separate EFSM long-reversal algo's domain). Therefore sizing-up amplifies exposure to
the worst observed regime AND to the untested-by-this-strategy tails. This study MUST
output a fraction recommendation **conditioned on the regime-robustness result (#1)**,
not a raw-ROI maximizer.
- **Counterfactual honesty:** resizing past trades assumes the *same trades would have
filled at the larger size*. That assumption degrades with size (market impact). The
study MUST estimate and discount for slippage/impact, not assume linear scaling.
## 1. The hard constraint that binds first — the 3× translator ceiling
`our_leverage = base_fraction × conviction`, max conviction = 9.0. To finance a position
the exchange leverage must satisfy `exch_lev ≥ our_leverage`. PINK/VIOLET's translator
caps exchange leverage at **3×**. Therefore the **maximum financeable base fraction**
before the cap binds on the highest-conviction trades is:
```
base_fraction_max ≈ 3.0 / 9.0 ≈ 0.333 (i.e. our_leverage_max = 0.333 × 9 = 3.0 = cap)
```
- At `f = 0.20`: max our_leverage 1.8 → 2× suffices, comfortable.
- At `f ≈ 0.333`: max our_leverage 3.0 → exactly the 3× cap (no buffer on max-conviction
trades).
- At `f > 0.333`: highest-conviction trades CANNOT be financed at 3× → they clip
(under-size) or require raising the translator cap (a separate margin-risk decision).
**Deliverable 1:** the exact binding curve `f → fraction of trades that clip at 3× cap`,
using the real conviction distribution (most trades are low-conviction, so the cap may
bind on very few trades well above 0.333 — quantify it, don't assume the 0.333 worst case
dominates).
## 2. Method
Operate on the **clean deduped trade set** (one row per `trade_id`; drop `HIBERNATE_HALT`
and `bars_held = 0`; see [[blue_margin_envelope_study]] for the cleaning that yields
+$47k / 2121 trades). Required per-trade fields: `pnl`, `pnl_pct`, `entry_price`,
`quantity`, `capital_before`, `leverage` (conviction), `our_leverage`, regime hash tags
(join to `maras_fingerprint.composite_hash`), and execution-quality (slippage) from
`trade_execution_quality` / `execution_quality_json`.
### 2a. Counterfactual resize grid
For `f ∈ {0.20, 0.25, 0.30, 0.333, 0.40, 0.50}` (and finer near the optimum):
- Per trade, resized notional scales by `f / 0.20`; **`pnl_pct` is size-invariant**, so
resized `$pnl = pnl_pct × resized_notional` **before** slippage discount.
- Apply the §2c slippage discount.
- Apply the §1 cap clip: if `f × conviction > 3.0`, clip notional to `3.0 × capital`.
### 2b. Path-dependent equity reconstruction
Replay trades in time order, compounding each resized `$pnl` onto a running capital base
(bigger size → bigger swings → different compounding path; do NOT just sum). Seed from the
real starting capital of the tracked window. Produce per-`f`:
- final capital, CAGR
- **max drawdown**, Calmar/MAR (CAGR ÷ maxDD), longest-underwater days
- Sharpe, Sortino, downside deviation
- risk-of-ruin estimate
### 2c. Slippage / market-impact model (critical — do NOT skip)
The largest real-world degrader. From the maker-fill telemetry estimate whether larger
notionals get worse fills / more requotes / more taker fallback:
- regress realized fill slippage (and maker→taker fallback rate) against order notional
/ notional-vs-ADV where available
- build a `slippage_bps(notional)` discount applied in §2a
- if data is insufficient, state so and use a conservative parametric impact assumption
(document it); flag the result as impact-uncertain
### 2d. Kelly / fractional-Kelly anchor
Estimate the growth-optimal fraction from the empirical win-rate + payoff distribution.
Recommend **fractional Kelly (¼–½)** given the edge is **non-stationary and
regime-conditional** — full Kelly assumes a stationary edge we have explicitly shown does
not hold. Compare the Kelly-implied fraction to the §1 cap ceiling and the §2b
drawdown-optimal fraction.
### 2e. Regime-conditioned drawdown (the binding test)
Re-run §2b conditioned on the regime **hash** buckets from #1 (NOT the MARAS label — the
label is held untrusted; sub-regimes within choppy-bearish are expected). The binding
drawdown is the **worst-hash-bucket** drawdown, not the aggregate. Add a **stress
scenario**: inject a hypothetical adverse excursion sized to the worst plausible
unsampled-regime loss and report each `f`'s survival.
## 3. Deliverables
1. Table: `f` × {final capital, CAGR, maxDD, Calmar, Sharpe, ruin-prob, %trades-clipped-at-3×}.
2. The §1 cap-binding curve.
3. The §2c slippage discount model + its effect on the optimum.
4. A **recommended base fraction** (or a conviction-conditioned fraction *schedule*),
with the explicit risk statement: how much extra ROI, at what extra drawdown, under
what regime assumption.
5. Machine-readable report → `prod/VIOLET_dev/reports/base_fraction_study_<ts>.json`;
1-page FINDINGS alongside.
## 4. Caveats to carry into every conclusion
- Non-stationary, regime-concentrated edge — the optimum is conditional, not universal.
- Counterfactual resizing assumes fillability at scale (mitigated by §2c, never eliminated).
- Single-slot (no concurrency) — confirmed; if that ever changes, margin math changes.
- The clean set still may carry minor residual pollution; corroborate against the
corrected-capital trajectory as in the parent study.
- Do not let raw-ROI maximization override drawdown/ruin constraints. The under-utilized
capital is an *opportunity bounded by regime risk*, not free money.
## 5. Related
[[blue_margin_envelope_study]] · [[violet_v3_alpha_doctrine]] ·
`prod/bingx/leverage.py` (translator) · `nautilus_dolphin/nautilus/alpha_bet_sizer.py`
(base_fraction) · `prod/clean_arch/dita_v2/blue_parity.py` (PINK wrapper, note 8 vs 9 drift).

View File

@@ -48,7 +48,7 @@ Self-consistent at row level vs recorded `dolphin.trade_events`:
- **DUAL-LEVERAGE:** conviction leverage sizes the QUANTITY (internal); exchange leverage
mapped at the venue boundary via `prod/bingx/leverage.py`
`map_internal_conviction_to_exchange_leverage_target` (round_half_even linear
0.59.0 → 1..cap; PINK/VIOLET use a max-3× cubic translator).
0.59.0 → 1..cap; PINK/VIOLET use a max-3× **linear** translator).
## 3. blue_parity drift (doctrine validated by evidence)