> ## Documentation Index
> Fetch the complete documentation index at: https://mathematicalcompany.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Optimal Execution

> Garleanu-Pedersen and Almgren-Chriss optimal execution models for prediction market trading.

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

<Tip>
  **What is this?** When you need to buy or sell a large position, trading it all at once moves the price against you. These two models compute the optimal schedule - how much to trade at each time step - to minimize the total cost. Garleanu-Pedersen is for portfolio rebalancing when your alpha signal decays over time. Almgren-Chriss is for pure liquidation when you just need to sell everything.
</Tip>

# Optimal Execution

Horizon implements two foundational optimal execution models: Garleanu-Pedersen (2013) for alpha-decay-aware portfolio transitions, and Almgren-Chriss (2001) for risk-averse liquidation scheduling. Both run entirely in Rust and produce executable trajectories compatible with the pipeline system.

<CardGroup cols={2}>
  <Card title="Garleanu-Pedersen" icon="arrow-trend-up">
    Optimal trading with alpha decay. Balances urgency from decaying signals against temporary and permanent market impact.
  </Card>

  <Card title="Almgren-Chriss" icon="arrow-down-to-line">
    Optimal liquidation under mean-variance preferences. Minimizes the expected cost plus risk penalty of unwinding a position.
  </Card>

  <Card title="Trajectory Output" icon="chart-line">
    Both models produce time-indexed position trajectories with per-step trade rates and cost estimates.
  </Card>

  <Card title="Pipeline Integration" icon="diagram-project">
    `hz.gp_executor()` and `hz.ac_liquidator()` drive real-time execution within `hz.run()`.
  </Card>
</CardGroup>

***

## Model Comparison

| Aspect               | Garleanu-Pedersen                        | Almgren-Chriss                        |
| -------------------- | ---------------------------------------- | ------------------------------------- |
| **Use case**         | Portfolio transition with alpha signal   | Pure liquidation / acquisition        |
| **Objective**        | Maximize alpha capture minus impact cost | Minimize expected cost + risk penalty |
| **Key parameter**    | Alpha decay rate (kappa)                 | Risk aversion (lambda)                |
| **Trade profile**    | Front-loaded when alpha decays fast      | Depends on risk aversion              |
| **Permanent impact** | Yes (linear)                             | Yes (linear)                          |
| **Temporary impact** | Yes (linear)                             | Yes (linear)                          |

<Note>
  Use Garleanu-Pedersen when you have a time-decaying signal and want to capture it optimally. Use Almgren-Chriss when you need to liquidate or acquire a fixed position with controlled risk.
</Note>

***

## Garleanu-Pedersen

The GP model solves for the optimal trading rate that maximizes expected alpha capture minus temporary and permanent impact costs. The solution is a closed-form exponential trajectory controlled by a single urgency parameter.

### hz.gp\_optimal\_trajectory

Compute the optimal position trajectory for a portfolio transition under alpha decay.

```python theme={null}
import horizon as hz

trajectory = hz.gp_optimal_trajectory(
    target_position=1000.0,    # desired final position
    current_position=0.0,      # starting position
    alpha=0.005,               # expected return per period
    alpha_decay=0.1,           # alpha half-life decay rate
    temporary_impact=1e-4,     # temporary impact coefficient
    permanent_impact=5e-5,     # permanent impact coefficient
    n_periods=20,              # number of time steps
)
for step in trajectory.steps:
    print(f"t={step.time}  position={step.position:.1f}  trade={step.trade_rate:.1f}")
```

| Parameter          | Type    | Description                                 |
| ------------------ | ------- | ------------------------------------------- |
| `target_position`  | `float` | Target position to acquire                  |
| `current_position` | `float` | Starting position (default: 0.0)            |
| `alpha`            | `float` | Expected return per period from the signal  |
| `alpha_decay`      | `float` | Exponential decay rate of alpha (positive)  |
| `temporary_impact` | `float` | Temporary impact coefficient (positive)     |
| `permanent_impact` | `float` | Permanent impact coefficient (non-negative) |
| `n_periods`        | `int`   | Number of time steps in the trajectory      |

Returns a `GPTrajectory`.

### hz.gp\_execution\_cost

Estimate the total execution cost (temporary + permanent impact) for a GP trajectory.

```python theme={null}
import horizon as hz

cost = hz.gp_execution_cost(
    target_position=1000.0,
    alpha_decay=0.1,
    temporary_impact=1e-4,
    permanent_impact=5e-5,
    n_periods=20,
)
print(f"Estimated cost: {cost:.4f}")
```

