BANGER
Product status: Banger’s public beta is paper-only. References to live execution are future-looking. Venue rules and legal claims can change; verify current primary sources for your jurisdiction.
2026-10-03 · 4 min read · reviewed 2026-10-14

Your First Python Paper Strategy: Observe Before Placing Orders

Start by checking that your strategy receives the market data you expect. A no-order observer logs one structured observation from an actual market callback. It helps isolate data handling before you add decisions or simulated order logic.

This walkthrough builds an observer and distinguishes delivered data from execution evidence. A single observation can help inspect the callback and logging path. It cannot establish continuous coverage, simulated fill behavior or returns.

Why start with an observer

Feed handling can fail because a price uses unexpected units, a side is confused, or a timestamp is interpreted incorrectly. An observer helps reveal those mistakes without calling any order method.

For binary Kalshi contracts, the raw orderbook endpoint returns YES and NO bids. The complementary side determines the corresponding ask price. Current documented fixed-point fields include yes_dollars and no_dollars inside orderbook_fp. These are venue response fields, not the normalized attributes passed to a Banger strategy.

Keep the raw venue response separate from Banger's normalized Tick. The SDK uses Decimal prices, optional bid and ask values, and a datetime timestamp. Missing quotes should remain visible as missing values; do not turn them into zero or assume the raw timestamp unit applies to the SDK object.

The contract: observe, do not trade

A Banger strategy subclasses Strategy and declares its venues and universe. The market callback is on_market_tick(self, market, tick, ctx). Use ctx.log(message, **fields) for structured logging. The observer below sets a flag after its first observation and has no calls to place, close, or cancel.

This example is checked against the public Banger 0.1.7 wheel and its bundled runtime source. The CLI documentation covers account setup; inspect the installed SDK signature without connecting to a venue:

pip install bangertrades==0.1.7
python -c "import inspect; from banger import Strategy, Tick; print(inspect.signature(Strategy.on_market_tick)); print(Tick.__annotations__)"

Replace REPLACE_WITH_CURRENT_OPEN_TICKER with the exact ticker of an open Kalshi market you have selected. An expired ticker cannot prove current market-data delivery. Save the following as strategy.py. It logs once, including explicit nulls for missing bid or ask values:

from banger import Strategy, signals
from banger_adapter_kalshi import Kalshi


class MarketObserver(Strategy):
    name = "market-observer"
    venues = [Kalshi()]
    universe = signals.kalshi_markets(
        status="open",
        tickers=["REPLACE_WITH_CURRENT_OPEN_TICKER"],
    )

    def on_start(self, ctx):
        self._observed = False

    def on_market_tick(self, market, tick, ctx):
        if self._observed:
            return
        self._observed = True
        spread = (
            tick.ask - tick.bid
            if tick.bid is not None and tick.ask is not None
            else None
        )
        ctx.log(
            "market_observation",
            market_id=market.market_id,
            bid=str(tick.bid) if tick.bid is not None else None,
            ask=str(tick.ask) if tick.ask is not None else None,
            spread=str(spread) if spread is not None else None,
            timestamp=tick.timestamp.isoformat(),
        )
        # No order method is called.

For the local CLI path, configure your Banger account as described in the CLI documentation before running banger run strategy.py --paper. This creates a local paper record in the control plane and reads public market data; it does not send orders to Kalshi. Stop with Ctrl+C after a short supervised check, for example five minutes. This article's code was tested offline with fixture ticks, not by starting a production session.

Read the log like a checklist

Inspect the one observation against the selected market. This example intentionally suppresses subsequent logs; if you need to study updates over time, deliberately extend it with a bounded sampling procedure.

A valid observation provides limited evidence that the selected market callback and logging path work. A broader feed or trading acceptance needs its own procedure.

What this test cannot prove

An observer does not test fills. It has no order call, so zero orders and fills are expected. It does not show whether a hypothetical order would execute at the displayed price or size, nor does it measure fees, slippage, or returns.

A displayed quote describes the book at an observed time. Paper fills depend on the simulator and available data; they are research evidence, not a guarantee of venue execution or profitability.

Banger’s public product is a paper research beta. The local observer requires no venue trading keys and does not enable live trading. Its first log can contain missing or invalid quote observations; inspect those values rather than treating the log as validated data. Preserve the version and verify shutdown. Adding order logic requires a separate bounded experiment.

Sources

Keep reading

Run your first strategy free

Paper-trade on Polymarket and Kalshi market data without venue keys.

Start free