Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-redis-postgres-pgpool-docker/llms.txt

Use this file to discover all available pages before exploring further.

Paper mode runs Live.background() against real market data arriving from the exchange but simulates all order execution — no real trades are placed and no exchange credentials need order-signing permissions. It shares the same entry structure as live mode, with src/main/paper.ts being the entry point, but is activated with the --paper flag instead of --live. This makes paper mode the ideal final validation step before committing a strategy to live trading: the strategy logic, persistence layer, and candle feed are all production-grade and real, while the risk is zero.

Entry Point

The full source of src/main/paper.ts is shown below. It is structurally identical to live.ts — same imports, same initialization order, same Live.background() call — differing only in the flag it checks: values.paper instead of values.live.
// src/main/paper.ts
import { getArgs } from "../helpers/getArgs";
import ioc from "../lib";
import { Live, waitForReady } from "backtest-kit";
import { ExchangeName } from "../enum/ExchangeName";
import { StrategyName } from "../enum/StrategyName";

const main = async () => {

  const { values } = getArgs();

  if (!values.entry) {
    return;
  }

  if (!values.paper) {
    return;
  }

  {
    await ioc.postgresService.waitForInit();
    await ioc.redisService.waitForInit();
  }

  await waitForReady(false);

  Live.background("TRXUSDT", {
    exchangeName: ExchangeName.CCXT,
    strategyName: StrategyName.Jan2026Strategy,
  });
};

main();
The simulated order execution is handled entirely inside Live.background() based on the backtest flag set by waitForReady(false) — paper mode passes false (live context) so candles are fetched from the exchange in real-time, but the order routing layer intercepts fills and simulates them without forwarding to the exchange.

Backtest vs Live vs Paper: Full Comparison

The table below captures every meaningful difference across all three modes. The persistence layer, strategy code, and exchange schema registration are identical in all three.
AspectBacktestLivePaper
CLI flag--backtest--live--paper
MODE env varbacktestlivepaper
Data sourcePostgreSQL candlesLive exchangeLive exchange
Order executionSimulatedRealSimulated
waitForReady paramtruefalsefalse
backtest in adapterstruefalsefalse
warmCandles callRequiredNoNo
Frame requiredYes (frameName)NoNo
Entry functionBacktest.background()Live.background()Live.background()
Exchange credentialsRead-only (OHLCV only)Full (order signing)Read-only (OHLCV only)

Running Paper Mode

# Local Node process, dockerized Postgres + Redis + PgPool
npm run start -- --entry --paper --ui ./build/index.cjs

# Full Docker Compose (all services including Node)
MODE=paper ENTRY=1 UI=1 STRATEGY_FILE=./build/index.cjs docker-compose up -d
As with live mode, STRATEGY_FILE must point to the compiled bundle that registers addStrategySchema for the strategy name referenced in Live.background(). The --ui flag loads this bundle before the signal loop begins.

Initialization Sequence

1

CLI flags checked

getArgs() returns early unless both --entry and --paper are set. The three mode flags (--backtest, --live, --paper) are independent booleans, so only one mode activates per process invocation.
2

postgresService.waitForInit()

Opens the PostgreSQL connection pool through PgBouncer/PgPool with a 15-second timeout. Paper records will be written to the same tables as live records, partitioned by the backtest=false context key value.
3

redisService.waitForInit()

Connects to Redis for the candle cache layer. Candles fetched from the live exchange during paper trading are cached in Redis to reduce API round-trips on subsequent ticks.
4

waitForReady(false)

Sets the runtime to non-backtest (live-context) mode. Paper mode passes false here — identical to live mode — because candles are sourced from the real exchange and time progresses in wall-clock order.
5

Live.background()

Starts the signal loop. On each candle close, the strategy’s getSignal is invoked with real-time price data. Any resulting positions are simulated: fills are calculated internally without placing orders on the exchange.

Persistence in Paper Mode

Paper mode uses the same adapter stack as live mode. All 16 backtest-kit adapters write to PostgreSQL identically — simulated positions, signals, notifications, and session state all persist and are queryable after the fact. Because waitForReady(false) is used, the backtest boolean in adapter context keys is false, placing paper records in the same partition as live records:
Adapter groupbacktest key valueShared with
StoragefalseLive records
NotificationfalseLive records
SessionfalseLive records
RecentfalseLive records
This means paper and live records coexist in the backtest=false partition. If you run paper and live modes against the same database simultaneously, use a different symbol or add a secondary discriminator at the query level to distinguish them.
Use paper mode to validate strategy behavior against live market conditions before switching to live mode. A paper run over several days of real market data gives you execution timing, slippage simulation, and persistence correctness that backtest mode — operating on pre-warmed historical candles — cannot fully replicate.

Next Steps

Persistence Overview

How PostgreSQL, Redis, and PgPool are wired together to back all 16 adapters across every mode.

Atomicity

How the adapter layer uses transactions and Redis pub/sub to guarantee consistent state across concurrent candle ticks.

Adapters

The full catalogue of adapter schemas — Storage, Notification, Session, Recent, and more.

Build docs developers (and LLMs) love