# Strategy: Midpoint Rolling Average Market Making

## Overview

The Midpoint Rolling Average strategy uses a fair value estimator based on a rolling window of orderbook midpoints. Instead of blindly joining the best bid, the agent calculates where the "true" price should be and makes informed decisions about order placement relative to that fair value.

## How It Works

### Fair Value Calculation

1. **Sample the orderbook** every tick (~1 second)
2. **Calculate midpoint**: `midpoint = (yes_bid + no_bid) / 2`
3. **Maintain a rolling window** of the last N midpoints (default: 10)
4. **Fair value** = arithmetic mean of the rolling window

```python
# From mm_core.py - BaseMarketMaker.update_fair_value()
midpoint = (yes_bid + no_bid) / 2
fair_value_history.append(midpoint)  # deque(maxlen=10)
current_fair_value = sum(fair_value_history) / len(fair_value_history)
```

### Trading Logic

Once fair value is established, the agent uses it to inform JOIN behavior and JUMP timing:

1. **Detect mispricing**: If YES bid is significantly below fair value, it's a good buy
2. **Avoid adverse selection**: Don't jump when the price is moving against you
3. **Time entries**: Wait for the rolling average to stabilize before triggering a jump
4. **Inform JUMP decisions**:
   - If spread around fair value is wide -> stay in JOIN to capture spread
   - If spread is tight and price is trending -> use JUMP on the lagging market to get filled before the move

### Agent Decision Flow

```
1. Fetch orderbook data
2. Calculate current midpoint
3. Update rolling average (10-tick window)
4. Compare current best bid to fair value:

   IF current_bid < fair_value - threshold:
     -> Market is underpriced, stay in JOIN to accumulate

   IF current_bid ≈ fair_value:
     -> Market is fairly priced, hold queue position in JOIN

   IF current_bid > fair_value + threshold:
     -> Market may be overpriced, reduce position or pause

   IF queue position degraded AND spread supports it:
     -> Trigger JUMP on that specific market
```

## Terminal Integration

The fair value system is toggled via:
- `{"action": "toggle_fair_value"}` - Enable/disable fair value tracking

When enabled, the terminal displays: `FV: $0.XX` showing the current rolling average fair value.

## Parameters

| Parameter | Default | Description |
|-----------|---------|-------------|
| `fair_value_enabled` | `false` | Toggle fair value tracking |
| `fair_value_history` | `deque(maxlen=10)` | Rolling window size |
| `current_fair_value` | `None` | Current computed fair value |

## When to Use

This strategy excels in:
- **Volatile markets** where the price swings frequently
- **Event-driven markets** where news causes rapid repricing
- **Multi-market scenarios** where cross-market signals help estimate fair value

## Combining with JOIN & JUMP

The Midpoint Rolling Average is not a standalone order placement mode — it is a **signal layer** that informs the agent's behavior within the JOIN/JUMP model:

1. Agent runs in **JOIN mode** continuously
2. Fair value tracking is enabled to monitor the rolling midpoint average
3. The signal informs:
   - **When to hold queue position** — fair value confirms current price is reasonable
   - **When to jump** — fair value shift suggests the price is moving favorably, and queue position is unfavorable
   - **When to pause** — fair value diverges significantly from current bids, indicating potential adverse selection
4. Agents should log their fair value observations for strategy proposals

## Risk Considerations

- Rolling average **lags** sudden moves — the window smooths out spikes
- In fast markets, a 10-tick window may be too slow. Agents can propose upgrades to use exponential moving averages (EMA) or adaptive window sizes
- Fair value is only as good as the orderbook data — thin books produce noisy estimates
