openquant._core.pipeline
Compiled from Rust (crates/pyopenquant). Signatures and types are from the shipped .pyi stubs; descriptions are the functions’ own docstrings, as help() shows them. All Python modules.
Functions
infer_periods_per_year
infer_periods_per_year(timestamps: Sequence[str]) -> float | NoneBars a year implied by the spacing of timestamps, for periods_per_year.
Takes the median gap between consecutive strictly increasing timestamps (zero and negative gaps are skipped) and maps it with a US equity convention of 252 sessions of 390 minutes (6.5 hours) a year: a gap under 20 hours gives 252 * 390 / gap_minutes (one-minute bars: 98280, five-minute: 19656, hourly: 1638); a gap from 20 hours to under 4 days gives 252 (daily bars, weekends and holidays included); a longer gap gives 365.25 / gap_days (weekly: 52.18). Bars that trade around the clock keep the session convention; pass periods_per_year explicitly for a 24-hour one. For tick, volume or dollar bars the result is only the typical bar rate.
Parameters
timestamps: list[str]Bar timestamps as
"%Y-%m-%d %H:%M:%S"(an optional fractional second is accepted), oldest first.
Returns
- float | None
Bars a year, or None when fewer than two timestamps strictly increase.
Raises
- ValueError
If a timestamp does not parse.
run_mid_frequency_pipeline
run_mid_frequency_pipeline(
timestamps: Sequence[str],
close: Sequence[float],
model_probabilities: Sequence[float],
asset_prices: Sequence[Sequence[float]],
model_sides: Sequence[float] | None = None,
asset_names: Sequence[str] | None = None,
cusum_threshold: float = 0.001,
num_classes: int = 2,
step_size: float = 0.1,
risk_free_rate: float = 0.0,
confidence_level: float = 0.05,
periods_per_year: float = 252.0,
) -> AnyRun the events, signals, portfolio, risk and backtest research pipeline in one call.
Chains existing modules on one instrument: (1) the symmetric CUSUM filter on close selects events (AFML Snippet 2.4); (2) the model probability and side at each event become a bet size 2 Phi(z) - 1 (AFML Snippet 10.1), rounded to multiples of step_size (Snippet 10.3) and held on every bar until the next event; (3) max-Sharpe mean-variance weights of asset_prices are computed (Markowitz, not AFML); (4) historical VaR, expected shortfall and conditional drawdown at risk of the strategy are computed, plus a Sharpe ratio annualised with periods_per_year (AFML section 14.7.1); (5) the equity curve, drawdowns and time under water are built (AFML Snippet 14.4). No labelling or model fitting happens here; probabilities and sides are inputs, one per bar.
The signal is applied with a one-bar lag: the strategy return over bar i is signal[i - 1] * (close[i] / close[i - 1] - 1). The portfolio stage is independent of the backtest (its weights are reported, not traded). risk_free_rate is an annual rate in both the allocation and realized_sharpe (which subtracts risk_free_rate / periods_per_year per bar). confidence_level is the lower-tail probability for VaR and expected shortfall (0.05 = worst 5% of per-bar returns); CDaR uses 1 - confidence_level.
Parameters
timestamps: list[str]Bar timestamps as
"%Y-%m-%d %H:%M:%S"(an optional fractional second is accepted), oldest first. Their order is not enforced;leakage_checks["timestamps_increasing"]reports it.close: list[float]Positive closing prices of the traded instrument, one per bar.
model_probabilities: list[float]Probability of the predicted class at each bar, in
[0, 1], known at that bar's close. Only values at CUSUM events are used, but every value must be in[0, 1].asset_prices: list[list[float]]Prices for the portfolio stage, one inner list per observation (oldest first, at least 2 rows, one per entry of
timestamps) and one column per asset.model_sides: list[float] | None, default NoneSide of the prediction at each bar (typically +1/-1); None means always long.
asset_names: list[str] | None, default NoneOne name per column of
asset_prices; defaults toasset_0,asset_1, ...cusum_threshold: float, default 0.001CUSUM threshold on cumulative log returns of
close; must be finite and > 0.num_classes: int, default 2Number of classes of the model behind
model_probabilities; must be >= 2.step_size: float, default 0.1Bet sizes are rounded to multiples of this step and clamped to
[-1, 1]; must be finite and > 0.risk_free_rate: float, default 0.0Annual risk-free rate, for the max-Sharpe allocation and for
realized_sharpe.confidence_level: float, default 0.05Lower-tail probability for VaR and expected shortfall, in
[0, 1].periods_per_year: float, default 252.0Bars a year of
closeand rows a year ofasset_prices. Annualisesrealized_sharpeand the portfolio's return, risk and Sharpe ratio; must be finite and > 0. The default is right for daily bars only: one-minute bars on a 390-minute (6.5-hour) session have252 * 390 = 98280a year.infer_periods_per_yearderives the value from the timestamps;openquant.pipeline.run_mid_frequency_pipelinedoes so by default.
Returns
- dict[str, Any]
A dict of stage dicts:
events:indices(0-based bar positions of the CUSUM events),timestamps,probabilitiesandsides(1.0 when no sides were given) at those events.signals:timestamps(the input bar timestamps),values(bet size on every bar, 0 before the first event) andevent_signal(discretised bet size in[-1, 1]per event).portfolio:asset_names,weights(sum to 1),portfolio_risk,portfolio_returnandportfolio_sharpe(all annualised).risk:value_at_risk(signed per-bar return, negative is a loss),expected_shortfall(mean of returns strictly below VaR, NaN when none are),conditional_drawdown_risk(in equity units) andrealized_sharpe(annualised withperiods_per_year).backtest:timestamps,strategy_returns(one shorter thanclose),equity_curve(starts at 1),drawdownsandtime_under_water_years(one per drawdown, in 365.25-day years).leakage_checks: booleanstimestamps_increasing(the timestamps strictly increase) andevent_indices_sorted, computed from the data, plus the deprecated constantsinputs_aligned(always True: mismatched lengths raise) andhas_forward_look_bias(always False: the pipeline does not detect look-ahead in the caller's probabilities or sides).
Raises
- ValueError
If a value is outside the range given under Parameters (a probability outside
[0, 1],cusum_thresholdorstep_sizenot finite and > 0, orasset_priceswithout one row per timestamp); a timestamp does not parse;asset_pricesis empty or ragged;timestamps,closeormodel_probabilitiesis empty;closediffers in length fromtimestamps,model_probabilitiesormodel_sides, orasset_namesfrom the number of assets;asset_priceshas fewer than 2 rows,cusum_threshold <= 0,num_classes < 2,confidence_levelis outside[0, 1]orperiods_per_yearis not finite and > 0; the CUSUM filter finds no event; or the max-Sharpe optimisation fails.