| Parameter          | Type    | Description                  |
| ------------------ | ------- | ---------------------------- |
| `target_position`  | `float` | Target position size         |
| `alpha_decay`      | `float` | Alpha decay rate             |
| `temporary_impact` | `float` | Temporary impact coefficient |
| `permanent_impact` | `float` | Permanent impact coefficient |
| `n_periods`        | `int`   | Number of time steps         |

Returns `float`: total estimated execution cost.

### hz.gp\_urgency

Compute the GP urgency parameter, which determines how aggressively the model front-loads trading. Higher urgency means faster execution.

```python theme={null}
import horizon as hz

kappa = hz.gp_urgency(
    alpha_decay=0.1,
    temporary_impact=1e-4,
    permanent_impact=5e-5,
)
print(f"GP urgency (kappa): {kappa:.4f}")
```

| Parameter          | Type    | Description                  |
| ------------------ | ------- | ---------------------------- |
| `alpha_decay`      | `float` | Alpha decay rate             |
| `temporary_impact` | `float` | Temporary impact coefficient |
| `permanent_impact` | `float` | Permanent impact coefficient |

Returns `float`: the urgency parameter kappa.

### GPTrajectory Type

| Field            | Type           | Description                            |
| ---------------- | -------------- | -------------------------------------- |
| `steps`          | `list[GPStep]` | Time-indexed trajectory steps          |
| `total_cost`     | `float`        | Total estimated execution cost         |
| `urgency`        | `float`        | Computed urgency parameter (kappa)     |
| `completion_pct` | `float`        | Percentage of target position acquired |

Each `GPStep` contains:

| Field             | Type    | Description                            |
| ----------------- | ------- | -------------------------------------- |
| `time`            | `int`   | Time step index                        |
| `position`        | `float` | Optimal position at this step          |
| `trade_rate`      | `float` | Number of contracts to trade this step |
| `remaining_alpha` | `float` | Alpha remaining at this step           |
| `cumulative_cost` | `float` | Cumulative execution cost so far       |

***

## Almgren-Chriss

The AC model minimizes the expected cost of liquidating (or acquiring) a position subject to a variance penalty. The risk aversion parameter controls the trade-off between execution speed (less timing risk) and patience (less impact cost).

### hz.ac\_optimal\_schedule

Compute the optimal liquidation schedule under mean-variance preferences.

```python theme={null}
import horizon as hz

schedule = hz.ac_optimal_schedule(
    position=1000.0,            # position to liquidate
    n_periods=20,               # number of time steps
    volatility=0.02,            # per-period return volatility
    temporary_impact=1e-4,      # temporary impact coefficient
    permanent_impact=5e-5,      # permanent impact coefficient
    risk_aversion=1e-6,         # risk aversion parameter (lambda)
)
for step in schedule.steps:
    print(f"t={step.time}  remaining={step.remaining:.1f}  trade={step.trade_size:.1f}")
```

| Parameter          | Type    | Description                                 |
| ------------------ | ------- | ------------------------------------------- |
| `position`         | `float` | Total position to liquidate (positive)      |
| `n_periods`        | `int`   | Number of time steps (at least 2)           |
| `volatility`       | `float` | Per-period return volatility (positive)     |
| `temporary_impact` | `float` | Temporary impact coefficient (positive)     |
| `permanent_impact` | `float` | Permanent impact coefficient (non-negative) |
| `risk_aversion`    | `float` | Risk aversion lambda (positive)             |

Returns an `ACTrajectory`.

### hz.ac\_efficient\_frontier

Compute the efficient frontier of (expected cost, variance) pairs across a range of risk aversion values.

```python theme={null}
import horizon as hz

frontier = hz.ac_efficient_frontier(
    position=1000.0,
    n_periods=20,
    volatility=0.02,
    temporary_impact=1e-4,
    permanent_impact=5e-5,
    n_points=50,
)
for point in frontier:
    print(f"lambda={point.risk_aversion:.2e}  cost={point.expected_cost:.4f}  var={point.variance:.6f}")
```

| Parameter          | Type    | Description                             |
| ------------------ | ------- | --------------------------------------- |
| `position`         | `float` | Position to liquidate                   |
| `n_periods`        | `int`   | Number of time steps                    |
| `volatility`       | `float` | Per-period volatility                   |
| `temporary_impact` | `float` | Temporary impact coefficient            |
| `permanent_impact` | `float` | Permanent impact coefficient            |
| `n_points`         | `int`   | Number of frontier points (default: 50) |

Returns `list[FrontierPoint]` with fields `risk_aversion`, `expected_cost`, and `variance`.

### hz.ac\_kappa

