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-20 · 6 min read · facts as of 2026-10-20

How to Write a Useful Paper Research Experiment Log

A paper experiment is only as useful as the record you keep of it. Six weeks later, "the NFL spread strategy looked good" tells you nothing. Which version? Which market? How many ticks actually arrived? Did you stop it cleanly or did it crash? Without those answers you cannot reproduce the run, and a result you cannot reproduce is not evidence of anything.

This is a manual logging discipline, not a product feature. No tool writes this record for you. Below is a compact template you can keep in a plain text file or a notebook next to each run. It is built for prediction-market paper research, where the gap between a simulated fill and a real venue execution is the whole point of being careful.

What a paper result actually is

Write this at the top of every log so you never forget it. A paper result is evidence under one specific data feed, one fill model, one fee model and one valuation model. It is not proof that the same orders would have filled on the venue, at those prices, for those fees. A forward-paper simulator that fills a non-crossing limit at the limit price is making an assumption, not observing a match. Tools like Banger make that explicit by logging a marker such as paper.fill.resting-assumed when a resting fill is assumed rather than crossed. Record which assumption produced each fill.

Keep marked value, settlement claim, credited cash and hypothetical executable proceeds as separate numbers. They are not interchangeable. A position marked at 60 cents is not 60 cents of cash you could realize, and a contract that settles at a dollar is a settlement claim, not a fill.

The fields to capture

Every entry should answer the same questions in the same order. Consistency is what makes a stack of logs comparable.

Market identity and data coverage

These two fields fail the most often. For identity, paste the live ticker string exactly. For coverage, log the gap between what you planned to observe and what arrived. A simulator's reported-volume quantity cap is not full order-book depth, and missing quotes can trigger a price fallback. If you do not write down that a fill was capped by reported volume or that a price came from a fallback, you will later read the result as cleaner than it was. Preserve unknowns as unknowns. An empty field that says "ask absent for 40s around 18:12 UTC" is more honest than a tidy number you invented.

Simulated orders, fills and fees

Log the request and the result as separate lines, because they differ. In a USD-notional interface, a request is a dollar size at a price, and the fill is whatever the model decided. Note whether the fill crossed the book or was an assumed resting fill. Note the fee model used, because fee rounding changes small-trade P&L. Banger's packaged standard Kalshi fee helper rounds up to a whole cent.

That helper is a simplification. Kalshi's published fee schedule, effective 7 July 2026, gives the general taker trading fee as round up(M x 0.07 x C x P x (1 - P)), where M is a per-series multiplier, C is contracts and P is price in dollars. The curve peaks near a 50 cent price and shrinks toward both ends, so at 100 contracts the fee is about $1.75 at 50 cents and about $0.63 at 10 cents or 90 cents. Some series carry maker fees or different multipliers. If your log's fee model rounds differently from the venue's finer fee-plus-position-cost rounding, say so. Do not confuse the raw per-contract fee component with an effective percentage of your stake, and do not treat a simplified helper as the venue's exact invoice.

Stop evidence is not optional

"I stopped it" is a claim. Stop evidence is proof. For a short supervised local check, a Ctrl+C and the final log lines are your evidence that the worker exited. A log count bounds output, not the lifetime of the run, so do not read a capped log as a stopped process. If you ran a hosted paper deployment, stopping needs its own confirmation: a stopped record and completed resource cleanup. A stopped badge can appear before cancellation actually completes, so wait for the completed state before you write the run down as finished.

One more line to include: stopping a paper run preserves your research history and says nothing about any real account's positions. There is nothing to flatten in paper, but writing that down keeps the mental model clean for the day you are not in paper.

Where risk limits fit

If your run used a risk envelope, log the fields you set and what they actually do, not what you wish they did. A max_position_usd caps cumulative cost basis, not a per-order stake. A forward-paper daily-loss control rejects new exposure after mark-to-market loss from the current UTC-day baseline hits its limit. It does not automatically flatten existing holdings, it does not guarantee a loss ceiling, and it does not stop the worker on a timer. A per-context limit is not an account-wide guarantee. Record the distinction so a future reader does not mistake a rejection rule for a stop-loss.

A reusable skeleton

Copy this into a text file per run and fill every field. Blank fields are findings too.

# Paper Experiment Log
run_id:              2026-10-20-nfl-spread-03
hypothesis:          YES drifts up after spread moves against favorite
strategy_version:    strategy.py @ <commit>, bangertrades <x.y.z>
market_ticker:       <exact live ticker, verbatim>
window_intended_utc: 2026-10-20 17:00 -> 20:00

data_coverage:
  ticks_start_utc:   <first tick>
  ticks_stop_utc:    <last tick>
  gaps:              <timestamps / ask absent / fallbacks>
  qty_cap_notes:     reported-volume cap, not full depth

sim_orders:
  - request:  side=YES size=$X price=0.48
    fill:     price=0.48 assumption=paper.fill.resting-assumed
    fee_model: standard Kalshi helper (rounds up to cent)

valuation:
  marked_value:      <...>   # not credited cash
  settlement_claim:  <...>

errors:              <exceptions / missing quotes / stale>
stop_evidence:       Ctrl+C; final log lines; process exited
                     (hosted: stopped record + cleanup completed)
unresolved:          <what the next run must isolate>

The payoff is boring and real. When two logs disagree, the fields tell you why: different version, different ticker, thinner data coverage, a fill assumption you forgot you relied on. That is the difference between research you can build on and a screenshot you half remember.

Sources

Keep reading

Run your first strategy free

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

Start free