Class Backtester
Fills. The strategy decides at bar i's close (its
indicators include close(i)). The order fills according to
BacktestConfig.fillPolicy(): at open(i+1) by default, at
close(i+1), or at close(i) (the optimistic zero-latency
mode). Fills are adjusted by slippageRate against the trader and
commission is charged on entry and exit notional. A signal on the last
bar under a next-bar policy has nothing to fill against and is dropped.
Stops. Stop-loss and take-profit levels are checked intrabar
against the bar's low and high, from the first bar whose whole range
lies after the entry: the entry bar itself for a next-open entry, the
following bar for close entries. A gap through the level fills at the
open. Stop fills also pay slippageRate: a stop is a market order
and fills worse than its trigger in a fast market. When both levels lie
inside one bar's range the stop wins, since the bar data cannot say which
was touched first and assuming the loss is the conservative reading.
Order of events on bar i. (1) a pending next-open order fills
at open(i); (2) stops are checked; (3) a pending next-close order
fills at close(i); (4) the strategy is asked for a signal via
TradingStrategy.onBar(int, double) with the quantity now held;
(5) under CLOSE the signal fills immediately, otherwise it waits.
A pending order is dropped when it no longer applies (a stop already
closed the position, or the book is already in the requested state).
Segments. runSegment(TradingStrategy, BarSeries, BacktestConfig, int, Backtester.State, int, boolean) runs over a window with a
starting Backtester.State and returns the end state instead of liquidating,
which is how WalkForwardAnalyzer carries a position across fold
boundaries without a forced exit and re-entry per fold.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordA segment's result and the state it ended in.static final recordBook state carried between segments. -
Method Summary
Modifier and TypeMethodDescriptionstatic BacktestResultrun(TradingStrategy strategy, BarSeries series, BacktestConfig config) static BacktestResultrun(TradingStrategy strategy, BarSeries series, BacktestConfig config, int tradeFrom) Variant with a warm-up prefix: indicators are initialised over the whole series, but no signal is acted on (and no equity recorded) beforetradeFrom.static Backtester.SegmentrunSegment(TradingStrategy strategy, BarSeries series, BacktestConfig config, int tradeFrom, Backtester.State start, int indexOffset, boolean liquidateAtEnd) Runs bars[tradeFrom, n)ofseriesstarting fromstart.static BacktestResultrunWholeLots(TradingStrategy strategy, BarSeries series, BacktestConfig config, double lotSize) Asrun(TradingStrategy, BarSeries, BacktestConfig)but entries buy a whole number of lots instead of investing all cash.
-
Method Details
-
run
-
run
public static BacktestResult run(TradingStrategy strategy, BarSeries series, BacktestConfig config, int tradeFrom) Variant with a warm-up prefix: indicators are initialised over the whole series, but no signal is acted on (and no equity recorded) beforetradeFrom. Walk-forward analysis uses this to avoid re-computing every indicator cold on each test window. The returned equity curve covers[tradeFrom, n). Any position open at the last bar is closed there atclose(n−1)(Trade.REASON_END_OF_DATA).The warm-up only warms what
TradingStrategy.init(BarSeries)precomputes (all shipped strategies);onBaris not called for warm-up bars. -
runWholeLots
public static BacktestResult runWholeLots(TradingStrategy strategy, BarSeries series, BacktestConfig config, double lotSize) Asrun(TradingStrategy, BarSeries, BacktestConfig)but entries buy a whole number of lots instead of investing all cash.The plain idea: a real account cannot hold 37.4 shares. An entry buys the largest multiple of
lotSizethat cash covers after slippage and commission, and the rest stays in cash. Formally, with fill pricefand commission ratec, the quantity isq = lot * floor(cash / (f (1 + c) lot)); the entry paysq f (1 + c). Whenq = 0the signal is dropped. Worked example (own test): cash 1000, price 30, lot 1, no costs givesq = 33and 10 left in cash, which is what the tick backtester and the paper gateway fill.- Parameters:
lotSize- positive lot size, 1 for whole shares- Since:
- 2.2.0
-
runSegment
public static Backtester.Segment runSegment(TradingStrategy strategy, BarSeries series, BacktestConfig config, int tradeFrom, Backtester.State start, int indexOffset, boolean liquidateAtEnd) Runs bars[tradeFrom, n)ofseriesstarting fromstart. Trade indices are reported aslocal index + indexOffset, so a caller running on a slice of a longer series passes the slice's starting index and gets indices into the full series.start.entryIndex()is absolute in the same sense.- Parameters:
liquidateAtEnd- close any open position atclose(n−1)(asrun(TradingStrategy, BarSeries, BacktestConfig)does); otherwise carry it in the returned state
-