Compute the AC kappa parameter that governs the curvature of the optimal trajectory.

```python theme={null}
import horizon as hz

kappa = hz.ac_kappa(
    volatility=0.02,
    temporary_impact=1e-4,
    permanent_impact=5e-5,
    risk_aversion=1e-6,
)
print(f"AC kappa: {kappa:.4f}")
```

| Parameter          | Type    | Description                  |
| ------------------ | ------- | ---------------------------- |
| `volatility`       | `float` | Per-period volatility        |
| `temporary_impact` | `float` | Temporary impact coefficient |
| `permanent_impact` | `float` | Permanent impact coefficient |
| `risk_aversion`    | `float` | Risk aversion parameter      |

Returns `float`.

### ACTrajectory Type

| Field           | Type           | Description                    |
| --------------- | -------------- | ------------------------------ |
| `steps`         | `list[ACStep]` | Time-indexed liquidation steps |
| `expected_cost` | `float`        | Expected total execution cost  |
| `variance`      | `float`        | Variance of execution cost     |
| `kappa`         | `float`        | Computed kappa parameter       |

Each `ACStep` contains:

| Field             | Type    | Description                        |
| ----------------- | ------- | ---------------------------------- |
| `time`            | `int`   | Time step index                    |
| `remaining`       | `float` | Position remaining after this step |
| `trade_size`      | `float` | Contracts to trade this step       |
| `cumulative_cost` | `float` | Cumulative cost so far             |

***

## Pipeline Integration

### hz.gp\_executor

Pipeline function for Garleanu-Pedersen execution. Reads `ctx.params["gp_request"]` and drives optimal trading each cycle.

```python theme={null}
import horizon as hz

def signal_generator(ctx):
    mid = ctx.feed.price
    # Generate alpha signal and set GP request
    ctx.params["gp_request"] = {
        "target_position": 500,
        "alpha": 0.003,
        "alpha_decay": 0.05,
        "temporary_impact": 1e-4,
        "permanent_impact": 5e-5,
    }
    return []

hz.run(
    name="gp-execution",
    markets=["0xcondition..."],
    pipeline=[
        signal_generator,
        hz.gp_executor(),
    ],
    interval=1.0,
)
```

### hz.ac\_liquidator

Pipeline function for Almgren-Chriss liquidation. Reads `ctx.params["ac_request"]` and executes the optimal schedule.

```python theme={null}
import horizon as hz

def liquidation_trigger(ctx):
    # Trigger liquidation when drawdown exceeds threshold
    if ctx.inventory.unrealized_pnl < -50.0:
        ctx.params["ac_request"] = {
            "position": abs(ctx.inventory.net_position),
            "n_periods": 10,
            "volatility": 0.02,
            "temporary_impact": 1e-4,
            "permanent_impact": 5e-5,
            "risk_aversion": 1e-6,
        }
    return []

hz.run(
    name="ac-liquidation",
    markets=["0xcondition..."],
    pipeline=[
        liquidation_trigger,
        hz.ac_liquidator(),
    ],
    interval=1.0,
)
```

***

## Mathematical Background

<AccordionGroup>
  <Accordion title="Garleanu-Pedersen (2013)">
    The GP model maximizes the trader's expected utility over a trading horizon:

    `max sum_t [alpha_t * x_t - (gamma/2) * (dx_t)^2 - (lambda/2) * (dx_t) * x_t]`

    where x\_t is position, dx\_t is trade rate, alpha\_t = alpha\_0 \* exp(-rho \* t) is decaying alpha, gamma is temporary impact, and lambda is permanent impact. The closed-form solution is an exponential trajectory with urgency kappa = sqrt(rho + lambda / gamma).
  </Accordion>

  <Accordion title="Almgren-Chriss (2001)">
    The AC model minimizes expected shortfall plus a risk penalty:

    `min E[cost] + lambda * Var[cost]`

    where cost includes both permanent impact (proportional to trade size) and temporary impact (proportional to trade rate). The optimal trajectory is `x_t = X * sinh(kappa * (T-t)) / sinh(kappa * T)` where kappa depends on risk aversion and impact parameters.
  </Accordion>

  <Accordion title="Choosing Between Models">
    Use GP when you have a decaying alpha signal (e.g., a mispricing that will correct over time). The model optimally front-loads trading to capture alpha before it decays, while controlling impact costs.

    Use AC when you have a fixed position to liquidate and no alpha signal. The model provides the cost-optimal schedule given your risk tolerance. Higher risk aversion produces faster, more expensive liquidation; lower risk aversion produces slower, cheaper liquidation with more timing risk.
  </Accordion>
</AccordionGroup>
