Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mathematicalcompany.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Ultra Feature. Requires an Ultra subscription. Get started at api.mathematicalcompany.com
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.

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.

Garleanu-Pedersen

Optimal trading with alpha decay. Balances urgency from decaying signals against temporary and permanent market impact.

Almgren-Chriss

Optimal liquidation under mean-variance preferences. Minimizes the expected cost plus risk penalty of unwinding a position.

Trajectory Output

Both models produce time-indexed position trajectories with per-step trade rates and cost estimates.

Pipeline Integration

hz.gp_executor() and hz.ac_liquidator() drive real-time execution within hz.run().

Model Comparison

AspectGarleanu-PedersenAlmgren-Chriss
Use casePortfolio transition with alpha signalPure liquidation / acquisition
ObjectiveMaximize alpha capture minus impact costMinimize expected cost + risk penalty
Key parameterAlpha decay rate (kappa)Risk aversion (lambda)
Trade profileFront-loaded when alpha decays fastDepends on risk aversion
Permanent impactYes (linear)Yes (linear)
Temporary impactYes (linear)Yes (linear)
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.

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.
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}")
ParameterTypeDescription
target_positionfloatTarget position to acquire
current_positionfloatStarting position (default: 0.0)
alphafloatExpected return per period from the signal
alpha_decayfloatExponential decay rate of alpha (positive)
temporary_impactfloatTemporary impact coefficient (positive)
permanent_impactfloatPermanent impact coefficient (non-negative)
n_periodsintNumber 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.
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}")
ParameterTypeDescription
target_positionfloatTarget position size
alpha_decayfloatAlpha decay rate
temporary_impactfloatTemporary impact coefficient
permanent_impactfloatPermanent impact coefficient
n_periodsintNumber 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.
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}")
ParameterTypeDescription
alpha_decayfloatAlpha decay rate
temporary_impactfloatTemporary impact coefficient
permanent_impactfloatPermanent impact coefficient
Returns float: the urgency parameter kappa.

GPTrajectory Type

FieldTypeDescription
stepslist[GPStep]Time-indexed trajectory steps
total_costfloatTotal estimated execution cost
urgencyfloatComputed urgency parameter (kappa)
completion_pctfloatPercentage of target position acquired
Each GPStep contains:
FieldTypeDescription
timeintTime step index
positionfloatOptimal position at this step
trade_ratefloatNumber of contracts to trade this step
remaining_alphafloatAlpha remaining at this step
cumulative_costfloatCumulative 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.
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}")
ParameterTypeDescription
positionfloatTotal position to liquidate (positive)
n_periodsintNumber of time steps (at least 2)
volatilityfloatPer-period return volatility (positive)
temporary_impactfloatTemporary impact coefficient (positive)
permanent_impactfloatPermanent impact coefficient (non-negative)
risk_aversionfloatRisk 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.
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}")
ParameterTypeDescription
positionfloatPosition to liquidate
n_periodsintNumber of time steps
volatilityfloatPer-period volatility
temporary_impactfloatTemporary impact coefficient
permanent_impactfloatPermanent impact coefficient
n_pointsintNumber 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.
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}")
ParameterTypeDescription
volatilityfloatPer-period volatility
temporary_impactfloatTemporary impact coefficient
permanent_impactfloatPermanent impact coefficient
risk_aversionfloatRisk aversion parameter
Returns float.

ACTrajectory Type

FieldTypeDescription
stepslist[ACStep]Time-indexed liquidation steps
expected_costfloatExpected total execution cost
variancefloatVariance of execution cost
kappafloatComputed kappa parameter
Each ACStep contains:
FieldTypeDescription
timeintTime step index
remainingfloatPosition remaining after this step
trade_sizefloatContracts to trade this step
cumulative_costfloatCumulative 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.
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.
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

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).
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.
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.