Files
siloqy/SYSTEM_BIBLE.md
Codex e38ec77221 PINK: fix fee-sign bug + WARN-unfreeze — 451/451 tests green
Defect A (fee sign): bingx_user_stream._normalise_order flipped to
  fee = -raw_fee so BingX negative-n costs arrive as positive kernel
  costs.  k_maker_rebates no longer accumulates phantom rebates.

Defect B (opening fee dropped): fill_qty now falls back to "z"
  (cumFilledQty) when "l" (lastFilledQty) is zero/absent, so
  apply_predicted_fill computes a non-zero opening-leg fee.

Architectural fix (WARN unfreezes): lib.rs reconcile() now unfreezes
  capital_frozen on WARN as well as OK.  WARN (0.01-20 USDT delta) is
  normal in-flight settlement — only ERROR (≥20, unexplained) should
  halt ENTERs.  The old keep-state logic trapped the kernel permanently
  frozen after the first trade's ENTER predicted-fee phase pushed delta
  briefly into ERROR.

Acceptance criterion: |k_capital - bingx_balance| < 1 USDT, frozen=False
after every round-trip trade — verified numerically against T-1/T-2
ground truth from the CRITICAL doc.

Docs: CRITICAL_AGENT-TODO_ACCOUNTING_BUGFIX.md §12-13 (fix record),
      CAPITAL_BOOKKEEPING_DESIGN.md §8 (kernel spec), SYSTEM_BIBLE §11.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:08:31 +02:00

