factrix.metrics.event_horizon ¶
Multi-horizon event analysis — how does the density behave across time?
Answers
- Is there pre-event leakage? (T-6..T-1 should be ~0)
- At which horizon is the density strongest?
- Does the alpha persist or decay quickly?
Metrics
compute_event_returns — per-event, per-offset raw return data event_around_return — return profile summary at each offset
Notes
Pipeline. Per-event return profile across k offsets
(per-event step); a descriptive curve only — no hypothesis test, so
p_value is None and the per-horizon hit_rate in
per_offset is a raw fraction, not a tested statistic.
factrix.metrics.event_horizon.event_around_return ¶
event_around_return(data: DataFrame, *, offsets: list[int] | None = None, factor_col: str = 'factor', price_col: str = 'price') -> MetricResult
Return profile at multiple offsets around event date.
No static panel-shape thresholds are declared (sample_threshold=SampleThreshold()) because this is a multi-horizon summary metric whose available offsets and event counts are factor-context-dependent.
Summarizes per-offset: mean, median, p25, p75, hit_rate, n.
The primary value is the pre-event leakage score: mean absolute return at pre-event offsets (should be ~0). High leakage → density may be reactive, not predictive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
Panel with |
required |
offsets
|
list[int] | None
|
Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
MetricResult
|
MetricResult with per-offset stats in metadata. When price data is |
MetricResult
|
unavailable, returns a short-circuit MetricResult ( |
MetricResult
|
|
MetricResult
|
single return contract. |
Notes
For each offset k: mean, median, p25, p75, hit_rate
across events with valid signed_return. The headline
value = mean_{k < 0} |mean_k| summarises pre-event leakage —
a healthy density has flat pre-event means.
factrix uses |mean| rather than absolute returns to avoid
rewarding offsets where positive and negative pre-event drifts
cancel — leakage with consistent direction would be missed by
mean(|return|).
Examples:
>>> import factrix as fx
>>> from factrix.preprocess import compute_forward_return
>>> from factrix.metrics.event_horizon import event_around_return
>>> panel = compute_forward_return(
... fx.datasets.make_event_panel(n_assets=50, n_dates=400, seed=0),
... forward_periods=5,
... )
>>> result = event_around_return(panel)
>>> result.name == ""
True
Offset conventions
Defaults: offsets = [-6, -3, -1, 1, 6, 12, 24]. Offset 0 is the
event date itself and is excluded from the defaults; user-supplied
offsets lists are honoured verbatim.
| \(k\) | Anchor | Formula | Sign-adjusted |
|---|---|---|---|
| \(k > 0\) (post-event) | Cumulative from \(t+1\) entry | price[t+1+k] / price[t+1] − 1 |
Yes — multiplied by sign(factor). The reading is signal quality. |
| \(k < 0\) (pre-event) | Single bar at offset | price[t+k] / price[t+k−1] − 1 |
No — the reading is leakage, where the bar's directional response matters independent of the eventual signal sign. |
| \(k = 0\) (corner) | Single bar at event | price[t] / price[t−1] − 1 |
No — falls into the pre-event branch. Pass with care; the event-day bar is usually contaminated by the announcement itself. |
The pre/post asymmetry is intentional. Mixing the two conventions on a single chart (post-event cumulative + pre-event single-bar) is the default factrix presentation; downstream consumers should not re-cumulate the pre-event leg.
Serial correlation across offsets
The binomial null at each offset assumes per-event independence at that offset. Adjacent post-event offsets are serially correlated within the same event — \(k = 6\) and \(k = 12\) share the \(t+1\) entry price and overlap on bars \([t+2, t+7]\). The reported per-offset \(p\)-values therefore have understated variance under the joint null across offsets; treat the curve as descriptive and read the binomial \(p\) one offset at a time. See also the confounded-event note on within-asset event clustering, which compounds the same issue.
Use cases¶
-
Right-size the event window
Read the post-event mean curve over \(k = 1 \ldots K\) to locate the horizon where signed drift peaks before reverting. Drives the choice of
EventConfig.event_window_postfor downstream MFE/MAE and CAAR work. -
Pre-event leakage check
Inspect \(k < 0\) mean returns: a healthy signal has flat pre-event means. The headline
event_around_return.valueis \(\mathrm{mean}_{k < 0} |\mathrm{mean}_k|\), summarising the leakage score in a single number.
Choosing a function¶
| Goal | Function |
|---|---|
| Per-event, per-offset raw return table for custom plots / cuts | compute_event_returns |
| Per-offset summary (mean / median / quartiles / hit-rate) with pre-event leakage headline | event_around_return |
Worked example — leakage score + per-offset curve¶
compute_event_returns → event_around_return on a synthetic event panel
import factrix as fx
from factrix.metrics.event_horizon import (
compute_event_returns, event_around_return,
)
panel = fx.datasets.make_event_panel(
n_assets=200, n_dates=500, event_rate=0.02,
post_event_drift_bps=40.0, seed=2024,
)
rets = compute_event_returns(panel, offsets=[-6, -3, -1, 1, 6, 12, 24])
print(rets.head())
# ┌────────┬────────────┬──────────┬────────────────┐
# │ offset ┆ date ┆ asset_id ┆ signed_return │
# ├────────┼────────────┼──────────┼────────────────┤
# │ -6 ┆ 2024-01-04 ┆ A0001 ┆ 0.0012 │
# │ 1 ┆ 2024-01-04 ┆ A0001 ┆ 0.0041 │
# │ ... ┆ ... ┆ ... ┆ ... │
# └────────┴────────────┴──────────┴────────────────┘
out = event_around_return(panel)
print(out.value) # mean |pre-event mean|
print(out.metadata["per_offset"][6]["mean"]) # post-event signed mean at k=6
# 0.0007 0.0094 (approximate)
See also¶
-
mfe_mae
Per-event excursion analysis on the same post-event window — peak favourable / adverse move and bars-to-peak.
-
caar/bmp_z
Inferential CAAR / BMP tests on the chosen
forward_periodshorizon. -
clustering_hhi
Event-date Herfindahl-Hirschman index (HHI) — the serial-correlation caveat above compounds with same-date clustering.
-
Metric applicability reference
Event-window / estimation-window contracts and confounded-event handling.
-
Individual × Sparse landing
Adjacent event-study metrics in the same cell.