Per-Asset-Class Risk
Different rules for equities, options, perps, and prediction markets
Different asset classes have different risk profiles. A 10% stop makes sense for an equity position but is way too wide for an options position and misleading for a prediction market where the native concept is “days to resolution” not “unrealized P&L.” per_asset_class lets you configure each class with its own AssetRisk bundle.
The dataclass
@dataclass
class AssetRisk:
# Stops for this asset class
stop_loss: Any = None
time_stop: Any = None
# Generic sizing caps
max_gross_notional_usd: float | None = None
max_position_pct_of_adv: float | None = None
max_position_notional_usd: float | None = None
# Equity-specific
max_sector_exposure: float | None = None
exclude_earnings_within_days: int | None = None
# Option-specific
max_portfolio_delta: float | None = None
max_portfolio_gamma: float | None = None
max_portfolio_vega: float | None = None
max_theta_burn_per_day_usd: float | None = None
# Perp-specific
max_leverage: float | None = None
liquidation_buffer_pct: float | None = None
max_funding_exposure_per_day_usd: float | None = None
# Prediction-market-specific
max_per_event_usd: float | None = None
min_days_to_resolution: int | None = None
Usage
from horizon.asset_classes import Equity, Option, Perp, Prediction
from horizon.risk import (
AssetRisk,
GreekStop,
RiskConfig,
StopLoss,
)
risk = RiskConfig(
per_asset_class={
Equity: AssetRisk(
stop_loss=StopLoss(per_position_pct=0.10, trailing_pct=0.05),
max_sector_exposure=0.40,
exclude_earnings_within_days=3,
),
Option: AssetRisk(
stop_loss=GreekStop(
close_if_delta_over=0.70,
close_if_gamma_over=0.08,
close_if_dte_under=2,
),
max_portfolio_delta=1000,
max_portfolio_gamma=50,
max_portfolio_vega=500,
max_theta_burn_per_day_usd=200,
),
Perp: AssetRisk(
stop_loss=StopLoss(per_position_pct=0.08),
max_leverage=3.0,
liquidation_buffer_pct=0.30,
max_funding_exposure_per_day_usd=50,
),
Prediction: AssetRisk(
stop_loss=StopLoss(per_position_usd=500),
max_per_event_usd=2_000,
min_days_to_resolution=3,
),
},
)
Equity
Option
Perp
Prediction
Combining with global risk
Per-asset-class rules live alongside the global risk layers:
risk = RiskConfig(
# Global. applies across all asset classes
per_order=OrderRisk(max_order_notional_usd=25_000),
drawdown=[DrawdownGuard(daily_pct=0.05, action=HaltNew)],
kill_switch=KillSwitch(auto_trigger_on=[PortfolioDrawdownEvent(0.25)]),
# Per asset class. applies only to that class
per_asset_class={
Equity: AssetRisk(stop_loss=StopLoss(per_position_pct=0.10)),
Option: AssetRisk(stop_loss=GreekStop(close_if_delta_over=0.70)),
},
)
Both run. Per-order checks apply to every order regardless of class; drawdown guards apply to total equity regardless of composition; kill switch fires on total drawdown. The per-class stops fire only on positions in the matching class.
When the strategy is multi-asset
If your strategy trades multiple asset classes and you want different rules for each, per_asset_class is the cleanest way to express it. Without it, you’d need separate risk configs per strategy, which wouldn’t work because risk is evaluated at the portfolio level.