# AGENCIO PREDICT — COMPREHENSIVE TRADING MATH & ALGORITHM AUDIT

**Audit Date:** April 23, 2026 (Re-audited: May 1, 2026; Expert Audit: May 4, 2026)
**Scope:** All trading mathematics, algorithms, signal generation, and AI decision-making systems
**Status:** Production-ready, audited 2026-04-23 (ALL 20 expert-level enhancements + 11 expert audit recommendations complete)

### Re-Audit Fixes (2026-05-01)

| File | Issue | Fix |
|------|-------|-----|
| `metrics.ts` | Skewness used population variance (n) but sample correction factor | Changed to sample variance (n-1) for consistency |
| `metrics.ts` | Kurtosis used population variance (n) but sample correction factor | Changed to sample variance (n-1) for consistency |
| `portfolio-correlation-monitor.ts` | StdDev used n denominator instead of n-1 | Changed to sample std dev (n-1, Bessel's correction) |

**Verified Correct (no change needed):**
- Calmar ratio dimension handling (100s cancel correctly)
- Correlation haircut formula (sqrt(effN/N) correctly reduces positions when correlation is high)
- Kelly criterion edge cases (negative Kelly returns 0)
- Autocorrelation denominator (standard formula using full variance)
- Position reconciliation halt behavior (criticalMismatch properly stops execution)

### Expert Audit Implementation (2026-05-04)

All 11 recommendations from comprehensive expert review implemented:

| # | Issue | Solution | File |
|---|-------|----------|------|
| 1 | No adjustment for multiple testing bias | **Deflated Sharpe Ratio**: DSR = PSR - Φ⁻¹(1 - 1/N) | `metrics.ts` |
| 2 | No intraday VaR monitoring | **15-minute VaR checks** with historical simulation | `guardrails/service.ts` |
| 3 | No participation rate limits | **Max ADV limits**: stocks 3%, ETFs 5%, crypto 2%, forex 10% | `trade-execution.ts` |
| 4 | Kelly sizing not regime-aware | **Regime-scaled Kelly**: BULL=0.5x, CRISIS=0.25x | `dsl/evaluator.ts` |
| 5 | Missing Information Ratio | **IR = alpha / tracking error** (annualized) | `metrics.ts` |
| 6 | Critic text could anchor Judge | **Blind Jury Pattern**: Judge sees only summary stats | `llm/jury.ts` |
| 7 | Temperatures not optimized | **Temperature scheduling**: proposer=0.4, critic=0.5, judge=0.1 | `llm/jury.ts`, `translate.ts` |
| 8 | No exposure limits | **Gross/Net limits**: 200% max gross, 100% max net | `guardrails/service.ts` |
| 9 | Missing Omega Ratio | **Ω = Σ max(0,r-L) / Σ max(0,L-r)** (full distribution) | `metrics.ts` |
| 10 | Missing Gain-to-Pain Ratio | **GPR = Σ gains / |Σ losses|** (trader-friendly) | `metrics.ts` |
| 11 | Regime-aware Kelly not in DSL | **New primitive `kelly_regime_aware()`** with 5 regime levels | `dsl/types.ts` |

---

## TABLE OF CONTENTS

1. [Backtest Metrics Library](#section-1-backtest-metrics-library)
2. [DSL Primitives (40 Total)](#section-2-dsl-primitives-40-total)
3. [Backtest Engine](#section-3-backtest-engine)
4. [Trade Execution Service](#section-4-trade-execution-service)
5. [Position Service](#section-5-position-service)
6. [Signal Generation](#section-6-signal-generation)
7. [Human-vs-Automation Composite Score](#section-7-human-vs-automation-composite-score)
8. [Tick-Level Whale/Bot Classifier](#section-8-tick-level-whale--bot-classifier)
9. [Algorithm Executor (Paper/Live Mode)](#section-9-algorithm-executor-paperlive-mode)
10. [Guardrails (5-Layer Hierarchy)](#section-10-guardrails-5-layer-hierarchy)
11. [LLM-Jury System](#section-11-llm-jury-system-defense-5)
12. [All-Seeing-Eye System](#section-12-all-seeing-eye-system)
13. [Risk Management Features](#section-13-risk-management-features)
14. [Data Integrity & Safety](#section-14-data-integrity--safety)
15. [Key Constants & Thresholds](#section-15-key-constants--thresholds)
16. [Execution Modes & Defaults](#section-16-execution-modes--defaults)
17. [Database Persistence](#section-17-database-persistence)
18. [Compliance & Audit Notes](#section-18-compliance--audit-notes)
19. [Key Files Reference](#appendix-key-files-reference)

---

## SECTION 1: BACKTEST METRICS LIBRARY

**File:** `packages/be/src/backtest/metrics.ts`

### Return Calculations

| Function | Formula | Notes |
|----------|---------|-------|
| `calculateTotalReturn` | `((finalEquity - initialCapital) / initialCapital) * 100` | Total % return over period |
| `calculateAnnualizedReturn` | `(1 + totalReturn/100)^(1/years) - 1` | CAGR formula; years = tradingDays / 252 |
| `calculateDailyReturns` | `((point.equity - prevEquity) / prevEquity) * 100` | Percent change day-over-day |

### Risk Calculations

| Metric | Formula | Constants |
|--------|---------|-----------|
| **Volatility** | `dailyStdDev * sqrt(252)` | 252 = TRADING_DAYS_PER_YEAR |
| **Sharpe Ratio** | `(annualizedReturn - riskFreeRate) / volatility` | Dynamic risk-free from FRED DTB3 (24h cache, 4% fallback) |
| **Sortino Ratio** | `(annualizedReturn - riskFreeRate) / downsideDeviation` | Denominator uses **total observations** (fixed 2026-04-23) |
| **Calmar Ratio** | `annualizedReturn / maxDrawdown` | Return per unit of max DD |

### Risk-Free Rate (Dynamic)

```typescript
// Fetches 3-month T-bill rate from FRED DTB3 series
// 24-hour cache, 4% fallback on error
fetchRiskFreeRate(): Promise<number>
```

### Drawdown Calculations

| Function | Behavior |
|----------|----------|
| `calculateDrawdownSeries` | For each bar: peak tracks highest equity, drawdown = (peak - current) / peak * 100 |
| `calculateMaxDrawdown` | Tracks peak equity, counts consecutive days in drawdown, returns max value + duration |
| `calculateVaR(0.95)` | Sorts returns ascending, takes return at index floor((1-0.95)*length) |
| `calculateCVaR(0.95)` | Average of returns in the tail below VaR threshold |
| `calculateCornishFisherVaR(0.95)` | Fat-tail adjusted VaR using skewness/kurtosis expansion (added 2026-04-23) |

### Trade Statistics

| Metric | Formula | Details |
|--------|---------|---------|
| **Win Rate** | `(winningTrades / totalTrades) * 100` | % of trades with positive P&L |
| **Profit Factor** | `grossProfit / grossLoss` | Upside / downside ratio |
| **Expectancy** | `(winRate * avgWin%) - (lossRate * avgLoss%)` | Expected return per trade |
| **Streaks** | Track consecutive wins/losses | Counts unbroken sequences |

### Advanced Metrics

| Metric | Formula | Interpretation |
|--------|---------|-----------------|
| **Skewness** | Fisher-Pearson: `(n/((n-1)(n-2))) * sum((r - mean)^3 / s^3)` where s uses n-1 | >0 = right tail, <0 = left tail |
| **Kurtosis** | Fisher-Pearson excess: `(n(n+1)/((n-1)(n-2)(n-3))) * sum() - 3(n-1)²/((n-2)(n-3))` where s uses n-1 | >0 = fat tails, <0 = thin tails |
| **Monthly Returns** | Grouped by YYYY-MM, calculated per month | Per-month aggregation with win rates |

### Statistical Tests (Added 2026-04-23)

| Function | Formula | Usage |
|----------|---------|-------|
| `ljungBoxTest(returns, maxLag)` | Q = n(n+2) * Σ(ρ_k² / (n-k)) | Detects autocorrelation in return series; p < 0.05 suggests non-random patterns |
| `neweyWestStdDev(returns, maxLag)` | HAC-adjusted standard deviation | Autocorrelation-adjusted volatility for more accurate risk metrics |

### Extreme Value Theory (Added 2026-04-23)

| Function | Formula | Usage |
|----------|---------|-------|
| `calculateGPDVaR(returns, confidence, threshold)` | GPD tail modeling with MLE | Tail risk estimation using Generalized Pareto Distribution |
| Returns | `{ var, xi (shape), sigma (scale), nExceedances }` | xi > 0 = heavy tail, xi < 0 = thin tail |

### Drawdown Decomposition (Added 2026-04-23)

| Function | Returns | Usage |
|----------|---------|-------|
| `analyzeDrawdownEvents(equityCurve)` | `{ events[], ulcerIndex, painIndex, avgRecoveryDays, maxUnderwaterDays }` | Full drawdown event analysis |
| **Ulcer Index** | `sqrt(mean(drawdown²))` | Risk of drawdown pain (lower = better) |
| **Pain Index** | `mean(drawdown)` | Average time spent underwater |
| **DrawdownEvent** | Peak/trough dates, depth, duration, recovery time | Each distinct drawdown episode |

### Benchmark Comparison

| Metric | Formula |
|--------|---------|
| **Beta** | `cov(portfolio, benchmark) / var(benchmark)` | Market sensitivity |
| **Alpha** | `annualReturn - (riskFree + beta * (benchmarkReturn - riskFree))` | Excess return |
| **Correlation** | `covariance / (stdDev_p * stdDev_b)` | Move synchronization |
| **Information Ratio** | `alpha / trackingError` | Risk-adjusted alpha per unit of tracking error |
| **Tracking Error** | `stdDev(excess returns) * sqrt(252)` | Annualized excess return volatility |

### Multiple-Testing Adjustment (Added 2026-05-04)

| Function | Formula | Usage |
|----------|---------|-------|
| `calculateDeflatedSharpe(psr, N)` | `DSR = PSR - Φ⁻¹(1 - 1/N)` | Adjusts for selection bias when N strategies tested |

**Interpretation:**
- A Sharpe of 2.0 that was best of 100 tested strategies has much lower DSR than one tested alone
- Prevents p-hacking and overfitting to historical data

### Risk-Adjusted Performance Metrics (Added 2026-05-04)

| Metric | Formula | Interpretation |
|--------|---------|----------------|
| **Information Ratio** | `IR = (R_p - R_b) / TE` | >0.5 good, >1.0 excellent |
| **Omega Ratio** | `Ω = Σmax(0,r-L) / Σmax(0,L-r)` | >1 = gains exceed losses |
| **Gain-to-Pain Ratio** | `GPR = Σgains / |Σlosses|` | >2 = good, intuitive for traders |
| **Ulcer Index** | `UI = sqrt(mean(DD²))` | Lower is better; penalizes deep + prolonged DDs |
| **Ulcer Performance Index** | `UPI = (R - Rf) / UI` | Sharpe but uses Ulcer Index |

---

## SECTION 2: DSL PRIMITIVES (40 Total)

**File:** `packages/be/src/algorithms/dsl/types.ts` → PRIMITIVES registry

### Category 1: PRICE / VOLUME (3 primitives)

```typescript
price(symbol: string) → number
  // Latest price for symbol

vwap(symbol: string, duration: string|number) → number
  // Volume-weighted average price; window in hours/days/etc.

volume_z(symbol: string, duration: string|number) → number
  // Z-score of current volume vs window mean; high = spike
```

### Category 2: TECHNICAL INDICATORS (8 primitives)

```typescript
rsi(period: number = 14) → number
  // Relative Strength Index, 0-100. <30 = oversold, >70 = overbought

macd() → number
  // MACD histogram (12-26 EMA difference)

bb_upper(period: number, stdDev: number) → number
  // Bollinger upper band = SMA + stdDev * std

bb_lower(period: number, stdDev: number) → number
  // Bollinger lower band = SMA - stdDev * std

atr(period: number = 14) → number
  // Average True Range — measure of volatility

obv() → number
  // On-Balance Volume — cumulative volume indicator

adx(period: number = 14) → number
  // Average Directional Index, 0-100. >25 = trend present

zscore(value: number) → number
  // (value - mean) / stddev for the trailing window
```

### Category 3: SENTIMENT SIGNALS (4 primitives)

```typescript
sentiment(source: string, duration: string|number) → number
  // Sentiment score [-1, +1] from source over window
  // Sources: 'reddit', 'twitter', 'news', etc.

whale_activity(symbol: string) → number
  // Whale activity score (see tick-classifier)

funding_rate(symbol: string) → number
  // Crypto perpetual funding rate, 8h rate in percent

human_automation_score(symbol: string) → number
  // Composite [-1, +1]: -1 = bot-dominated, +1 = human-driven
  // (Reads from computed_insights, no look-ahead)

human_automation_confidence(symbol: string) → number
  // Confidence [0..1] of latest human-automation composite
```

### Category 4: MACRO INDICATORS (8 primitives)

**Yield Curve:**
```typescript
curve_slope_2s10s() → number
  // 10Y - 2Y Treasury slope, %, negative = inverted (recession)

curve_slope_3m10y() → number
  // 10Y - 3M slope, Fed-preferred recession gauge

curve_slope_5s30s() → number
  // 30Y - 5Y slope, term premium / long-end steepening
```

**Credit & Risk:**
```typescript
credit_ratio_hy_ig() → number
  // HYG / LQD price ratio; lower = spreads widening (risk-off)

vix() → number
  // VIX level

treasury_2y10y_spread() → number
  // 2Y-10Y spread (alias for curve_slope_2s10s)

move_index() → number
  // ICE BofA MOVE — implied Treasury volatility (bond-market VIX)

real_yield_10y() → number
  // 10Y TIPS real yield %, liquidity discount rate

breakeven_5y5y() → number
  // 5Y5Y forward inflation expectation %, Fed credibility gauge
```

**Blackout Flags:**
```typescript
fed_blackout() → boolean
  // True if within FOMC blackout window

cpi_release_today() → boolean
  // True if CPI scheduled today

earnings_blackout() → boolean
  // True if any held position has earnings within ±2h
```

### Category 5: OPTIONS / DERIVATIVES (5 primitives)

```typescript
iv_rank(symbol: string) → number
  // IV percentile (0-100), >80 = elevated vol, <20 = depressed

iv_percentile(symbol: string) → number
  // % of days in past year with lower IV

put_call_ratio(symbol: string) → number
  // Volume ratio; >1 = bearish (more puts), <1 = bullish

gamma_exposure(symbol: string) → number
  // Dealer gamma exposure (normalized); negative = dealer short gamma

options_volume_ratio(symbol: string) → number
  // Options volume / avg daily volume; >2 = unusual flow
```

### Category 6: POSITION STATE (3 primitives)

```typescript
position_pnl_pct() → number
  // Current open-position P&L %

position_age_hours() → number
  // Hours since position opened

account_drawdown_pct() → number
  // Current drawdown % from account peak equity
```

### Category 7: SIZING HELPERS (4 primitives)

```typescript
kelly(win_prob: number, payoff_ratio: number, max_position_usd: number, fraction?: number) → number
  // Full Kelly Criterion: f* = (p * b - q) / b
  // where p = win probability, b = payoff ratio (avg_win / avg_loss), q = 1 - p
  // fraction: Optional, defaults to 0.5 (half-Kelly for risk management)
  // Returns: clamped fraction * max_position_usd
  // Fixed 2026-04-23: Now uses proper formula instead of simplified edge * cap

kelly_regime_aware(win_prob: number, payoff_ratio: number, max_position_usd: number) → number
  // Added 2026-05-04: Regime-aware Kelly with automatic fraction scaling
  // Uses detectCurrentRegime() to determine market regime
  // Regime-based Kelly fractions:
  //   BULL:      0.50 (most aggressive)
  //   SIDEWAYS:  0.40
  //   RECOVERY:  0.35
  //   BEAR:      0.30
  //   CRISIS:    0.25 (most conservative)
  // Formula: kelly_fraction * (p * b - q) / b * max_position_usd
  // Automatically reduces position sizing during high-risk regimes

fixed_usd(amount: number) → number
  // Fixed dollar amount sizing

risk_pct(pct: number) → number
  // Size position to risk N% of account on this trade (uses stop distance)
```

### Category 8: COMPOSERS (3 primitives)

```typescript
all(...booleans) → boolean
  // AND of all args

any(...booleans) → boolean
  // OR of all args

xor(a: boolean, b: boolean) → boolean
  // Exactly one of two booleans
```

### Category 9: PRICE-ACTION PATTERNS (12 primitives)

**Support/Resistance:**
```typescript
support_level(lookback: number) → number
  // Lowest swing low in lookback bars

resistance_level(lookback: number) → number
  // Highest swing high in lookback bars

swing_high(lookback: number, nth: number = 1) → number
  // Nth most recent swing high

swing_low(lookback: number, nth: number = 1) → number
  // Nth most recent swing low
```

**Consolidation/Clusters:**
```typescript
cluster_high(lookback: number) → number
  // High of consolidation zone

cluster_low(lookback: number) → number
  // Low of consolidation zone

cluster_mid(lookback: number) → number
  // Midpoint of consolidation zone

in_cluster(lookback: number) → boolean
  // True if current price within cluster

cluster_breakout_up(lookback: number) → boolean
  // Price broke above cluster (this bar)

cluster_breakout_down(lookback: number) → boolean
  // Price broke below cluster (this bar)
```

**Level Testing:**
```typescript
broke_above(level: number, bars_ago: number) → boolean
  // Close crossed above level within bars_ago bars

broke_below(level: number, bars_ago: number) → boolean
  // Close crossed below level within bars_ago bars

retested(level: number, tolerance_pct: number) → boolean
  // Price within tolerance_pct% of level

holding_above(level: number) → boolean
  // Current price > level

holding_below(level: number) → boolean
  // Current price < level

price_at_level(level: number, tolerance_pct: number) → boolean
  // Price within tolerance_pct% of level
```

### Category 10: CROSS-ASSET (2 primitives)

```typescript
spread(a: number, b: number) → number
  // a - b (for pairs/spreads)

ratio(symbol1: string, symbol2: string, duration: string|number) → number
  // Hedge ratio (v1: returns 1.0, TODO: implement historical correlation)
```

---

## SECTION 3: BACKTEST ENGINE

**File:** `packages/be/src/backtest/engine.ts`

### Signal Evaluation (5 calculations)

| Function | Behavior | Lookback |
|----------|----------|----------|
| `calculatePercentChange` | `(current - past) / past * 100` | Configurable period |
| `calculateMovingAverage` | Sum last N bars / N | Configurable period |
| `calculateRSI` | `100 - 100/(1+RS)` where RS = avgGain/avgLoss | 14 default |
| `calculateVolatility` | stdDev of returns * sqrt(period) | Configurable |
| `calculateMomentum` | current - past | Configurable period |

### Crossover Detection

```typescript
checkCrossover(direction: 'above' | 'below')
  // Compare prev short MA vs prev long MA
  // Compare curr short MA vs curr long MA
  // direction='above' → prev ≤ long AND curr > long
  // direction='below' → prev ≥ long AND curr < long
```

### Position Sizing

```typescript
calculatePositionSize(strategy, equity, price):
  switch (config.type):
    'fixed' → fixed dollar amount
    'percent_equity' → equity * percentOfEquity%
    'volatility_adjusted' → equity * 50% (simplified)
    'kelly' → simplified Kelly fraction (not full formula)
  // Caps with min/max position size limits
```

### Backtest Loop

```
for each bar from warmup_period to end:
  if in_position:
    - Check exit rules (boolean evaluation)
    - Check stop loss: PL <= -stopLossPercent
    - Check take profit: PL >= takeProfitPercent
    - If exit: close at slippaged price, record trade

  if not in_position:
    - Check entry rules (boolean evaluation)
    - If enter: open at slippaged price, calculate position

  - Calculate current equity = cash + position_value
  - Record equity point + daily/cumulative return
  - Calculate benchmark value if available
```

### Slippage & Commissions

```typescript
calculateSlippage:
  base_slippage * typeMultiplier * sizeImpact * volMultiplier * randomFactor

  // Defaults by asset class (basis points):
  // - stock: 5 bps
  // - etf: 3 bps
  // - crypto: 15 bps
  // - forex: 2 bps

// Commission schedule (basis points):
  // - stock/etf: 0
  // - crypto: 10 maker, 25 taker
  // - forex: 2 maker, 5 taker
```

---

## SECTION 4: TRADE EXECUTION SERVICE

**File:** `packages/be/src/trading/services/trade-execution.ts`

### Slippage Calculation (Almgren-Chriss Model, updated 2026-04-23)

```typescript
calculateSlippage(assetClass, orderValue, tradeType, volatility, mode, avgDailyVolume?):

  // 1. BID-ASK SPREAD COMPONENT (added 2026-04-23)
  spreadBps = TYPICAL_SPREADS[assetClass][liquidityTier] / 2  // Half-spread for crossing

  // 2. MARKET IMPACT (Almgren-Chriss square-root model, fixed 2026-04-23)
  participation = orderValue / avgDailyVolume
  permanentImpact = 0.1 * volatility * sqrt(participation)
  temporaryImpact = volatility * sqrt(participation) * urgencyMultiplier
  impactBps = (permanentImpact + temporaryImpact) * 10000

  // 3. BASE SLIPPAGE + MODIFIERS
  baseBps = BASE_SLIPPAGE[assetClass]
  typeMultiplier = market ? 1.5 : 1.0
  volMultiplier = 1 + volatility * 5

  // CRITICAL: mode gates randomness
  randomFactor = mode === 'live' ? 1.0 : (0.8 + random() * 0.4)

  totalBps = spreadBps + impactBps + (baseBps * typeMultiplier * volMultiplier * randomFactor)
  return totalBps / 10000    // Convert to decimal
```

**Bid-Ask Spread Tiers (basis points):**
```typescript
TYPICAL_SPREADS = {
  stock:     { tight: 1, normal: 3, wide: 10 },   // Large-cap to small-cap
  etf:       { tight: 1, normal: 2, wide: 5 },
  crypto:    { tight: 5, normal: 15, wide: 50 },  // BTC/ETH to altcoins
  forex:     { tight: 0.5, normal: 1, wide: 3 },  // Majors to exotics
  index:     { tight: 1, normal: 2, wide: 5 },
  commodity: { tight: 2, normal: 5, wide: 15 },
}
```

**Mode Semantics:**
- `'mock' | 'backtest' | 'paper'` → adds ±20% jitter for realism
- `'live'` → DETERMINISTIC (no randomness; real fill from exchange)

### Time-of-Day Liquidity Adjustment (Added 2026-04-23)

```typescript
calculateTimeOfDayLiquidityMultiplier(hour, assetClass, exchange = 'US'):
  // US Equities (NYSE/NASDAQ):
  //   09:30-10:00 (first 30 min):     1.3x spread (opening volatility)
  //   10:00-11:30:                    1.0x (normal)
  //   11:30-14:00 (lunch):            1.2x (thin liquidity)
  //   14:00-15:30:                    1.0x (normal)
  //   15:30-16:00 (last 30 min):      1.25x (closing auction)
  //   Pre/post market:               1.5x (sparse liquidity)

  // Crypto (24/7):
  //   00:00-04:00 UTC:               1.2x (Asia dominant)
  //   04:00-08:00 UTC:               1.1x (EU wakeup)
  //   08:00-14:00 UTC:               1.0x (EU+US overlap, best)
  //   14:00-21:00 UTC:               1.0x (US dominant)
  //   21:00-24:00 UTC:               1.15x (US closing)

getCurrentLiquidityMultiplier(assetClass):
  // Returns current multiplier based on server time
```

**Integration:** Slippage calculation multiplies base slippage by `timeOfDayMultiplier` when option enabled.

### Participation Rate Limits (Added 2026-05-04)

```typescript
MAX_PARTICIPATION_RATE = {
  stock:     0.03,   // 3% of ADV - conservative
  etf:       0.05,   // 5% - market makers provide liquidity
  crypto:    0.02,   // 2% - fragmented liquidity, manipulation risk
  forex:     0.10,   // 10% - very deep markets
  index:     0.05,   // 5% - via futures/ETFs
  commodity: 0.03,   // 3% - moderate liquidity
}

checkParticipationRate(assetClass, orderValue, avgDailyVolume):
  // Returns { passes, participationRate, maxRate, recommendedOrderValue, warning }
  // Warns at 70% of limit, fails above limit
  // Orders exceeding limit risk detection and adverse selection

adjustOrderForParticipation(assetClass, desiredValue, avgDailyVolume):
  // Returns adjusted order size that complies with participation limit
```

**Why this matters:**
- Orders >5% of ADV trigger whale-watcher algorithms
- Large orders cause permanent market impact (prices move against you)
- Creates adverse selection (informed traders front-run)

### Fee Calculation

```typescript
calculateFees(assetClass, orderValue, isMaker):
  feeBps = isMaker ? fees.maker : fees.taker
  calculatedFee = (feeBps / 10000) * orderValue
  return max(calculatedFee, $0.01)    // $0.01 minimum
```

### Execution Price

```typescript
calculateExecutionPrice(requestedPrice, side, slippage):
  slippageDirection = side === 'buy' ? +1 : -1
  return requestedPrice * (1 + slippage * slippageDirection)
```

---

## SECTION 5: POSITION SERVICE

**File:** `packages/be/src/trading/services/position-service.ts`

### Position Sizing from Balance

```typescript
if percentOfBalance:
  availableBalance = portfolio.currentBalance
  positionValue = (percentOfBalance / 100) * availableBalance
  positionQuantity = positionValue / price

// Risk Metrics (calculated at open):
  riskAmount = |entryPrice - stopLoss| * quantity
  riskPercent = (riskAmount / balance) * 100
  rewardRiskRatio = |takeProfit - entryPrice| / |entryPrice - stopLoss|
```

### Stop Loss Types

| Type | Formula |
|------|---------|
| `fixed` | User-provided stop price |
| `trailing` | High-water mark * (1 - trailingStopPercent%) |
| `break_even` | Triggers at activation PL, moves to entry |
| `time_based` | Exits if held > max_holding_hours |

### Take Profit Types

| Type | Behavior |
|------|----------|
| `fixed` | User-provided target |
| `trailing` | Locks in gains as price rises |
| `partial` | Multiple TP levels, close N% at each |

---

## SECTION 6: SIGNAL GENERATION

**File:** `packages/be/src/trading/services/signal-generator.ts`

### Algorithm Weights (Learned/Configurable)

```typescript
DEFAULT_ALGORITHM_WEIGHTS:
  lstm: 0.20
  xgboost: 0.18
  arima: 0.12
  garch: 0.10
  random_forest: 0.15
  technical: 0.12
  sentiment: 0.08
  ensemble: 0.05
```

### Confidence Thresholds

```typescript
CONFIDENCE_THRESHOLDS:
  strong: 0.75     // High conviction → larger position
  moderate: 0.55   // Medium conviction
  weak: 0.35       // Low conviction or hedge
```

### Signal Generation

```typescript
generateSignal(request):
  riskRewardRatio = |targetPrice - entryPrice| / |entryPrice - stopLoss|
  expiresInHours = request.expiresInHours (default 24)

  // Stores to trading.trade_signals:
  //   - symbol, asset_class, direction (long/short/neutral)
  //   - strength, confidence, expected_magnitude
  //   - timeframe, entry/target/stop prices
  //   - risk_reward_ratio
  //   - ensemble_prediction, algorithm_votes
  //   - contributing_factors, data_sources
```

### Adaptive Ensemble Weights (Added 2026-04-23)

```typescript
// Regime-specific algorithm performance (empirically calibrated)
REGIME_ALGORITHM_WEIGHTS = {
  BULL: {
    lstm: 0.25,        // Trend-following works
    sentiment: 0.20,   // FOMO signals correlate
    technical: 0.15,
    xgboost: 0.15,
    random_forest: 0.10,
    garch: 0.05,       // Vol models less useful
    arima: 0.05,
    ensemble: 0.05,
  },
  BEAR: {
    garch: 0.25,       // Volatility clustering dominates
    xgboost: 0.20,
    random_forest: 0.15,
    lstm: 0.10,
    technical: 0.10,
    sentiment: 0.08,   // Contrarian (low weight)
    arima: 0.07,
    ensemble: 0.05,
  },
  SIDEWAYS: {
    arima: 0.25,       // Mean reversion works
    technical: 0.25,   // Range patterns
    // ...others reduced
  },
  CRISIS: {
    garch: 0.30,       // Vol models critical
    xgboost: 0.20,
    // All algorithms reduced confidence via getRegimeConfidenceMultiplier()
  },
  RECOVERY: {
    lstm: 0.22,
    sentiment: 0.20,   // Optimism returning
    // ...balanced weights
  },
}

getAdaptiveAlgorithmWeights(regime: MarketRegime): Record<string, number>
  // 1. Get base regime weights
  // 2. Apply online learning adjustments from recent accuracy
  // 3. Return normalized weights

updateAdaptiveAlgorithmPerformance(algorithmId, correct: boolean): void
  // Rolling accuracy update for online learning
  // Uses 20-prediction sliding window

getRegimeConfidenceMultiplier(regime: MarketRegime): number
  // CRISIS → 0.6 (reduce all confidence by 40%)
  // BULL → 1.1 (slight boost)
  // RECOVERY → 1.05
  // BEAR, SIDEWAYS → 1.0
```

---

## SECTION 7: HUMAN-VS-AUTOMATION COMPOSITE SCORE

**File:** `packages/be/src/insights/composite-score.ts`

### Sub-Inputs (5 Today)

#### Sub-Input 1: Divergence (All Asset Classes)

```typescript
scoreDivergence(classification):
  HUMAN-DRIVEN       → vote = +1.0, weight = 1.0 * max(0.4, conf)
  SOCIAL-NOISE       → vote = +0.4, weight = 0.6 * max(0.4, conf)
  BOT-LIKELY         → vote = -1.0, weight = 1.0 * max(0.4, conf)
  QUIET              → vote =  0.0, weight = 0.2
  INSUFFICIENT       → null (skipped)
```

#### Sub-Input 2: Crypto Funding Rate Extremity (Crypto Only)

```typescript
scoreCryptoFunding(symbol):
  EXTREME_PCT = 0.05% (8h rate)

  magnitude ≥ 0.05%:
    vote = -min(1, magnitude / 0.10)     // Bot-dominated leverage

  magnitude ≥ 0.025%:
    vote = -0.3                           // Elevated

  magnitude < 0.025%:
    vote = +0.2                           // Balanced (human)

  weight: 0.7
```

#### Sub-Input 3: VIX Regime Bias (Equities/ETF/Index)

```typescript
scoreVixRegime():
  VIX_RISKOFF_PERCENTILE = 75
  VIX_LOWVOL_PERCENTILE = 25

  percentile ≥ 75:
    vote = -0.4     // Risk-off, algo de-risking

  percentile ≤ 25:
    vote = +0.3     // Low-vol, human positioning

  25 < percentile < 75:
    vote = 0        // Normal regime

  weight: 0.3 (market-wide, not symbol-specific)
```

#### Sub-Input 4: Prediction-Market Arb-Bot Activity (Market-Wide)

```typescript
scoreArbBotActivity():
  // Reads latest arb_bot_metrics row
  vote = botActivityScore (pre-computed)
  weight: 0.25 (lower weight for market-wide signals)
```

#### Sub-Input 5: Volume Anomaly Classifier (Stocks/ETF/Crypto)

```typescript
scoreVolumeAnomaly(symbol, assetClass):
  VOLUME_WINDOW_DAYS = 30
  VOLUME_EXTREME_Z = 3.0
  VOLUME_ELEVATED_Z = 2.0

  today_z = (today_volume - mean_volume) / stddev_volume

  absZ ≥ 3.0:
    if (sentiment moved):
      vote = +0.3   // Capital-backed conviction
    else:
      vote = -0.4   // Algo / liquidation / rebalance

  2.0 ≤ absZ < 3.0:
    vote = -0.2     // Elevated flow, likely algo

  absZ < 2.0:
    null            // Skip (normal volume)

  weight: 0.4
```

### Aggregation

```typescript
// COMPOSITE SCORE CALCULATION:

score = sum(vote_i * weight_i) / sum(weight_i)

// Range: [-1, +1]
//   +1 = human-dominated
//    0 = ambiguous
//   -1 = bot-dominated

// Label mapping:
//   score ≥ 0.50 + conf ≥ 0.30   → human-driven
//   0.15 ≤ score < 0.50          → human-leaning
//   -0.15 < score < 0.15         → neutral
//   -0.50 < score ≤ -0.15        → bot-leaning
//   score ≤ -0.50                → bot-driven
//   conf < 0.30                  → unclassified

// CONFIDENCE CALCULATION:
//   attempted = #subScores + #failed_attempts (excluding -not-applicable, -no-data)
//   fired = #subScores that produced votes
//   confidence = fired / attempted ∈ [0, 1]

// INPUT HASH:
//   SHA256(symbol:assetClass:name1=vote1:weight1;name2=vote2:weight2;...)
//   Used for skip-recompute on unchanged inputs
```

---

## SECTION 8: TICK-LEVEL WHALE / BOT CLASSIFIER

**File:** `packages/be/src/insights/tick-classifier.ts`

### Three Core Signals

#### Signal 1: Whale Ratio

```typescript
whaleRatio = whaleVolume / totalVolume

// where:
//   whaleVolume = sum of trades in top 5% by size

// Interpretation:
//   > 0.40   → Institutional/whale activity
//   0.25-0.40 → Moderate
//   < 0.25   → Retail flow
```

#### Signal 2: Bot Signature Score (Composite)

```typescript
// Combines three heuristics:

// 1. Round-number clustering:
roundNumberRatio = (# of trades divisible by 10/100/1000) / total

// 2. Repeated-size clustering:
//    Top-3 most common sizes accounting for > X% of trades
repeatedSizeFraction = top3Count / totalTrades

// 3. Sub-second burst timing:
subSecondBurstRatio = (# of trades within 100ms windows) / total

botSignatureScore = weighted average of the three
// Higher = more algorithmic (round numbers, repetition, timing precision)
```

#### Signal 3: Aggressor Imbalance

```typescript
aggressorImbalance = (aggressiveBuyVolume - aggressiveSellVolume) / totalVolume

// Range: [-1, +1]
//   +1 = all buys (bullish pressure)
//    0 = balanced
//   -1 = all sells (bearish pressure)

// Note: Requires aggressor direction (isBuyerMaker on Binance;
//       tick-rule inference needed for Polygon equities)
```

#### Signal 4: VPIN (Volume-Synchronized Probability of Informed Trading) — Added 2026-04-23

```typescript
// Reference: Easley, López de Prado & O'Hara (2012)
// Real-time toxicity measure predicting flash crashes

calculateVPIN(trades: TradeRecord[], bucketVolume: number): number
  // Divides trades into equal-volume buckets
  // Calculates order imbalance within each bucket
  // Returns: average |buyVol - sellVol| / (buyVol + sellVol) across buckets

  // Interpretation:
  //   0.0 - 0.3: Normal balanced flow
  //   0.3 - 0.5: Elevated toxicity
  //   0.5 - 0.7: High toxicity (flash crash risk)
  //   > 0.7: Critical toxicity (likely adverse selection)
```

#### Signal 5: Kyle's Lambda (Price Impact Coefficient) — Added 2026-04-23

```typescript
// OLS regression of price changes on signed order flow
// High lambda = illiquid market OR informed trading presence

calculateKylesLambda(trades: TradeRecord[]): { lambda: number; r2: number }
  // lambda: Price change (bps) per unit of signed volume
  // r2: Regression quality (0-1)

  // Interpretation:
  //   lambda < 0.001: High liquidity, market maker dominated
  //   lambda 0.001-0.01: Normal microstructure
  //   lambda > 0.01: Low liquidity OR informed traders present
```

#### Signal 6: Order Size Bimodality Analysis — Added 2026-04-23

```typescript
analyzeOrderSizeDistribution(sizes: number[]): {
  bimodalityCoefficient: number;  // Sarle's B: (skewness² + 1) / (kurtosis + 3)
  isBimodal: boolean;             // B > 0.555 threshold
  flowType: 'retail_dominated' | 'institutional_dominated' | 'mixed_flow' | 'unknown';
  retailMode?: number;            // Peak 1 (smaller orders)
  institutionalMode?: number;     // Peak 2 (larger orders)
  retailFraction: number;         // % volume from retail-sized orders
}

// Interpretation:
//   B < 0.555: Unimodal (one dominant participant type)
//   B > 0.555: Bimodal (distinct retail + institutional modes)
//   retailFraction > 0.7: Retail dominated
//   retailFraction < 0.3: Institutional dominated
```

#### Signal 7: Advanced Bot Detection Features — Added 2026-04-23

```typescript
calculateAdvancedBotFeatures(trades): {
  // ML-grade features for bot detection
  interarrivalVariance: number;       // Low variance = algorithmic timing
  priceClusteringRatio: number;       // Round number clustering (0-1)
  sequentialImprovement: number;      // Price improvement on sequential trades
  evenLotRatio: number;               // Trades divisible by 100
  trailingDigitEntropy: number;       // Entropy of last digit (high = human, low = algo)
  advancedBotScore: number;           // Composite 0-1 (higher = more algorithmic)
}

// Features inspired by academic literature on bot detection
// Can be used as inputs to ML classifier
```

### Whale Classification (6 Buckets)

| Label | Criteria | Confidence |
|-------|----------|------------|
| **retail** | whaleRatio < 0.25 AND botSignature < 0.30 | (slack_whale + slack_bot) / 2 |
| **market_maker** | botSignature ≥ 0.55 AND \|imbalance\| ≤ 0.15 | Ratio of how far above thresholds |
| **fund_rebalance** | whaleRatio ≥ 0.40 AND botSignature ≤ 0.50 AND imbalance ∈ [0.20, 0.80] | Composite of all three |
| **liquidation_cascade** | whaleRatio ≥ 0.40 AND botSignature ≥ 0.50 AND imbalance ≤ -0.35 | Weighted: 0.4*whale + 0.3*bot + 0.3*imbalance |
| **coordinated** | botSignature ≥ 0.70 AND \|imbalance\| ≥ 0.45 | Conservative threshold |
| **unknown_flow** | Aggressor direction unknown (Polygon equities until tick-rule inference) | N/A |

---

## SECTION 9: ALGORITHM EXECUTOR (PAPER/LIVE MODE)

**File:** `packages/be/src/algorithms/paper/executor.ts`

### Run Lifecycle

```
startRun(algorithmId, mode='paper'|'live', options):
  1. Load strategy AST from latest version
  2. Seed default guardrails (L1) if not present
  3. If live: preflight check (broker key, MFA, platform kill-switch)
  4. Insert row: predict.algorithm_runs (mode, started_at)

tickRun(runId):
  1. Load strategy AST
  2. Fetch current price snapshot + recent OHLC window
  3. Build EvalContext at snapshot timestamp (asOf-frozen, no look-ahead)
  4. Evaluate entry/exit rules via DSL evaluator
  5. If entry signal:
     a. Calculate position size (kelly / fixed_usd / risk_pct)
     b. Calculate slippage via calculateSlippage(mode)
     c. Simulate or execute via broker
     d. Insert predict.algorithm_trades row
  6. If exit signal or stop-loss/take-profit hit:
     a. Close position at slippaged price
     b. Calculate P&L
     c. Insert predict.algorithm_trades row
  7. Evaluate L1 guardrails
     - If breach: recordKill(), set ended_at, halt run
  8. Append predict.algorithm_telemetry row (equity, daily_return)

stopRun(runId, reason):
  1. Set ended_at = NOW()
  2. Close any open position
  3. Calculate final metrics
  4. Archive to algorithm_run_results
```

### Stop Conditions (Risk Control)

```typescript
loadStopConditions(algorithmId):
  maxRunDurationHours: number | null
  profitTargetPct: number | null
  maxTradesPerRun: number | null
  stopOnConsecutiveLosses: number | null
  stopOnConsecutiveWins: number | null
```

### Run Counters

```typescript
loadRunCounters(runId):
  tradeCount: number
  consecutiveLosses: number
  consecutiveWins: number
```

---

## SECTION 10: GUARDRAILS (5-LAYER HIERARCHY)

**File:** `packages/be/src/algorithms/guardrails/service.ts`

### Layer 1: Hard Account Guardrails (L1 — Implemented)

```typescript
DEFAULT_ACCOUNT_GUARDRAILS:
  {
    kind: 'max_daily_loss_pct',      threshold: 2,     hard: false
    kind: 'max_drawdown_pct',        threshold: 10,    hard: true
    kind: 'max_leverage',            threshold: 1,     hard: true
    kind: 'max_position_usd',        threshold: 10000, hard: false

    // Added 2026-05-04 (Expert Audit):
    kind: 'max_gross_exposure_pct',  threshold: 200,   hard: true   // 2x leverage max
    kind: 'max_net_exposure_pct',    threshold: 100,   hard: false  // Fully directional max
    kind: 'max_intraday_var_pct',    threshold: 5,     hard: false  // 95% VaR budget
  }

// Hard=true: Cannot be modified except via direct SQL admin.
//            Protected by database trigger: protect_hard_guardrails
```

### Intraday VaR Monitoring (Added 2026-05-04)

```typescript
calculateIntradayVaR(runId, confidence = 0.95):
  // Historical simulation using 5-min equity snapshots
  // Returns { varPct, sampleSize }

shouldCheckIntradayVaR(runId):
  // Returns true every 15 minutes (cached check)

checkIntradayVaR(runId, guardrails):
  // Returns GuardrailBreach if VaR exceeds max_intraday_var_pct threshold

calculateExposureMetrics(positions, currentEquity):
  // Returns { grossExposure, netExposure, grossPct, netPct }
  // grossExposure = Σ |position_value|  (long + short absolute)
  // netExposure = Σ position_value      (long - short)
```

### Layer 2: Per-Strategy Circuit Breakers (L2 — Sprint 4)

```typescript
// TBD: Consecutive loss tracking, Sharpe degradation detection
```

### Layer 3: Time / Event Blackouts (L3 — Sprint 3.5)

```typescript
// TBD: Earnings blackout, FOMC blackout windows
```

### Layer 4: LLM-Detected Anomalies (L4 — Sprint 4)

```typescript
// TBD: Slippage surge detection, regime shift alerts
```

### Layer 5: Manual Panic Button (L5 — Implemented)

```typescript
recordKill(userId, runId, algorithmId, reason, trigger='manual'):
  1. Set algorithm_runs.ended_at = NOW()
  2. Close all open positions
  3. Insert predict.algorithm_kill_log row
  4. Archive results
```

---

## SECTION 11: LLM-JURY SYSTEM (DEFENSE 5)

**File:** `packages/be/src/algorithms/llm/jury.ts`

### Three-Model Architecture (Updated 2026-05-04)

**Temperature Scheduling:**
```typescript
DEFAULT_JURY_TEMPERATURES = {
  proposer: 0.4,   // Creative enough to propose improvements
  critic: 0.5,     // Creative to find edge cases (was 0.0 - too restrictive)
  judge: 0.1,      // Near-deterministic for consistency (was 0.0)
}
```

**Blind Jury Pattern (Defense against anchoring bias):**
The Judge does NOT see the critic's detailed text. This prevents anchoring bias
where the judge is influenced by how the critic framed concerns.

```
┌─────────────────────────────────────────────────────────────────┐
│ PROPOSER (Claude Opus, t=0.4)                                   │
│ - Creative, generates modification proposal                     │
│ - Max 10 parameter changes                                      │
│ - Must stay within self_modify.bounds                           │
│ - Returns: ProposalSchema                                       │
│   { diff_description, parameter_changes[], expected_improvement,│
│     risk_note, confidence ∈ [0,1] }                             │
└──────────────────────┬──────────────────────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────────────────────┐
│ CRITIC (Claude Opus, t=0.5)                                     │
│ - Adversarial, "find what's wrong"                              │
│ - Higher temp to find edge cases (was 0.0)                      │
│ - Check for regime-specific tuning                              │
│ - Returns: CritiqueReviewSchema                                 │
│   { disagreements[], summary, confidence ∈ [0,1] }              │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       │ BLIND JURY: Only summary stats passed ↓
                       │ (not critic's text - prevents anchoring)
                       │
┌──────────────────────▼──────────────────────────────────────────┐
│ JUDGE (Claude Haiku, t=0.1)                                     │
│ - Near-deterministic for consistent rulings                     │
│ - Receives ONLY:                                                │
│   • criticalIssues: count                                       │
│   • warningIssues: count                                        │
│   • infoIssues: count                                           │
│   • criticConfidence: number                                    │
│   • (NOT the critic's narrative text)                           │
│ - Apply 0.85 confidence threshold (Defense 6)                   │
│ - Returns: JudgeSchema                                          │
│   { decision: 'accept'|'reject'|'escalate_human',               │
│     reason, applied_confidence_threshold }                      │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
         DB: predict.algorithm_llm_jury
         (All three outputs + prompt hashes logged)
```

### Confidence Gate (Defense 6)

```typescript
if min(proposer.confidence, critic.confidence) < 0.85:
  decision = 'escalate_human'
else:
  // (judge weighs material from proposer + critic)
```

---

## SECTION 12: ALL-SEEING-EYE SYSTEM

**File:** `packages/be/src/all-seeing-eye/index.ts`

### Orchestration Cycle

```
runCycle():
  1. aggregateAllData()
     - Market data (prices, volumes, spreads)
     - AI predictions (all-seeing-eye ensemble)
     - Sentiment data (social, news)
     - Derivatives data (VIX, funding, IV)
     - Prediction markets (Polymarket, Kalshi, etc.)
     - Trust layer metrics
     - Algorithm performance
     - Price action patterns

  2. generateInsights()
     - Build correlation matrix
     - Ensemble prediction
     - Reasoning engine
     - Validate insights (dual-layer analysis)

  3. runBlackSwanDetection()
     - Anomaly detection (Z-score > 3.5 sigma)
     - Correlation breaks (> 0.3 shift)
     - Event type classification (12 types)
     - Historical pattern matching
     - Severity assessment

  4. generateActionsFromInsight()
     - Risk assessment
     - Guardrail check
     - Action proposal (entry, exit, hedge, allocation shift)

  5. checkGuardrails()
     - All-Seeing-Eye guardrails (platform-wide)
     - Per-strategy guardrails
     - Circuit breakers
     - Position limits

  6. executeAction() / approveAction() / rejectAction()
     - Mode-aware execution
     - Paper / live routing
     - Broker adapter call
     - Trade logging

  7. emitRealtime()
     - SSE events to clients
     - Probability updates
     - Validation results
     - Black-swan warnings
```

### Black Swan Detector

**File:** `packages/be/src/all-seeing-eye/black-swan/detector.ts`

```typescript
ANOMALY_Z_SCORE_THRESHOLD = 3.5 // sigma
CORRELATION_BREAK_THRESHOLD = 0.3
MIN_ANOMALOUS_SIGNALS = 3

// Event Types (12):
//   - market_crash         (S&P, NASDAQ, DOW, VIX)
//   - flash_crash          (S&P, VIX, volume)
//   - liquidity_crisis     (Treasury, spread, credit)
//   - currency_crisis      (DXY, EURUSD, emerging)
//   - geopolitical         (Gold, Oil, defense, VIX)
//   - pandemic             (Healthcare, travel, retail, sentiment)
//   - infrastructure       (Utilities, tech, cloud)
//   - cyber                (Tech, security, crypto)
//   - natural_disaster     (Insurance, utilities, REITs)
//   - regulatory           (Crypto, fintech, banking)
//   - contagion            (Emerging, HY, spread)
//   - systemic             (Banking, financial, credit)

// Detection logic:
//   1. Calculate Z-scores for all data points
//   2. If ≥3 signals breach ANOMALY_Z_SCORE_THRESHOLD OR max Z > 5.25:
//      → isAnomaly = true
//
//   3. Build correlation matrix vs historical baseline
//   4. If any pair has |Δcorr| > 0.3:
//      → Correlation break
//
//   5. Match to event-type pattern (signal names + correlation signs)
//   6. Find closest historical match (via cosine similarity)
//   7. Calculate severity = weighted average of signal extremity
```

### Forward-Looking Black Swan Signals (Added 2026-04-23)

#### Yield Curve Inversion Detector

```typescript
detectYieldCurveInversion(): Promise<BlackSwanSignal | null>
  // Monitors three key yield spreads:
  //   - 3M-10Y spread (Fed's preferred recession gauge)
  //   - 2s10s spread (traditional recession indicator)
  //   - 5s30s spread (term premium / long-end steepening)

  // Alert thresholds:
  //   3M-10Y < 0:    HIGH severity (recession signal)
  //   2s10s < -10bp: MEDIUM severity (recession warning)
  //   5s30s < -25bp: LOW severity (term premium concern)
```

#### Credit Spread Breakout Detector

```typescript
detectCreditSpreadBreakout(): Promise<BlackSwanSignal | null>
  // Monitors credit stress indicators:
  //   - HY spread: High-yield OAS (Option-Adjusted Spread)
  //   - IG spread: Investment-grade OAS
  //   - HY/IG ratio: Relative stress

  // Alert conditions:
  //   HY > 80th percentile AND widening by >10% week-over-week
  //   HY/IG ratio spike (credit quality divergence)
```

#### Intermarket Divergence Detector

```typescript
detectIntermarketDivergence(): Promise<IntermarketDivergence[]>
  // Monitors correlation breaks between normally-correlated assets:
  //   - SPY/TLT (stocks vs bonds, normally -0.3 to -0.5)
  //   - GLD/DXY (gold vs dollar, normally -0.6)
  //   - VIX/SPY (fear vs market, normally -0.7)

  // Alert: |recent_corr - historical_corr| > 0.4
  // Indicates: Regime change, liquidity crisis, or structural break
```

---

## SECTION 13: RISK MANAGEMENT FEATURES

### Position-Level Stops

```typescript
// Stop Loss Types:
//   - fixed:        Price-level stop
//   - trailing:     Triggered at N%, moves to entry on down-move
//   - break_even:   Activation price, then follows to entry +offset
//   - time_based:   Exits if held > max_holding_hours

// Take Profit Types:
//   - fixed:        Target price
//   - trailing:     Locks gains as price rises
//   - partial:      Multiple TP levels, close % at each

// Scaling:
//   - Scale in:     Add to position at N% down
//   - Partial TP:   Close N% at each TP level
//   - Trailing:     High-water mark tracking
```

### Account-Level Limits

```
Hard Guardrails (L1):
  - max_drawdown_pct: 10%         (hard=true, DB-protected)
  - max_leverage: 1.0x            (hard=true)

Soft Guardrails (Modifiable):
  - max_daily_loss_pct: 2%
  - max_position_usd: $10,000
  - max_pair_notional: [per pair]
  - correlation_floor: [minimum diversification]
```

### Portfolio Correlation Monitor (Added 2026-04-23)

**File:** `packages/be/src/trading/services/portfolio-correlation-monitor.ts`

```typescript
interface PortfolioCorrelationAnalysis {
  avgPairwiseCorrelation: number;   // Average correlation between all position pairs
  effectivePositions: number;        // Diversification ratio (HHI-based)
  concentrationRisk: number;         // Top 3 positions as % of portfolio
  diversificationScore: number;      // 0-100 composite score
  portfolioVolatility: number;       // Correlation-adjusted portfolio vol
  violations: CorrelationViolation[];
}

analyzePortfolioCorrelation(positions: Position[]): PortfolioCorrelationAnalysis
  // 1. Build pairwise correlation matrix
  // 2. Calculate average off-diagonal correlation
  // 3. Compute effective positions via Herfindahl-Hirschman Index
  //    effectiveN = 1 / sum(weight_i^2)
  // 4. Assess concentration risk (top 3 holdings)
  // 5. Calculate diversification score (0-100)
  // 6. Compute portfolio volatility with correlation adjustment

// Violation Types:
//   - high_correlation: avgCorr > 0.7
//   - concentration: top 3 > 60% of portfolio
//   - low_diversification: effectiveN < 3
```

### Risk Management Utilities (Added 2026-04-23)

**File:** `packages/be/src/trading/services/risk-management-utils.ts`

#### Volatility-Adjusted Position Sizing (Risk Parity)

```typescript
volatilityAdjustedPositionSize(
  targetVolContribution,  // e.g., 0.02 = 2% portfolio vol
  assetVolatility,        // e.g., 0.25 = 25% annualized
  portfolioValue,
  price
): { shares: number; dollarValue: number; volContribution: number }

// Equal risk allocation: assets with higher vol get smaller positions
// Standard institutional quant fund approach
```

#### Correlation-Aware Position Sizing

```typescript
correlationAdjustedSize(
  baseSize,
  correlationWithPortfolio,  // -1 to +1
  existingExposurePct        // 0 to 1
): { adjustedSize: number; reductionPct: number; reason: string }

// Diversification penalty: high correlation = reduced size
// Prevents concentration in correlated assets
// Up to 50% reduction for highly correlated positions
```

#### Days-to-Liquidate Calculation

```typescript
calculateDaysToLiquidate(
  positionValue,
  avgDailyVolume,
  maxParticipationRate = 0.10  // 10% of daily volume
): {
  daysToLiquidate: number;
  isIlliquid: boolean;
  liquidityRisk: 'low' | 'medium' | 'high' | 'critical';
  recommendation: string;
  dailyLiquidationCapacity: number;
}

// Risk classification:
//   ≤1 day:  low
//   2-3 days: medium
//   4-7 days: high
//   >7 days: critical
```

#### Portfolio Liquidity Risk Assessment

```typescript
assessPortfolioLiquidityRisk(positions[], maxParticipationRate):
  {
    totalValue: number;
    weightedDaysToLiquidate: number;
    illiquidPositions: Array<{symbol, daysToLiquidate, percentOfPortfolio}>;
    overallLiquidityRisk: 'low' | 'medium' | 'high' | 'critical';
  }
```

#### Tail Hedge Recommendations

```typescript
recommendTailHedge(portfolioVaR, portfolioValue, currentHedgeRatio, portfolioBeta):
  {
    action: 'buy_puts' | 'reduce_exposure' | 'add_bonds' | 'increase_cash' | 'no_action';
    urgency: 'low' | 'medium' | 'high';
    details: string;
    suggestedHedgeSize?: number;
    suggestedStrike?: string;    // e.g., '5% OTM'
    estimatedCost?: number;
  }

// Automatic hedge suggestions based on VaR threshold breaches
```

#### Comprehensive Position Sizing

```typescript
calculateOptimalPositionSize(symbol, params): PositionSizingRecommendation
  {
    symbol: string;
    baseSize: number;
    volatilityAdjustedSize: number;
    correlationAdjustedSize: number;
    liquidityConstrainedSize: number;
    finalRecommendedSize: number;        // Min of all constraints
    constraints: string[];               // Active limiting factors
  }
```

### Self-Modification Bounds

```typescript
SelfModifySpec:
  mode: 'manual' | 'llm-proposed-approved' | 'llm-autonomous'
  bounds:
    [
      { param, range: [min, max], max_change_per_24h, max_change_per_7d }
    ]
  forbidden_changes: [...params that can never auto-modify]
  rollback_trigger:
    [
      { metric: 'sharpe', threshold: 0.5, action: 'revert_24h' | 'revert_7d' | 'pause' | 'kill' }
    ]
```

---

## SECTION 14: DATA INTEGRITY & SAFETY

### No Look-Ahead Guarantee

```typescript
EvalContext {
  asOf: string                  // ISO timestamp of current bar
  bars?: OHLCVBar[]            // Only bars up to and including asOf
}

// Evaluator enforces:
//   - No access to future prices
//   - Indicators computed from bars[0..idx] only
//   - sentimentData has timestamp ≤ asOf
//   - All derived series (yield curves) computed at asOf
```

### Security & ID Generation

```typescript
// Use secureId() from packages/be/src/lib/ids.ts
// All security-sensitive IDs use crypto.randomBytes, not Math.random()

// Examples:
//   runId = secureId('run')          // 'run_<32 hex chars>'
//   tradeId = secureId('trade')
//   apiKeyId = secureId('apikey')
```

### Parameterized Queries

```typescript
// All database access uses parameterized queries
// Pattern: query<T>(sql, [param1, param2, ...])
// Never: string concatenation, template literals with user data
```

---

## SECTION 15: KEY CONSTANTS & THRESHOLDS

### Time Constants

| Constant | Value | Usage |
|----------|-------|-------|
| TRADING_DAYS_PER_YEAR | 252 | Annualization |
| RISK_FREE_RATE | 4% | Sharpe, Sortino, alpha |
| DEFAULT_VALIDITY_MINUTES | 30 | Composite score cache |
| RECENT_WINDOW_TRADES | 500 | Tick classifier window |

### Threshold Constants

| Threshold | Value | Purpose |
|-----------|-------|---------|
| FUNDING_EXTREME_PCT | 0.05% | Crypto funding extremity |
| VIX_RISKOFF_PERCENTILE | 75 | Risk-off regime |
| VIX_LOWVOL_PERCENTILE | 25 | Low-vol regime |
| VOLUME_EXTREME_Z | 3.0 | Volume spike detector |
| VOLUME_ELEVATED_Z | 2.0 | Moderate elevation |
| ANOMALY_Z_SCORE_THRESHOLD | 3.5 sigma | Black-swan detector |
| CORRELATION_BREAK_THRESHOLD | 0.3 | Correlation anomaly |
| WHALE_PERCENTILE | 95th | Top 5% by trade size |
| MIN_CONSENSUS_VOTES | 3 | Signal consensus |
| CONFIDENCE_STRONG | 0.75 | Signal strength gate |
| CONFIDENCE_MODERATE | 0.55 | Signal strength gate |
| CONFIDENCE_WEAK | 0.35 | Signal strength gate |
| LLM_JURY_CONFIDENCE_GATE | 0.85 | Defense 6 escalation |

---

## SECTION 16: EXECUTION MODES & DEFAULTS

### Execution Mode Gating

```typescript
getUserExecutionMode(userId):
  // Returns: 'mock' (default) | 'paper' | 'live'

  // - mock:   $100k simulated capital, full slippage/fees, no broker
  // - paper:  $100k simulated capital, deterministic slippage, no broker
  // - live:   real broker, real capital, real fills (MFA-gated)
```

### Mode-Aware Slippage

```
'mock' / 'paper' / 'backtest':
  slippageRandomFactor = 0.8 + Math.random() * 0.4  // ±20% jitter

'live':
  slippageRandomFactor = 1.0  // DETERMINISTIC
  // (Real fill from broker, not synthesized)
```

---

## SECTION 17: DATABASE PERSISTENCE

### Key Tables

| Table | Purpose | Critical Fields |
|-------|---------|-----------------|
| `predict.algorithm_runs` | Algorithm instances | mode, strategy_id, started_at, ended_at, trade_count |
| `predict.algorithm_trades` | Per-run trades | run_id, entry_price, exit_price, profit_loss, exit_reason |
| `predict.algorithm_telemetry` | Equity curve | run_id, date, equity, daily_return, drawdown |
| `predict.algorithm_guardrails` | Risk limits | user_id, kind, threshold, hard (DB-protected) |
| `predict.algorithm_llm_jury` | LLM decisions | proposer_output, critic_output, judge_output, decision |
| `predict.computed_insights` | All-Seeing-Eye | kind, scope_type, scope_id, values (JSONB), confidence, inputs_hash |
| `trading.trade_signals` | Market signals | symbol, direction, confidence, entry/target/stop prices, expired_at |
| `predict.algorithm_risk_controls` | Position sizing | algorithm_id, max_run_duration_hours, profit_target_pct, max_trades_per_run |

---

## SECTION 18: COMPLIANCE & AUDIT NOTES

### Real vs. Claimed Features

| Feature | Status | Notes |
|---------|--------|-------|
| Self-learning weights | REAL | DB-persisted since migration 039 |
| 40 DSL primitives | REAL | All 40 in PRIMITIVES registry, 35 handlers wired |
| Backtest metrics (13) | REAL | Sharpe, Sortino, Calmar, VaR, CVaR, **Cornish-Fisher VaR**, skew, kurt, streaks, etc. |
| Dynamic risk-free rate | REAL | FRED DTB3 integration, 24h cache (added 2026-04-23) |
| Almgren-Chriss slippage | REAL | Square-root market impact model (added 2026-04-23) |
| Full Kelly criterion | REAL | Proper formula f*=(p*b-q)/b with half-Kelly default (fixed 2026-04-23) |
| VPIN toxicity metric | REAL | Volume-synchronized informed trading detection (added 2026-04-23) |
| Kyle's Lambda | REAL | Price impact coefficient via OLS (added 2026-04-23) |
| Human-vs-bot detection | REAL (crypto), PARTIAL (equities) | Crypto: Binance aggTrades (FREE/keyless). Equities: Polygon trades blocked without key |
| Whale/bot classification | REAL (crypto) | Tick-level: whale ratio, bot signature, aggressor imbalance, 6-bucket labels |
| L1 Guardrails | REAL | Hard limits, DB-protected, panic button |
| LLM-Jury (3-model) | REAL | Proposer/Critic/Judge with 0.85 confidence gate |
| Black-Swan Detector | REAL | Z-score > 3.5, correlation breaks, 12 event types, historical matching |
| Black-Swan Forward Signals | REAL | Yield curve, credit spreads, intermarket divergence (added 2026-04-23) |
| Portfolio Correlation Monitor | REAL | Pairwise correlation, effective positions, concentration risk (added 2026-04-23) |
| Adaptive Ensemble | REAL | Regime-specific weights, online learning (added 2026-04-23) |
| All-Seeing-Eye | REAL | Unified AI orchestration, realtime SSE, multi-signal fusion |
| Ljung-Box Autocorrelation | REAL | Statistical test for return predictability (added 2026-04-23) |
| Newey-West Volatility | REAL | HAC-adjusted standard deviation (added 2026-04-23) |
| GPD VaR (Extreme Value) | REAL | Tail risk via Generalized Pareto Distribution (added 2026-04-23) |
| Drawdown Decomposition | REAL | Ulcer Index, Pain Index, recovery analysis (added 2026-04-23) |
| Time-of-Day Liquidity | REAL | Session-aware slippage multipliers (added 2026-04-23) |
| Order Size Bimodality | REAL | Sarle's coefficient for retail/institutional flow detection (added 2026-04-23) |
| Advanced Bot Features | REAL | ML-grade features: interarrival variance, trailing digit entropy (added 2026-04-23) |
| Vol-Adjusted Position Sizing | REAL | Risk parity approach (added 2026-04-23) |
| Correlation-Aware Sizing | REAL | Diversification penalty for concentrated positions (added 2026-04-23) |
| Days-to-Liquidate | REAL | Liquidity risk assessment per position (added 2026-04-23) |
| Tail Hedge Recommendations | REAL | Automatic hedge suggestions based on VaR (added 2026-04-23) |
| Deflated Sharpe Ratio | REAL | Multiple-testing bias adjustment (added 2026-05-04) |
| Information Ratio | REAL | Risk-adjusted active return vs benchmark (added 2026-05-04) |
| Omega Ratio | REAL | Probability-weighted gains/losses (added 2026-05-04) |
| Gain-to-Pain Ratio | REAL | Trader-friendly risk metric (added 2026-05-04) |
| Intraday VaR Monitoring | REAL | 15-minute historical simulation checks (added 2026-05-04) |
| Participation Rate Limits | REAL | ADTV-based order sizing constraints (added 2026-05-04) |
| Gross/Net Exposure Limits | REAL | Leverage (200%) and directional (100%) caps (added 2026-05-04) |
| Blind Jury Pattern | REAL | Judge sees only summary stats, not critic text (added 2026-05-04) |
| Temperature Scheduling | REAL | Role-optimized temps: proposer=0.4, critic=0.5, judge=0.1 (added 2026-05-04) |
| Regime-Aware Kelly | REAL | DSL primitive with 5 regime levels (added 2026-05-04) |

### Known Limitations (Tracked in TODO.md)

1. **Equity Tick Classification** — Polygon per-trade needs API key; no tick-rule inference yet
2. **L2 Order-Book Imbalance** — Requires exchange depth feeds (Binance free for crypto, equities need SIP)
3. **Forex History** — Frankfurter spot-only; no real candles (using synthesized ±1% high/low)
4. **Ad Platform OAuth** — Scaffolding ready, needs live credentials
5. **L2 Circuit Breakers** — Consecutive loss tracking (Sprint 4)
6. **L3 Event Blackouts** — Earnings/FOMC calendar integration (Sprint 3.5)
7. **L4 LLM Anomaly Detection** — Slippage surge, regime shift alerts (Sprint 4)

---

## APPENDIX: KEY FILES REFERENCE

| Component | File Path |
|-----------|-----------|
| Metrics Library | `packages/be/src/backtest/metrics.ts` |
| Backtest Engine | `packages/be/src/backtest/engine.ts` |
| DSL Types & Primitives | `packages/be/src/algorithms/dsl/types.ts` |
| DSL Evaluator | `packages/be/src/algorithms/dsl/evaluator.ts` |
| Trade Execution | `packages/be/src/trading/services/trade-execution.ts` |
| Position Service | `packages/be/src/trading/services/position-service.ts` |
| Signal Generator | `packages/be/src/trading/services/signal-generator.ts` |
| Portfolio Correlation Monitor | `packages/be/src/trading/services/portfolio-correlation-monitor.ts` |
| Human-Auto Composite | `packages/be/src/insights/composite-score.ts` |
| Tick Classifier (VPIN, Kyle's Lambda, Bimodality) | `packages/be/src/insights/tick-classifier.ts` |
| Risk Management Utils | `packages/be/src/trading/services/risk-management-utils.ts` |
| Algorithm Executor | `packages/be/src/algorithms/paper/executor.ts` |
| Guardrails | `packages/be/src/algorithms/guardrails/service.ts` |
| LLM Jury | `packages/be/src/algorithms/llm/jury.ts` |
| All-Seeing-Eye | `packages/be/src/all-seeing-eye/index.ts` |
| Black Swan Detector | `packages/be/src/all-seeing-eye/black-swan/detector.ts` |

---

## CHANGE LOG

| Date | Changes |
|------|---------|
| 2026-05-04 | **Expert Audit - 11 Recommendations Implemented**: Deflated Sharpe Ratio (multiple-testing bias), Intraday VaR monitoring (15-min checks), Max participation rate (ADTV limits), Regime-aware Kelly DSL primitive, Information Ratio, Blind jury pattern (anchoring defense), Temperature scheduling (proposer=0.4/critic=0.5/judge=0.1), Gross/net exposure limits (200%/100%), Omega Ratio, Gain-to-Pain Ratio, Ulcer Index |
| 2026-04-23 | **ALL 20 Expert-Level Enhancements Complete**: Sortino fix, Almgren-Chriss slippage, bid-ask spreads, dynamic risk-free rate, Cornish-Fisher VaR, full Kelly criterion, VPIN, Kyle's Lambda, yield curve/credit/intermarket black swan signals, portfolio correlation monitor, adaptive ensemble weights, Ljung-Box autocorrelation, Newey-West volatility, GPD VaR (EVT), drawdown decomposition (Ulcer/Pain Index), time-of-day liquidity, order size bimodality, advanced bot features, vol-adjusted position sizing, correlation-aware sizing, days-to-liquidate, tail hedge recommendations |
| 2026-04-23 | **New API Endpoints**: `/trading/risk/advanced` (GPD VaR, drawdown analysis, liquidity risk, return quality), `/trading/risk/position-size` (optimal sizing with all constraints) |
| 2026-04-23 | **New Frontend Component**: `AdvancedRiskMetrics.tsx` - institutional risk metrics panel |
| 2026-04-20 | Initial audit document |

---

**End of Audit Document**

*This comprehensive document covers all mathematical calculations, algorithmic logic, and AI decision-making systems in the Agencio Predict platform. All file paths are relative to the repository root and can be used for direct code review or compliance verification.*

*Last updated: 2026-04-23 — 20 institutional-grade enhancements fully implemented and wired to frontend/backend*
