Class AlphaBacktester

java.lang.Object
com.quantfinlib.alpha.AlphaBacktester

public final class AlphaBacktester extends Object
Execution-aware factor backtest: runs a factor through a construction pipeline into target weights at each rebalance and simulates holding, trading and financing the book bar by bar.

Timing. Scores and targets are computed from data up to close(t). The trade fills according to AlphaBacktester.Config.fillPolicy(): at close(t) (CLOSE, the zero-latency upper bound), at open(t+1) (NEXT_OPEN, the default) or at close(t+1) (NEXT_CLOSE). Each bar is split at the open into an overnight segment close(t) → open(t+1) and an intraday segment open(t+1) → close(t+1) so a next-open fill earns exactly what it should.

Drift. Weights are fractions of equity and drift with prices between trades: after a segment with name returns r_i and book return r_p = Σ w_i r_i, w_i ← w_i (1 + r_i)/(1 + r_p). Turnover at a rebalance is measured against the drifted book. (Holding the target weights fixed every bar would be a free daily rebalance, which manufactures return for reversal-heavy books and understates turnover.) Cash is 1 − Σ w_i and earns nothing inside a segment; financing is charged separately.

Costs are charged on the traded fraction of equity: commission, half-spread and slippage in flat bps, and square-root market impact (MarketImpactModel.estimate(BarSeries, int, int), with ADV and volatility from the bars before the fill bar) on the traded shares |Δw|·capital·equity/price. Costs come out of equity and the executed weights are fractions of post-cost equity.

Participation cap. With maxParticipation > 0 each name trades at most maxParticipation × ADV shares per bar; the unexecuted remainder carries over to the next bar's fill point until the target is reached or replaced by the next rebalance. The mean distance from the target is reported as AlphaBacktester.Result.meanTrackingGap().

Financing per bar, from the book held over the bar: a borrow fee on short notional, interest on positive cash (1 − Σw, which includes short sale proceeds, so the short rebate is implicit), and a margin rate on negative cash (leverage). Rates are annual and accrue 1/periodsPerYear per bar.

Terminal events. Returns come from AlphaContext.returnBetween(int, int, boolean, int, boolean), so a held name that delists earns its delisting return; the position then becomes cash, or acquirer shares for a stock merger whose acquirer is in the panel. Names dead at a fill point cannot be traded.

The gross curve applies the same book without trading costs or financing. For share-level accounting with dividends and index drops use backtest.portfolio.PortfolioBacktester.