QuantJourney Backtester

QuantJourney Backtester

Share product feedback

✓

Thank you.

Your note is now in the QuantJourney inbox.

docs/engine/choose-path.mdx

Choose Your Engine Path

Decision guide for choosing weight mode, order mode and daily-bar execution assumptions.

Use this page when you know the strategy idea but not the right engine surface. The fastest path is usually to start with the object you already have: a signal matrix, target weights, order rules, or an execution caveat.

Sourcebacktester/core.py + backtester/execution/
LayerDecision guide
ModeWeights, orders, or both
Inputstrategy object, timing assumption and execution requirement
Outputrecommended engine path and first guide to read
Primary APIexecution_mode="weights" or execution_mode="orders"
Main caveatOrder mode is not more correct by default. It is correct when order state changes the result.

Decision Table

I have...UseStart with
Ranking signals across many namesWeight modeWeights
Target portfolio weightsWeight modeRebalancing
Cash, gross, net or leverage constraintsWeight modeWeights + Risk Models
Take-profit, stop-loss or trailing stop behaviorOrder modeStop Loss + Brackets
Limit entries with expiryOrder modeLimit Orders
Bracket or OCO behavior like BacktraderOrder modeOrder Lifecycle
A Zipline-style sizing workflowOrder mode helpersOrder Lifecycle
Daily bars and TP/SL on the same candleOrder mode plus boundary reviewExecution Assumptions

Recipes

ExampleEngine pathWhy
A. Top-10 monthly momentumWeight modeRanking and scheduled rebalance are portfolio-weight problems.
B. Long/short dollar-neutral factorWeight modeGross/net exposure belongs in the weight matrix.
C. SMA crossover with market exitOrder modeCurrent position state and market exits matter.
D. Limit entry with 3-bar expiryOrder modePending order age and cancellation are part of the result.
E. Bracket TP/SLOrder modeEntry creates managed OCO child exits after fill.
F. Gap-through stop-lossOrder mode caveatStop price is a trigger, not guaranteed execution.
G. TP and SL touched on one daily candleDaily-bar boundaryOHLC proves both touched, not the intraday sequence.
H. Signal exit cancels protective ordersOrder mode hygieneA market exit must cancel stale stop/limit/bracket/OCO children.

Example A: Top-10 Monthly Momentum

Weight mode: ranking becomes target weights
python
class TopTenMomentum(Backtester):
    def _compute_signals(self):
        close = self.instruments_data.get_feature("adj_close")
        return close.pct_change(252).rank(axis=1, ascending=False)

    def _compute_weights(self):
        ranks = self.instruments_data.get_feature(
            "strategies", self.strategy_name, "signals"
        )
        selected = ranks <= 10
        return selected.div(selected.sum(axis=1), axis=0).fillna(0.0)

strategy = TopTenMomentum(
    instruments=universe,
    backtest_period={"start": "2015-01-01", "end": "2025-01-01"},
    execution_mode="weights",
    rebalance_policy=RebalancePolicy(frequency="BME"),
)

Example D: Limit Entry With Three-Bar Expiry

Order mode: pending order state matters
python
self.fill_engine.submit(Order(
    instrument="AAPL",
    side=OrderSide.BUY,
    quantity=100,
    order_type=OrderType.LIMIT,
    limit_price=round(bars["AAPL"].close * 0.98, 2),
    expires_after_bars=3,
))

Example E: Bracket TP/SL From Actual Fill Price

Order mode: entry activates managed exits
python
self.bracket_percent("AAPL", weight=0.20, tp=0.10, sl=0.05)

Daily-Bar Boundary Test

If your thesis depends on whether the high or low happened first inside one daily candle, the model boundary is the dominant assumption. Use intraday bars or report the same-bar convention explicitly.