---
title: "Adversarial Simulation"
description: "Test strategy robustness against adversarial agents. Whale attacks, front-running, spoofing, and liquidity draining. Vulnerability scoring and anti-fragile optimization."
icon: "user-secret"
---

<Warning>
  **Ultra Feature.** Requires an Ultra subscription. [Get started at api.mathematicalcompany.com](https://api.mathematicalcompany.com)
</Warning>

# Adversarial Simulation

A strategy that works in calm markets may collapse when a whale dumps, a front-runner snipes your orders, or a spoofer fakes liquidity. Horizon's adversarial module simulates these attacks against your strategy and measures the impact. All adversary logic is pure Rust (stateless); simulation orchestration is in Python.

## Overview

<CardGroup cols={2}>
  <Card title="4 Adversary Types" icon="skull">
    Whale, front-runner, spoofer, and liquidity drainer.
  </Card>
  <Card title="Vulnerability Scoring" icon="gauge-high">
    `hz.vulnerability_score()` quantifies strategy weakness to each attack.
  </Card>
  <Card title="Baseline vs Adversarial" icon="chart-mixed">
    `hz.adversarial_sim()` compares performance with and without adversaries.
  </Card>
  <Card title="Anti-Fragile Optimization" icon="shield-halved">
    `hz.anti_fragile()` evolves parameters that perform well under attack.
  </Card>
</CardGroup>

---

## Adversary Types

| Type | Behavior |
|------|----------|
| `Whale` | Large orders that move the market against you |
| `FrontRunner` | Detects your pending orders and trades ahead |
| `Spoofing` | Places and cancels large orders to fake liquidity |
| `LiquidityDrainer` | Removes liquidity at critical moments |

---

## Core Functions

### Adversary Actions

Each adversary type has a pure function that produces actions from market state.

```python
import horizon as hz

action = hz.whale_action(
    config=hz.AdversaryConfig(hz.AdversaryType.Whale, "whale_1", intensity=1.0, size_multiplier=5.0),
    current_price=0.55,
    market_id="btc_100k",
    seed=42,
)
print(f"Side: {action.side}, Size: {action.size}, Price: {action.price}")
```

```python
action = hz.front_runner_action(config, pending_price=0.55, pending_size=100.0, market_id="btc", seed=42)
action = hz.spoofing_action(config, current_price=0.55, market_id="btc", seed=42)
action = hz.liquidity_drainer_action(config, bid_price=0.54, ask_price=0.56, market_id="btc", seed=42)
```

### hz.compute_simulation_metrics

Compare baseline and adversarial PnL curves.

```python
result = hz.compute_simulation_metrics(
    baseline_pnls=[1.0, 2.0, 1.5, 3.0, 2.5],
    adversarial_pnls=[0.8, 1.5, 0.5, 2.0, 1.0],
)
print(f"Baseline Sharpe: {result.baseline_sharpe:.4f}")
print(f"Adversarial Sharpe: {result.adversarial_sharpe:.4f}")
print(f"PnL degradation: {result.pnl_degradation:.2%}")
print(f"Max drawdown increase: {result.max_drawdown_increase:.4f}")
```

### hz.vulnerability_score

Single score (0-1) for how vulnerable the strategy is.

```python
score = hz.vulnerability_score(
    baseline_pnls=[1.0, 2.0, 3.0],
    adversarial_pnls=[0.5, 1.0, 1.5],
)
print(f"Vulnerability: {score:.2f}")  # 0.0 = immune, 1.0 = destroyed
```

---

## Types

### AdversaryConfig

```python
config = hz.AdversaryConfig(
    adversary_type=hz.AdversaryType.Whale,
    name="big_whale",
    intensity=1.0,          # 0.0-1.0 attack intensity
    size_multiplier=5.0,    # how much larger than typical orders
)
```

### Preset Configurations

```python
from horizon.adversarial import WHALE_PRESET, FRONT_RUNNER_PRESET, SPOOFING_PRESET, DRAINER_PRESET
```

---

## Simulation Functions

### hz.adversarial_sim

Run baseline vs adversarial comparison.

```python
import horizon as hz

result = hz.adversarial_sim(
    pipeline_factory=lambda params: [my_strategy],
    data=historical_data,
    adversaries=[
        hz.AdversaryConfig(hz.AdversaryType.Whale, "whale", intensity=0.8, size_multiplier=5.0),
        hz.AdversaryConfig(hz.AdversaryType.FrontRunner, "runner", intensity=0.5, size_multiplier=1.0),
    ],
    num_cycles=100,
    seed=42,
)
print(f"PnL degradation: {result.pnl_degradation:.2%}")
print(f"Vulnerability: {result.vulnerability:.4f}")
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `pipeline_factory` | `Callable` | required | Function(params) -> pipeline |
| `data` | `Any` | `None` | Historical data for backtest |
| `adversaries` | `list[AdversaryConfig]` | `[WHALE_PRESET]` | Adversary configurations |
| `num_cycles` | `int` | `100` | Simulation length |
| `seed` | `int` | `42` | Random seed |

### hz.anti_fragile

Evolutionary optimization for adversarial robustness. Finds parameters that perform well even under attack.

```python
result = hz.anti_fragile(
    pipeline_factory=lambda params: [my_strategy_factory(**params)],
    param_bounds=[
        {"name": "spread", "min": 0.01, "max": 0.10},
        {"name": "size", "min": 1, "max": 50, "discrete": True},
    ],
    adversaries=[hz.WHALE_PRESET, hz.FRONT_RUNNER_PRESET],
    data=historical_data,
    pop_size=30,
    generations=50,
    seed=42,
)
print(f"Anti-fragile params: {result['best_genome']}")
print(f"Adversarial fitness: {result['best_fitness']:.4f}")
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `pipeline_factory` | `Callable` | required | Strategy factory |
| `param_bounds` | `list[dict]` | required | Parameter bounds |
| `adversaries` | `list[AdversaryConfig]` | whale + front-runner | Attack configuration |
| `data` | `Any` | `None` | Historical data |
| `pop_size` | `int` | `30` | Evolution population size |
| `generations` | `int` | `50` | Evolution generations |
| `seed` | `int` | `42` | Random seed |

---

## Examples

### Test Strategy Robustness

```python
import horizon as hz

# Test against all adversary types
for adv_type, name in [
    (hz.AdversaryType.Whale, "Whale"),
    (hz.AdversaryType.FrontRunner, "Front-Runner"),
    (hz.AdversaryType.Spoofing, "Spoofer"),
    (hz.AdversaryType.LiquidityDrainer, "Drainer"),
]:
    config = hz.AdversaryConfig(adv_type, name.lower(), intensity=1.0, size_multiplier=5.0)
    result = hz.adversarial_sim(
        pipeline_factory=lambda p: [my_strategy],
        data=data,
        adversaries=[config],
    )
    print(f"{name}: PnL degradation={result.pnl_degradation:.2%}, "
          f"vulnerability={result.vulnerability:.4f}")
```

### Find Anti-Fragile Parameters

```python
import horizon as hz

result = hz.anti_fragile(
    pipeline_factory=lambda p: [make_strategy(p)],
    param_bounds=[
        {"name": "spread", "min": 0.02, "max": 0.15},
        {"name": "size", "min": 5, "max": 100, "discrete": True},
        {"name": "window", "min": 10, "max": 200, "discrete": True},
    ],
    adversaries=[hz.WHALE_PRESET, hz.FRONT_RUNNER_PRESET, hz.SPOOFING_PRESET],
    pop_size=30,
    generations=50,
)
# These parameters are optimized to perform well even under adversarial conditions
print(f"Anti-fragile spread: {result['best_genome'][0]:.4f}")
```

<Warning>
  Adversarial agents are heuristic simulations, not full market microstructure simulators. They test directional robustness (how your strategy handles unexpected market actions) but do not replicate the exact mechanics of real adversaries. Use them as stress tests, not as precise predictions.
</Warning>