386 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DOLPHIN Trading System Bible
**Version:** 1.0.0
**Last Updated:** 2026-03-24
**Status:** Production Ready - Paper Trading Operational
---
## 1. System Overview
The DOLPHIN Trading System is a production-grade algorithmic trading platform implementing clean hexagonal architecture for high-frequency eigenvalue-based trading strategies.
### 1.1 Current Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ DOLPHIN TRADING SYSTEM │
│ Version 1.0.0 │
├─────────────────────────────────────────────────────────────────────────┤
│ PRESENTATION LAYER │
│ ├── Paper Trading CLI (paper_trade.py) │
│ ├── System Monitor (status.py) │
│ └── Trading Dashboard (future) │
├─────────────────────────────────────────────────────────────────────────┤
│ CORE BUSINESS LOGIC (PORTS) │
│ ├── DataFeedPort - Abstract market data interface │
│ ├── TradingPort - Abstract execution interface │
│ └── StrategyPort - Abstract strategy interface │
├─────────────────────────────────────────────────────────────────────────┤
│ ADAPTER LAYER │
│ ├── HazelcastDataFeed - Live data from DolphinNG6 │
│ ├── PaperTradeExecutor - Simulated order execution │
│ └── (Future: BinanceDataFeed, LiveExecutor) │
├─────────────────────────────────────────────────────────────────────────┤
│ DOMAIN LOGIC │
│ ├── TradingEngine - Position sizing, risk management │
│ ├── SignalProcessor - Eigenvalue signal generation │
│ ├── PortfolioManager - Position tracking, PnL calculation │
│ └── ACBIntegration - Adaptive Circuit Breaker │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ INFRASTRUCTURE │
│ ├── Hazelcast Cluster - Single Source of Truth (localhost:5701) │
│ ├── Scan Bridge Service - Arrow file watcher → Hazelcast │
│ ├── Arrow File Storage - /mnt/ng6_data/arrow_scans/ │
│ └── Nautilus Trader - Execution framework (future integration) │
└─────────────────────────────────────────────────────────────────────────┘
```
### 1.2 Key Metrics
| Metric | Value |
|--------|-------|
| Architecture Pattern | Hexagonal (Clean Architecture) |
| Data Latency | ~5 seconds (DolphinNG6 pulse) |
| Assets Tracked | 50 (BTC, ETH, BNB, etc.) |
| Eigenvalue Windows | 50, 150, 300, 750 periods |
| Current BTC Price | $71,281.03 |
| Paper Trade Volume | 0.001 BTC per signal |
---
## 2. Version History
### v1.0.0 (2026-03-24) - CURRENT
**Codename:** Clean Slate
#### Major Features
- ✅ Clean hexagonal architecture implementation
- ✅ Hazelcast DataFeed adapter (live data from DolphinNG6)
- ✅ Scan Bridge Service (Arrow → Hazelcast bridge)
- ✅ Paper trading engine with PnL tracking
- ✅ Mean reversion strategy on velocity divergence
- ✅ 23 round-trip trades executed in testing
#### Components Added
- `prod/clean_arch/ports/data_feed.py` - Port interfaces
- `prod/clean_arch/adapters/hazelcast_feed.py` - Hazelcast adapter
- `prod/clean_arch/core/trading_engine.py` - Business logic
- `prod/scan_bridge_service.py` - Infrastructure bridge
- `prod/clean_arch/paper_trade.py` - Trading CLI
#### Infrastructure
- Hazelcast cluster at localhost:5701
- Scan bridge watching /mnt/ng6_data/arrow_scans/
- 6,500+ Arrow scan files processed
---
## 3. Architecture Principles
### 3.1 Hexagonal Architecture (Ports & Adapters)
The system follows strict dependency rules:
```
Core (inner) → Adapters (outer)
Ports (interfaces)
```
**Rule:** Dependencies only point inward. Core knows nothing about Hazelcast, Arrow files, or Binance.
### 3.2 Single Source of Truth
All market data comes from Hazelcast `DOLPHIN_FEATURES` map:
- Price + eigenvalues written atomically by DolphinNG6
- No synchronization issues
- Guaranteed consistent timestamps
### 3.3 File Timestamp vs Scan Number
The Scan Bridge uses **file modification time** (mtime) instead of scan numbers because:
- DolphinNG6 resets scan counters on restarts
- mtime always correctly identifies the latest file
- Handles NG6 crashes and restarts gracefully
---
## 4. Subsystems
### 4.1 Data Flow Architecture
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ DolphinNG6 │────▶│ Arrow Files │────▶│ Scan Bridge │────▶│ Hazelcast │
│ (Trading) │ │ (Storage) │ │ (Service) │ │ (SSOT) │
└─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
5s pulse │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Binance │◀────│ Nautilus │◀────│ Trading │◀────│ Hazelcast │
│ (Paper) │ │ Trader │ │ Engine │ │ DataFeed │
│ │ │ (Future) │ │ (Core) │ │ (Adapter) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
```
### 4.2 Component Details
#### Scan Bridge Service
**File:** `prod/scan_bridge_service.py`
**Purpose:** Watch Arrow files and push to Hazelcast
**Key Features:**
- Uses `watchdog` for file system events
- Parses JSON columns (`assets_json`, `asset_prices_json`)
- Handles numpy types in serialization
- Rolls to new day directory automatically
**Startup:**
```bash
cd /mnt/dolphinng5_predict/prod
source /home/dolphin/siloqy_env/bin/activate
python3 scan_bridge_service.py
```
#### Hazelcast DataFeed Adapter
**File:** `prod/clean_arch/adapters/hazelcast_feed.py`
**Purpose:** Implement DataFeedPort using Hazelcast
**Key Methods:**
- `connect()` - Connect to Hazelcast cluster
- `get_latest_snapshot(symbol)` - Get MarketSnapshot
- `subscribe_snapshots(callback)` - Subscribe to updates
**Data Structure:**
```python
MarketSnapshot(
timestamp=datetime,
symbol="BTCUSDT",
price=71281.03,
eigenvalues=[...], # 50 loadings
velocity_divergence=-0.0058,
scan_number=7315
)
```
#### Trading Engine
**File:** `prod/clean_arch/core/trading_engine.py`
**Purpose:** Pure business logic, no external dependencies
**Responsibilities:**
- Position sizing
- Signal processing
- Risk management
- PnL calculation
---
## 5. Trading Strategy
### 5.1 Current Strategy: Velocity Divergence Mean Reversion
**Logic:**
```python
if velocity_divergence < BUY_THRESHOLD: # -0.01
BUY 0.001 BTC
elif velocity_divergence > SELL_THRESHOLD: # 0.01
SELL position
```
**Rationale:** Extreme negative velocity divergence suggests oversold conditions.
### 5.2 Signal Sources
| Signal | Source | Description |
|--------|--------|-------------|
| `velocity_divergence` | DolphinNG6 | Rate of change divergence |
| `instability_composite` | DolphinNG6 | Market instability metric |
| `w50_lambda_max` | DolphinNG6 | Max eigenvalue (50-period) |
| `asset_loadings` | DolphinNG6 | Eigenvector components |
---
## 6. Operations Guide
### 6.1 Starting the System
```bash
# 1. Ensure Hazelcast is running
docker ps | grep hazelcast
# 2. Start Scan Bridge
cd /mnt/dolphinng5_predict/prod
source /home/dolphin/siloqy_env/bin/activate
python3 scan_bridge_service.py &
# 3. Verify data flow
python3 clean_arch/status.py
# 4. Run paper trading
python3 clean_arch/paper_trade.py --duration 60
```
### 6.2 Monitoring
**Check Status:**
```bash
cd /mnt/dolphinng5_predict/prod/clean_arch
python3 status.py
```
**Expected Output:**
```
🐬 DOLPHIN PAPER TRADING STATUS
⚡ HAZELCAST: CONNECTED
Scan: #7315
Assets: 50
Prices: 50
BTC Price: $71,281.03
```
### 6.3 Troubleshooting
| Issue | Solution |
|-------|----------|
| No Hazelcast connection | Check `docker ps`, restart container |
| No data in Hz | Restart scan bridge, check Arrow files |
| Scan number mismatch | Normal - bridge uses mtime, not scan # |
| Zero eigenvalues | Check `asset_loadings` field exists |
---
## 7. Evolution Roadmap
### Phase 1: Hazelcast Feed (COMPLETE - v1.0.0)
- ✅ Clean architecture
- ✅ Hazelcast adapter
- ✅ Paper trading
- ✅ Scan bridge service
### Phase 2: Direct Market Feed (v1.1.0)
- [ ] Binance WebSocket adapter
- [ ] Local eigenvalue computation
- [ ] Reduced latency (<100ms)
### Phase 3: Rust Kernel (v2.0.0)
- [ ] Port core to Rust
- [ ] Python adapter layer only
- [ ] Microsecond latency
### Phase 4: Live Trading (v3.0.0)
- [ ] Live order execution
- [ ] Risk management integration
- [ ] Production deployment
---
## 8. File Reference
| Path | Purpose | Version Added |
|------|---------|---------------|
| `prod/clean_arch/ports/data_feed.py` | Port interfaces | v1.0.0 |
| `prod/clean_arch/adapters/hazelcast_feed.py` | Hz adapter | v1.0.0 |
| `prod/clean_arch/core/trading_engine.py` | Business logic | v1.0.0 |
| `prod/scan_bridge_service.py` | Arrow bridge | v1.0.0 |
| `prod/clean_arch/paper_trade.py` | Trading CLI | v1.0.0 |
| `prod/clean_arch/status.py` | Status monitor | v1.0.0 |
---
## 9. Environment
**Python Environment:** `/home/dolphin/siloqy_env`
**Python Version:** 3.12.12
**Key Dependencies:**
- nautilus_trader 1.219.0
- hazelcast-python-client 5.6.0
- pyarrow
- watchdog
**Data Locations:**
- Arrow files: `/mnt/ng6_data/arrow_scans/YYYY-MM-DD/`
- Hazelcast: `localhost:5701`
- Logs: `/tmp/scan_bridge.log`
---
## 10. Team & Ownership
**System Architect:** Clean Architecture Pattern
**Data Source:** DolphinNG6 (Eigenvalue Engine)
**Infrastructure:** Hazelcast Cluster
**Trading Engine:** Hexagonal Core
---
*This document is the single source of truth for the DOLPHIN Trading System architecture and operations. All changes must be documented with version updates.*
**Document Version:** 1.0.0
**Last Modified:** 2026-03-24
**Next Review:** On Phase 2 completion
---
## 11. DITAv2 / PINK — Accounting Architecture & Known Fixes
### 11.1 Fee Sign Convention (CRITICAL — 2026-06-08)
The Rust K-account uses **POSITIVE = cost, NEGATIVE = rebate** for all fee buckets.
BingX VST uses the **opposite convention**: the `"n"` (commission) field is **NEGATIVE for costs, POSITIVE for rebates**.
The sign translation is applied at `bingx_user_stream.py:_normalise_order()`:
```python
raw_fee = _safe_float(o.get("n") or 0.0)
fee = -raw_fee # BingX cost (neg) → kernel cost (pos)
```
**Never apply this translation twice.** The kernel's `apply_fill_settled` / `apply_predicted_fill` always expect kernel convention (positive = cost). If a second boundary layer exists, it must pass fees already in kernel convention.
### 11.2 Opening-Fee Settlement (Defect B — fixed 2026-06-08)
BingX ENTER fills report filled quantity only in field `"z"` (cumFilledQty), not `"l"` (lastFilledQty). The `_normalise_order` fallback:
```python
_last_qty = _safe_float(o.get("l") or 0.0)
_cum_qty = _safe_float(o.get("z") or o.get("cumFilledQty") or 0.0)
fill_qty = _last_qty if _last_qty > 0.0 else _cum_qty
```
Ensures `apply_predicted_fill` receives non-zero `fill_qty` for ENTER fills, so the opening-leg fee prediction lands in `k_taker_fees`.
### 11.3 Reconcile / Capital Freeze Logic
The Rust kernel classifies K-vs-E divergence:
| `reconcile_status` | delta range | `capital_frozen` |
|---|---|---|
| `OK` | < 0.01 USDT | False |
| `WARN` | 0.0120 USDT | False (unsettled but tradeable) |
| `ERROR` | 20 USDT | True (unexplained gap, HALT ENTERs) |
**WARN does NOT freeze.** During a live trade, the ENTER predicted fee temporarily pushes delta into ERROR range (seed balance not yet updated by exchange). The EXIT's realized PnL brings delta back into WARN (< 20), then the `ACCOUNT_UPDATE` event brings it to OK. Freezing on WARN would permanently block all trading after the first trade.
Only `ERROR` (≥ 20 USDT, unexplained) warrants a freeze.
### 11.4 Acceptance Criterion
After every round-trip trade: `|k_capital bingx_wallet_balance| < 1.0 USDT` and `capital_frozen = False`.
Verified numerically against BingX ledger in `test_fee_sign_accounting.py` (34 tests, all green as of 2026-06-08).
### 11.5 Test File
`prod/clean_arch/dita_v2/test_fee_sign_accounting.py` 34 tests covering:
- Prove-Broken: characterises the pre-fix buggy behaviour
- Prove-Fixed: T-2 and T-1 ground-truth round-trips
- Boundary layer: BingX `_normalise_order` sign + fill_qty
- Edge cases: rebates, partials, multiple fills