# Market Manipulation Detection System

**Version:** 1.0
**Status:** Production-Ready
**Last Updated:** 2026-05-12

---

## Overview

Agencio Predict includes a comprehensive market manipulation detection system designed to protect algorithmic trading strategies from adverse market conditions caused by manipulative activity. The system detects 7 types of manipulation across equities, crypto, and forex markets using real-time and historical data.

This document covers:
- [Detection Capabilities](#detection-capabilities)
- [Architecture](#architecture)
- [Data Sources](#data-sources)
- [DSL Primitives Reference](#dsl-primitives-reference)
- [Real-Time Monitoring](#real-time-monitoring)
- [Integration Guide](#integration-guide)
- [API Reference](#api-reference)

---

## Detection Capabilities

### 1. Stop-Loss Hunting Detection

**File:** `packages/be/src/insights/stop-hunt-detector.ts`

Stop-loss hunting occurs when large players intentionally push price through known support/resistance levels to trigger stop-loss orders, then reverse to profit from the artificial liquidity.

**Detection Method:**
1. Identify key S/R levels using ATR-based clustering
2. Detect price piercing through these levels
3. Confirm rapid reversal (within 3-5 bars)
4. Validate with volume spike (2x normal)
5. Score confidence based on magnitude and speed

**Signals Detected:**
- Long squeeze (price pushed below support, then reverses up)
- Short squeeze (price pushed above resistance, then reverses down)
- Failed hunts (pierce without sufficient reversal)

**Key Metrics:**
| Metric | Description | Range |
|--------|-------------|-------|
| `huntMagnitude` | Distance pierced beyond S/R as % of ATR | 0-5+ |
| `huntConfidence` | Confidence score (0-1) | 0-1 |
| `reversalSpeed` | Bars to reversal | 1-10 |
| `volumeMultiple` | Volume vs 20-bar average | 1-10x |

### 2. Spoofing/Layering Detection

**File:** `packages/be/src/insights/spoofing-detector.ts`

Spoofing involves placing large orders with intent to cancel before execution, creating false impression of supply/demand. Layering is multiple spoof orders at different price levels.

**Detection Method:**
1. Track large walls (>5x average depth) in L2 order book
2. Monitor wall appearance/disappearance patterns
3. Detect correlation between wall removal and price movement
4. Calculate spoof confidence based on pattern consistency

**Key Metrics:**
| Metric | Description | Range |
|--------|-------------|-------|
| `spoofProbability` | Likelihood of spoofing (0-1) | 0-1 |
| `wallSize` | Size of detected wall in quote currency | USD |
| `priceImpact` | Price movement after wall removal | % |
| `spoofSide` | Which side was spoofed (bid/ask) | bid/ask |

### 3. Wash Trading Detection

**File:** `packages/be/src/insights/manipulation-detector.ts`

Wash trading involves simultaneous buying and selling by the same entity to create artificial volume and misleading market activity.

**Detection Method:**
1. Analyze trade pairs within time window (default 5 seconds)
2. Match by size, timing, and price proximity
3. Cluster potential wash trades
4. Calculate wash ratio (matched volume / total volume)

**Key Metrics:**
| Metric | Description | Range |
|--------|-------------|-------|
| `washRatio` | Proportion of volume that appears washed | 0-1 |
| `matchedPairs` | Number of suspicious trade pairs | count |
| `clusterCount` | Number of wash trade clusters | count |
| `severity` | Risk level (low/medium/high) | enum |

### 4. Pump and Dump Detection

**File:** `packages/be/src/insights/manipulation-detector.ts`

Pump and dump schemes artificially inflate prices through coordinated buying and misleading promotions, followed by selling to uninformed buyers.

**Detection Method:**
1. Detect volume spike (>3x 20-bar average)
2. Confirm rapid price increase (>5% in lookback period)
3. Identify reversal pattern (price decline after peak)
4. Classify phase: accumulation → pump → distribution → dump

**Key Metrics:**
| Metric | Description | Range |
|--------|-------------|-------|
| `isActive` | Whether pump/dump is currently in progress | boolean |
| `phase` | Current phase of the scheme | enum |
| `pumpMagnitude` | Price increase during pump phase | % |
| `volumeSpike` | Volume multiple vs baseline | 1-20x |

### 5. Closing Auction Manipulation

**File:** `packages/be/src/insights/manipulation-detector.ts`

Manipulation of closing auction prices affects index calculations, derivative settlements, and fund NAVs.

**Detection Method:**
1. Analyze price action in final 15 minutes of session
2. Detect abnormal volume concentration in close period
3. Identify divergence between close and VWAP
4. Flag sudden directional pressure near close

**Key Metrics:**
| Metric | Description | Range |
|--------|-------------|-------|
| `closeDeviation` | Close price vs session VWAP | % |
| `closeVolumeRatio` | Close volume vs session average | 1-10x |
| `riskScore` | Overall manipulation risk | 0-1 |
| `isManipulated` | Whether close appears manipulated | boolean |

### 6. Options Flow Manipulation

**File:** `packages/be/src/integrations/polygon-options.ts`

Unusual options activity can signal informed trading, manipulation, or positioning ahead of events.

**Detection Method:**
1. Fetch options trades from Polygon.io
2. Identify large notional trades (>$100k)
3. Detect size anomalies (>5x average)
4. Analyze put/call ratios and sweep patterns

**Key Metrics:**
| Metric | Description | Range |
|--------|-------------|-------|
| `unusualCount` | Number of unusual activity flags | count |
| `largestTrade` | Largest options trade notional | USD |
| `putCallRatio` | Put volume / call volume | 0-5+ |
| `flowSentiment` | Net sentiment from flow (-1 to +1) | -1 to +1 |

### 7. Quote Stuffing Detection

**Future Implementation**

Quote stuffing floods the market with rapid order submissions and cancellations to slow competitors' systems.

**Detection Requirements:**
- High-frequency quote data (microsecond timestamps)
- Order-to-trade ratio analysis
- Latency pattern detection

**Status:** Requires paid exchange data feed (CME, NYSE, NASDAQ direct)

---

## Architecture

```
┌─────────────────────────────────────────────────────────────────────┐
│                    MANIPULATION DETECTION LAYER                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐    │
│  │  Stop Hunt      │  │  Spoofing       │  │  Manipulation   │    │
│  │  Detector       │  │  Detector       │  │  Detector       │    │
│  │                 │  │                 │  │                 │    │
│  │  - S/R Levels   │  │  - Wall Tracker │  │  - Wash Trading │    │
│  │  - Pierce Detect│  │  - Pattern Match│  │  - Pump & Dump  │    │
│  │  - Reversal     │  │  - L2 Analysis  │  │  - Close Manip  │    │
│  └────────┬────────┘  └────────┬────────┘  └────────┬────────┘    │
│           │                    │                    │              │
│           ▼                    ▼                    ▼              │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │                    DSL PRIMITIVE LAYER                       │  │
│  │                                                               │  │
│  │  is_stop_hunt()  spoofing_risk()  manipulation_risk_score() │  │
│  │  stop_hunt_direction()  is_spoofing_detected()  ...          │  │
│  └─────────────────────────────────────────────────────────────┘  │
│                              │                                     │
└──────────────────────────────┼─────────────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    DATA SOURCES                                      │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐    │
│  │  Binance WS     │  │  Polygon.io     │  │  Schwab API     │    │
│  │  (Real-time L2) │  │  (Options Flow) │  │  (Options Chain)│    │
│  │                 │  │                 │  │                 │    │
│  │  - depth@100ms  │  │  - Trades       │  │  - Full Chain   │    │
│  │  - Top 5/10/20  │  │  - Quotes       │  │  - Greeks       │    │
│  │  - Combined     │  │  - Aggregates   │  │  - Open Interest│    │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
```

### Component Responsibilities

| Component | File | Purpose |
|-----------|------|---------|
| Stop Hunt Detector | `stop-hunt-detector.ts` | S/R analysis, pierce detection, reversal confirmation |
| Spoofing Detector | `spoofing-detector.ts` | L2 wall tracking, disappearance patterns, price impact |
| Manipulation Detector | `manipulation-detector.ts` | Wash trading, pump/dump, closing auction |
| Binance WS | `binance-ws.ts` | Real-time L2 order book streaming |
| Polygon Options | `polygon-options.ts` | Options flow and unusual activity |
| Schwab Options | `schwab-options.ts` | Equity options chain and Greeks |
| Realtime Spoofing | `realtime-spoofing-service.ts` | WebSocket + spoofing detector integration |

---

## Data Sources

### 1. Binance WebSocket (Crypto)

**File:** `packages/be/src/integrations/binance-ws.ts`

Real-time L2 order book streaming for crypto pairs.

**Streams Available:**
| Stream | Update Speed | Levels | Use Case |
|--------|--------------|--------|----------|
| `<symbol>@depth5@100ms` | 100ms | Top 5 | Fast signals |
| `<symbol>@depth10@100ms` | 100ms | Top 10 | Balanced |
| `<symbol>@depth20@100ms` | 100ms | Top 20 | Spoofing detection |
| `<symbol>@depth@100ms` | 100ms | Full | Deep analysis |

**Configuration:**
```typescript
import { subscribeDepth, getDepthSnapshot } from '../integrations/binance-ws';

// Subscribe to real-time updates
subscribeDepth('BTCUSDT', (snapshot) => {
  console.log('Mid price:', snapshot.midPrice);
  console.log('Spread:', snapshot.spreadBps, 'bps');
}, { level: '20', updateSpeed: '100ms' });

// Get current snapshot
const book = getDepthSnapshot('BTCUSDT');
```

**Limits:**
- Max 10 streams per WebSocket connection
- Automatic reconnection with 5-second delay
- Ping/pong keepalive every 30 seconds

### 2. Polygon.io Options (Equities)

**File:** `packages/be/src/integrations/polygon-options.ts`

Options trades, quotes, and unusual activity detection.

**Endpoints Used:**
| Endpoint | Data | Rate Limit |
|----------|------|------------|
| `/v3/trades/O:{symbol}` | Options trades | 5/min (free) |
| `/v3/snapshot/options/{underlying}` | Full snapshot | 5/min (free) |

**Configuration:**
```bash
# Environment variable
POLYGON_API_KEY=your_api_key
```

```typescript
import { fetchOptionsFlow, fetchOptionsSnapshot } from '../integrations/polygon-options';

// Get options flow with unusual activity
const flow = await fetchOptionsFlow('AAPL', 60); // Last 60 minutes
console.log('Unusual activities:', flow.unusualActivity.length);
console.log('Put/Call ratio:', flow.summary.putCallRatio);

// Get options snapshot
const snapshot = await fetchOptionsSnapshot('AAPL');
console.log('ATM IV:', snapshot.atmIv);
console.log('Max pain:', snapshot.maxPainStrike);
```

**Unusual Activity Thresholds:**
- Large size: >5x average trade size
- Large notional: >$100,000
- High severity: >$500,000 notional

### 3. Schwab Trader API (Options Chain)

**File:** `packages/be/src/integrations/schwab-options.ts`

Full options chain data with Greeks for equity options.

**Requirements:**
- User must have authenticated Schwab broker connection
- OAuth tokens stored in `user_broker_credentials` table
- Token refresh required every 7 days

**Configuration:**
```typescript
import { fetchOptionsChain, fetchAtmIv, fetchMaxPain } from '../integrations/schwab-options';

// Fetch full options chain
const chain = await fetchOptionsChain(userId, 'AAPL', {
  strikeCount: 10,  // 10 strikes around ATM
  type: 'all',      // Both calls and puts
});

console.log('Expirations:', chain.expirations);
console.log('Put/Call OI ratio:', chain.summary.putCallOiRatio);
console.log('IV Skew:', chain.summary.ivSkew);

// Quick helpers
const atmIv = await fetchAtmIv(userId, 'AAPL');
const maxPain = await fetchMaxPain(userId, 'AAPL', '2026-05-17');
```

**Data Returned:**
- Full options chain by expiration
- Greeks: delta, gamma, theta, vega, rho
- Open interest and volume
- Implied volatility per contract
- Put/call aggregates and ratios

---

## DSL Primitives Reference

All manipulation detection primitives are available in the Algorithm Builder DSL.

### Stop-Loss Hunting Primitives

| Primitive | Type | Description |
|-----------|------|-------------|
| `is_stop_hunt(lookback)` | `boolean` | True if stop hunt detected in lookback period |
| `stop_hunt_direction(lookback)` | `'long'│'short'│'none'` | Direction of detected hunt |
| `stop_hunt_magnitude(lookback)` | `number` | Magnitude of hunt (0-5+ ATR multiple) |
| `stop_hunt_confidence(lookback)` | `number` | Confidence score (0-1) |
| `recent_stop_hunts(lookback)` | `number` | Count of hunts in period |
| `is_near_hunt_level(lookback)` | `boolean` | Price near potential hunt level |
| `hunt_probability(lookback)` | `number` | Probability of imminent hunt (0-1) |
| `is_long_squeeze(lookback)` | `boolean` | True if long squeeze detected |
| `is_short_squeeze(lookback)` | `boolean` | True if short squeeze detected |

**Example Usage:**
```
# Avoid entering during stop hunts
entry: rsi < 30 AND NOT is_stop_hunt(20)

# Exit on squeeze
exit: is_long_squeeze(10) AND direction == "long"

# Reduce size near hunt levels
size: IF is_near_hunt_level(20) THEN kelly * 0.5 ELSE kelly
```

### Spoofing Detection Primitives

| Primitive | Type | Description |
|-----------|------|-------------|
| `spoofing_risk(symbol)` | `number` | Current spoofing risk score (0-1) |
| `is_spoofing_detected(symbol)` | `boolean` | True if active spoofing detected |

**Example Usage:**
```
# Avoid trading during spoofing
entry: signal > 0.7 AND spoofing_risk(symbol) < 0.5

# Use limit orders during high spoof risk
order_type: IF spoofing_risk(symbol) > 0.7 THEN "limit" ELSE "market"
```

### Manipulation Detection Primitives

| Primitive | Type | Description |
|-----------|------|-------------|
| `manipulation_risk_score(lookback)` | `number` | Aggregate manipulation risk (0-1) |
| `is_pump_dump_active(lookback)` | `boolean` | True if pump/dump in progress |
| `pump_dump_phase(lookback)` | `string` | Current phase (accumulation/pump/distribution/dump/none) |
| `closing_auction_risk(lookback)` | `number` | Closing manipulation risk (0-1) |
| `is_closing_manipulation(lookback)` | `boolean` | True if close appears manipulated |

**Example Usage:**
```
# Avoid pump and dump schemes
entry: momentum > 0 AND NOT is_pump_dump_active(50)

# Exit before manipulated close
exit: closing_auction_risk(15) > 0.7 AND time_to_close < 30

# Scale position by manipulation risk
size: kelly * (1 - manipulation_risk_score(20))
```

### Options Flow Primitives

| Primitive | Type | Description |
|-----------|------|-------------|
| `options_flow_sentiment(symbol)` | `number` | Flow sentiment (-1 to +1) |
| `unusual_options_count(symbol)` | `number` | Count of unusual activities |
| `options_put_call_ratio(symbol)` | `number` | Put/call volume ratio |
| `largest_options_trade(symbol)` | `number` | Largest trade notional (USD) |
| `max_pain_strike(symbol)` | `number` | Max pain strike price |

**Example Usage:**
```
# Fade extreme sentiment
entry: options_flow_sentiment(symbol) < -0.5 AND rsi < 30

# Add conviction on unusual activity
size: IF unusual_options_count(symbol) > 3 THEN kelly * 1.5 ELSE kelly

# Trade toward max pain near expiration
bias: IF price < max_pain_strike(symbol) THEN "long" ELSE "short"
```

### Schwab Options Primitives (Requires User Auth)

| Primitive | Type | Description |
|-----------|------|-------------|
| `schwab_put_call_ratio(symbol)` | `number` | Put/call OI ratio from Schwab |
| `schwab_iv_skew(symbol)` | `number` | IV skew (call IV - put IV) |
| `schwab_max_pain(symbol)` | `number` | Max pain strike from Schwab |
| `schwab_atm_iv(symbol)` | `number` | ATM implied volatility |

**Example Usage:**
```
# Trade IV skew
entry: schwab_iv_skew(symbol) > 5 AND direction == "put_spread"

# Volatility filter
entry: schwab_atm_iv(symbol) < 30 AND momentum > 0
```

---

## Real-Time Monitoring

### Spoofing Monitor Service

**File:** `packages/be/src/insights/realtime-spoofing-service.ts`

The real-time spoofing service integrates Binance WebSocket streaming with the spoofing detector for 100ms latency detection.

**Starting the Monitor:**
```typescript
import {
  watchForSpoofing,
  unwatchSpoofing,
  onSpoofingAlert,
  getSpoofingMonitorStats,
} from '../insights/realtime-spoofing-service';

// Start monitoring symbols
watchForSpoofing('BTCUSDT');
watchForSpoofing('ETHUSDT');

// Register alert handler
onSpoofingAlert((alert) => {
  console.log(`SPOOFING DETECTED: ${alert.signal.description}`);
  console.log(`  Confidence: ${alert.signal.confidence}`);
  console.log(`  Severity: ${alert.signal.severity}`);
  console.log(`  Side: ${alert.signal.spoofSide}`);
  console.log(`  Wall Size: $${alert.signal.wallSize.toLocaleString()}`);

  // Take action (e.g., pause trading, alert user)
  if (alert.signal.severity === 'high') {
    pauseTrading(alert.signal.symbol);
  }
});

// Check monitoring stats
const stats = getSpoofingMonitorStats();
for (const s of stats) {
  console.log(`${s.symbol}: ${s.updatesReceived} updates, ${s.signalsDetected} signals`);
}
```

**Alert Structure:**
```typescript
interface SpoofingAlert {
  signal: {
    symbol: string;
    timestamp: string;
    confidence: number;      // 0-1
    severity: 'low' | 'medium' | 'high';
    spoofSide: 'bid' | 'ask';
    priceLevel: number;
    wallSize: number;        // USD
    priceImpact: number;     // %
    description: string;
  };
  analysis: {
    spoofProbability: number;
    signals: SpoofingSignal[];
    bidWalls: WallInfo[];
    askWalls: WallInfo[];
  };
  timestamp: string;
}
```

### Scheduler Integration

Add to the scheduler for periodic manipulation checks:

```typescript
// In scheduler job definition
{
  name: 'manipulation-scan',
  interval: '5m',
  handler: async () => {
    const watchlist = await getActiveWatchlist();

    for (const symbol of watchlist) {
      // Get recent bars
      const bars = await getHistoricalPrices(symbol, 100);

      // Run detectors
      const stopHunts = analyzeStopHunts(symbol, bars);
      const manipulation = {
        washRatio: detectWashTrading(trades).washRatio,
        pumpDump: detectPumpAndDump(bars),
        closingRisk: detectClosingAuctionManipulation(bars).riskScore,
      };

      // Store results
      await storeManipulationScan(symbol, {
        ...stopHunts,
        ...manipulation,
      });

      // Alert on high-risk
      if (manipulation.pumpDump.isActive) {
        await sendManipulationAlert(symbol, 'pump_dump');
      }
    }
  },
}
```

---

## Integration Guide

### Adding to Existing Algorithm

1. **Backtest Engine** (`packages/be/src/algorithms/backtest/engine.ts`)

The manipulation primitives are already wired into `buildIndicators()`:

```typescript
// In engine.ts buildIndicators()
const stopHuntAnalysis = analyzeStopHunts(symbol, bars);
const manipRiskResult = detectPumpAndDump(bars, lookback);

return {
  // ... existing indicators
  is_stop_hunt: (lookback: number) => dslIsStopHunt(bars, lookback),
  stop_hunt_direction: (lookback: number) => dslStopHuntDirection(bars, lookback),
  manipulation_risk_score: (lookback: number) => dslManipulationRiskScore(bars),
  // ... etc
};
```

2. **Paper/Live Executor** (`packages/be/src/algorithms/paper/executor.ts`)

Similarly wired for real-time evaluation:

```typescript
// In executor.ts tickRun()
const ctx: EvalContext = {
  // ... existing context
  is_stop_hunt: (lookback: number) => dslIsStopHunt(bars, lookback),
  spoofing_risk: async (sym: string) => dslSpoofingRisk(sym),
  // ... etc
};
```

3. **Creating a Manipulation-Aware Strategy**

```
name: "Manipulation-Aware Momentum"
universe: ["AAPL", "GOOGL", "MSFT"]

# Entry conditions
entry:
  - momentum(20) > 0.02
  - NOT is_stop_hunt(10)
  - NOT is_pump_dump_active(50)
  - manipulation_risk_score(20) < 0.3
  - spoofing_risk(symbol) < 0.5

# Exit conditions
exit:
  - is_long_squeeze(5)
  - closing_auction_risk(15) > 0.7
  - manipulation_risk_score(10) > 0.6

# Position sizing
size:
  base: kelly * 0.5
  manipulation_adjustment: 1 - manipulation_risk_score(20)
  final: base * manipulation_adjustment
```

### Adding New Detection Types

To add a new manipulation detector:

1. **Create Detector Module:**
```typescript
// packages/be/src/insights/new-detector.ts
export interface NewManipulationResult {
  detected: boolean;
  confidence: number;
  details: { ... };
}

export function detectNewManipulation(bars: OHLCVBar[]): NewManipulationResult {
  // Detection logic
}

// DSL helpers
export function dslIsNewManipulation(bars: OHLCVBar[], lookback: number): boolean {
  const slice = bars.slice(-lookback);
  return detectNewManipulation(slice).detected;
}
```

2. **Register DSL Primitives:**
```typescript
// packages/be/src/algorithms/dsl/types.ts
export const PRIMITIVES = {
  // ... existing
  is_new_manipulation: { args: ['lookback'], returnType: 'boolean' },
};

// packages/be/src/algorithms/dsl/evaluator.ts
export interface IndicatorBundle {
  // ... existing
  is_new_manipulation: (lookback: number) => boolean;
}
```

3. **Wire into Engine:**
```typescript
// packages/be/src/algorithms/backtest/engine.ts
import { dslIsNewManipulation } from '../../insights/new-detector';

function buildIndicators(bars: OHLCVBar[], ...): IndicatorBundle {
  return {
    // ... existing
    is_new_manipulation: (lookback) => dslIsNewManipulation(bars, lookback),
  };
}
```

4. **Wire into Executor:**
```typescript
// packages/be/src/algorithms/paper/executor.ts
import { dslIsNewManipulation } from '../../insights/new-detector';

// In tickRun(), add to EvalContext
is_new_manipulation: (lookback) => dslIsNewManipulation(bars, lookback),
```

---

## API Reference

### Internal Service APIs

#### Stop Hunt Analysis

```typescript
import { analyzeStopHunts } from '../insights/stop-hunt-detector';

const analysis = analyzeStopHunts('BTCUSDT', bars, {
  atrPeriod: 14,           // ATR calculation period
  minHuntMagnitude: 0.5,   // Minimum ATR multiple to qualify
  reversalBars: 5,         // Max bars for reversal confirmation
  volumeMultiple: 2.0,     // Required volume spike
});

// Returns:
{
  huntsDetected: StopHunt[],
  keyLevels: { support: number[], resistance: number[] },
  currentRisk: 'low' | 'medium' | 'high',
  nearestHuntLevel: number | null,
  summary: {
    totalHunts: number,
    longSqueezes: number,
    shortSqueezes: number,
    avgMagnitude: number,
    avgConfidence: number,
  }
}
```

#### Spoofing Detection

```typescript
import { detectSpoofingFromSnapshot } from '../insights/spoofing-detector';

const analysis = detectSpoofingFromSnapshot('BTCUSDT', orderBookSnapshot);

// Returns:
{
  spoofProbability: number,  // 0-1
  signals: SpoofingSignal[],
  bidWalls: WallInfo[],
  askWalls: WallInfo[],
  recentActivity: {
    wallsAppeared: number,
    wallsDisappeared: number,
    avgWallLifeMs: number,
  }
}
```

#### Manipulation Detection

```typescript
import {
  detectWashTrading,
  detectPumpAndDump,
  detectClosingAuctionManipulation,
} from '../insights/manipulation-detector';

// Wash trading (requires tick-level trade data)
const washResult = detectWashTrading(trades, 5000); // 5-second window

// Pump and dump
const pumpResult = detectPumpAndDump(bars, 50);

// Closing auction
const closeResult = detectClosingAuctionManipulation(bars, 15);
```

#### Options Flow

```typescript
import { fetchOptionsFlow, fetchOptionsSnapshot } from '../integrations/polygon-options';

// Get flow with unusual activity
const flow = await fetchOptionsFlow('AAPL', 60);

// Get snapshot with IV and OI
const snapshot = await fetchOptionsSnapshot('AAPL');
```

#### Schwab Options Chain

```typescript
import { fetchOptionsChain, fetchAtmIv } from '../integrations/schwab-options';

// Full chain (requires user auth)
const chain = await fetchOptionsChain(userId, 'AAPL', {
  strikeCount: 10,
  expirationFrom: '2026-05-10',
  expirationTo: '2026-06-10',
  type: 'all',
});

// Quick ATM IV
const iv = await fetchAtmIv(userId, 'AAPL');
```

---

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `POLYGON_API_KEY` | For options flow | Polygon.io API key |
| `SCHWAB_CLIENT_ID` | For Schwab | Schwab OAuth client ID |
| `SCHWAB_CLIENT_SECRET` | For Schwab | Schwab OAuth client secret |

**Note:** Binance WebSocket is keyless for public market data.

---

## Troubleshooting

### Common Issues

**1. Spoofing alerts not triggering**
- Verify WebSocket connection: `getBinanceDepthStream().connected`
- Check symbol format: should be uppercase with USDT suffix (e.g., `BTCUSDT`)
- Verify wall detection thresholds in `spoofing-detector.ts`

**2. Stop hunt detection too sensitive**
- Increase `minHuntMagnitude` (default 0.5 ATR)
- Increase `volumeMultiple` threshold (default 2.0)
- Require more reversal confirmation bars

**3. Options flow returning empty**
- Verify `POLYGON_API_KEY` is set
- Check rate limits (5 requests/minute on free tier)
- Verify market hours (options only trade during market hours)

**4. Schwab options returning null**
- Verify user has valid Schwab OAuth tokens
- Check token expiration (7-day hard limit)
- Verify symbol format (standard equity tickers only)

### Logging

Enable detailed logging for debugging:

```typescript
import { moduleLogger } from '../lib/logger';

// Each module has its own logger
const log = moduleLogger('spoofing-detector');
log.debug({ symbol, wallCount }, 'Detected walls');
log.warn({ signal }, 'Spoofing signal generated');
```

---

## Console Alerts & Notifications

### Manipulation Alert Service

**File:** `packages/be/src/insights/manipulation-alert-service.ts`

The manipulation alert service provides real-time notifications when manipulation is detected, integrating with both SSE streaming for console alerts and persistent notifications.

**Alert Types:**
| Type | Event | Severity | Channel |
|------|-------|----------|---------|
| `STOP_HUNT` | Stop-loss hunting detected | medium-critical | surveillance, trading |
| `SPOOFING` | Order book spoofing detected | medium-critical | surveillance, trading |
| `PUMP_DUMP` | Pump & dump pattern detected | high-critical | surveillance, trading |
| `CLOSING_AUCTION` | Closing auction manipulation | high-critical | surveillance, trading |
| `WASH_TRADING` | Wash trading detected | medium-critical | surveillance, trading |

**SSE Integration:**

Alerts are broadcast via SSE to both `surveillance` and `trading` channels:

```typescript
// In manipulationAlertService.emitAlert()
realtimeEmitter.broadcast({
  id: fullAlert.id,
  type: 'SURVEILLANCE_ALERT',
  channel: 'surveillance',
  data: {
    alertId: fullAlert.id,
    marketId: fullAlert.symbol,
    alertType: `MANIPULATION_${fullAlert.type}`,
    severity: fullAlert.severity,
    title: fullAlert.title,
    description: fullAlert.description,
    confidence: fullAlert.confidence,
    evidence: fullAlert.evidence,
  },
  timestamp: new Date(),
});
```

**Console Widget Integration:**

The Terminal Console (AGENCIO TERMINAL) automatically receives manipulation alerts via the surveillance SSE channel. Alerts appear in the ALL tab and TRADING tab with:
- Alert severity color coding (red=critical, orange=high, yellow=medium)
- Symbol and manipulation type
- Description with key metrics
- Evidence breakdown

**Subscribing to Alerts in Custom Code:**

```typescript
import { onSpoofingAlert } from '../insights/realtime-spoofing-service';
import { manipulationAlertService } from '../insights/manipulation-alert-service';

// Option 1: Use the realtime spoofing service callback
onSpoofingAlert((alert) => {
  // Automatically triggers SSE broadcast via manipulationAlertService
  console.log(`Spoofing: ${alert.signal.description}`);
});

// Option 2: Manually emit alerts for other manipulation types
manipulationAlertService.emitStopHuntAlert(symbol, stopHuntAnalysis);
manipulationAlertService.emitPumpDumpAlert(symbol, pumpDumpResult);
manipulationAlertService.emitClosingAuctionAlert(symbol, closingResult);
manipulationAlertService.emitWashTradingAlert(symbol, washResult);
```

**Alert Cooldown:**

To prevent alert spam, each symbol+type combination has a 60-second cooldown. The same alert won't be emitted again for that symbol until the cooldown expires.

**Persistent Notifications:**

When `subscribedUserIds` is provided, alerts are also saved to the notifications database for the user's notification center:

```typescript
// Emit with persistent notifications for specific users
manipulationAlertService.emitSpoofingAlert(analysis, ['user-123', 'user-456']);
```

---

## Related Documentation

- `docs/13-broker-integration.md` — Broker setup and authentication
- `docs/44-pattern-detection-and-ai-features.md` — Pattern detection (FVG, candlesticks)
- `docs/55-pepperstone-broker-integration.md` — Pepperstone OAuth flow
- `docs/56-schwab-broker-integration.md` — Schwab OAuth flow
- `docs/12-algorithm-builder.md` — AI Algorithm Builder overview
- `TRADING_MATH_AUDIT.md` — Backtest metrics and calculations
