Owns the PubSub topics, alert thresholds, and broadcasting logic for portfolio risk events.
Two kinds of messages go out over RiskEngine.PubSub:
{:risk_update, snapshot}on the risk topic (default"portfolio:risk") — sent after every trade, regardless of whether any threshold was crossed.{:alert, alert}on the alerts topic (default"alerts") — sent only when a portfolio's drawdown or volatility exceeds its configured threshold.
Topics and thresholds are configurable per environment:
config :risk_engine, RiskEngine.RiskBroadcaster,
risk_topic: "portfolio:risk",
alerts_topic: "alerts",
drawdown_threshold: 20.0,
volatility_threshold: 5_000.0
Summary
Types
A threshold breach for a single portfolio metric.
A point-in-time snapshot of a portfolio's risk metrics.
Functions
Broadcasts the current risk snapshot for a portfolio on the risk topic.
Checks a portfolio's drawdown and volatility against their configured
thresholds and broadcasts a {:alert, alert} message on the alerts topic
for each one that's exceeded.
Types
@type alert() :: %{ portfolio_id: String.t(), type: :drawdown | :volatility, value: float(), at: DateTime.t() }
A threshold breach for a single portfolio metric.
@type snapshot() :: %{ portfolio_id: String.t(), cash_exposure: float(), peak_exposure: float(), volatility: float(), drawdown_pct: float(), updated_at: DateTime.t() | nil }
A point-in-time snapshot of a portfolio's risk metrics.
Functions
@spec broadcast_risk_update(RiskEngine.Portfolio.Server.t()) :: :ok | {:error, term()}
Broadcasts the current risk snapshot for a portfolio on the risk topic.
Sends {:risk_update, snapshot} unconditionally — call check_alerts/1
separately to raise threshold alerts.
@spec check_alerts(RiskEngine.Portfolio.Server.t()) :: :ok | {:error, term()} | nil
Checks a portfolio's drawdown and volatility against their configured
thresholds and broadcasts a {:alert, alert} message on the alerts topic
for each one that's exceeded.
A single call can raise zero, one, or both kinds of alert.