Backtesting
Alpha
Test whether a trading signal is profitable over a long period. Instead of replaying every order book change, the engine checks each market at a fixed interval and trades it to the position your signal wants. To model how a strategy fills against the real order book, use the Execution backtest.
Quick Start
Each bar, the engine trades every market to your target, filling at the next bar's mid with slippage and platform-accurate fees.
Runs on the synchronous client. Latency, queue position, and the other execution-engine options have no effect here. Subtypes, results, saving, and the dashboard are shared; see Runs.
from marketlens import MarketLens
from marketlens.backtest import AlphaStrategy
class MomentumTilt(AlphaStrategy):
def on_market_start(self, ctx, market, bar):
self._prev = None
def on_bar(self, ctx, market, bar):
if self._prev is not None:
move = bar.mid - self._prev
ctx.target_weight(max(-1.0, min(1.0, 50 * move)))
self._prev = bar.mid
client = MarketLens()
result = client.backtest(
strategy=MomentumTilt(),
id="nyc-daily-weather",
initial_cash=10_000,
resolution="1m",
price="mid",
fill="next",
slippage_bps=5,
after="2026-07-07T18:00:00Z",
before="2026-07-08T02:00:00Z",
)
print(result.summary())Strategies
Override on_bar and set a target. The engine calls it once per market per bar.
class MyAlpha(AlphaStrategy):
def on_market_start(self, ctx, market, bar):
self._prev = None
def on_bar(self, ctx, market, bar):
if self._prev is not None and bar.mid > self._prev:
ctx.target_weight(0.25)
else:
ctx.target_weight(0.0)
self._prev = bar.mid
def on_market_end(self, ctx, market):
print(ctx.position().shares)Context
Passed to every hook. Set a target, read positions, and query state. Targets persist until you change them, so re-asserting one trades nothing.
# signed fraction of equity (order_target_percent)
ctx.target_weight(0.20)
# or a signed share count
ctx.target_position(500)# rebalance off bar state and current PnL
pos = ctx.position()
if ctx.bar.spread > 0.05 or pos.unrealized_pnl < -200:
ctx.target_weight(0.0)Bars
A bar is one market's state over a single interval, for example one minute at resolution 1m. The engine fills and marks at its mid. price="mid" bars carry spread and depth; price="close" bars carry OHLCV.
def on_bar(self, ctx, market, bar):
# bar.mid is the fill and mark price in every mode
if bar.spread < 0.03 and bar.bid_depth > bar.ask_depth:
ctx.target_weight(0.30)