Package-level declarations

Types

Link copied to clipboard
class Backtest(strategies: List<Pair<String, Strategy>>, rules: List<RiskRule> = emptyList(), haltRules: List<HaltRule> = emptyList(), feed: TickFeed, candleWindow: TimeWindow? = null, initialTimestamp: Long = 0, replayEndTimestamp: Long? = null, source: MarketSource = NullMarketSource, calendar: TradingCalendar = TradingCalendar.crypto(), warmupSpec: WarmupSpec = WarmupSpec.None, symbols: List<String> = emptyList(), cadence: SampleCadence? = null, startingBalance: BigDecimal = java.math.BigDecimal.ZERO, startingBalances: Map<String, BigDecimal> = emptyMap(), dailyDdBasis: DailyDrawdownBasis = com.qkt.risk.DailyDrawdownBasis.BALANCE, totalDdBasis: DrawdownBasis = com.qkt.risk.DrawdownBasis.STATIC, strategyRiskLimits: Map<String, StrategyRiskLimits> = emptyMap(), bookCapital: BigDecimal? = null, instruments: InstrumentRegistry = com.qkt.instrument.NoopInstrumentRegistry, accountingConfig: AccountingConfig = com.qkt.accounting.AccountingConfig(), tradedSymbols: List<String> = symbols, bookRiskConfig: BookRiskConfig? = null, brokerKind: BrokerKind = BrokerKind.PAPER, executionConfig: ExecutionSimulationConfig = ExecutionSimulationConfig.forBrokerKind(brokerKind), pacerLedger: PacerLedger = com.qkt.risk.PacerLedger(), pacerCooldownDurationMs: Long? = null, pacerCooldownAfterConsecutive: Int = 1, pacerCooldownDurationMsFor: (String) -> Long?? = null, pacerCooldownAfterConsecutiveFor: (String) -> Int? = null, maxOrderQty: BigDecimal = com.qkt.risk.rules.PreTradeControls.DEFAULT_MAX_ORDER_QTY, maxOrderNotional: BigDecimal = com.qkt.risk.rules.PreTradeControls.DEFAULT_MAX_ORDER_NOTIONAL, priceCollarFrac: BigDecimal = com.qkt.risk.rules.PreTradeControls.DEFAULT_PRICE_COLLAR_FRAC, latencyEnabled: Boolean = System.getenv("QKT_LATENCY_TRACKING") == "1", gateFor: (String) -> Boolean = { true }, preCandle: (Candle) -> Unit = {}, regimeWeights: () -> Map<String, BigDecimal> = { emptyMap() }, val barFills: BarFills = BarFills.NONE, tickResolvedBars: Map<String, Sequence<Candle>>? = null, tickSlicer: (String, Long, Long) -> Sequence<Tick>? = null, engineHolder: Array<ReplayEngine?>? = null, enforceLiveBreakers: Boolean = false, runawayMaxRoundTrips: Int = com.qkt.risk.RunawayBreaker.DEFAULT_MAX_ROUND_TRIPS, runawayRoundTripWindowMs: Long = com.qkt.risk.RunawayBreaker.DEFAULT_ROUND_TRIP_WINDOW_MS, runawayMaxRejections: Int = com.qkt.risk.RunawayBreaker.DEFAULT_MAX_REJECTIONS, runawayRejectionWindowMs: Long = com.qkt.risk.RunawayBreaker.DEFAULT_REJECTION_WINDOW_MS)
Link copied to clipboard

Makes the local tick store complete for a backtest before it runs: fetch missing days (via the store's configured fetcher), validate session-hour coverage against the trading calendar, repair any incomplete day once (delete + refetch), then fail loud on a remaining hole unless allowed.

Link copied to clipboard
data class BacktestResult(val trades: List<TradeRecord>, val rejections: List<RiskRejectedEvent>, val finalPositions: Map<String, Position>, val global: PerformanceReport, val perStrategy: Map<String, PerformanceReport>, val cadence: SampleCadence, val latencyReport: LatencyRegistry.Report? = null, val halts: List<RiskEvent.Halted> = emptyList(), val conditionalAutocorr: Map<String, ConditionalAutocorr> = emptyMap(), val bookAnalytics: BookAnalytics? = null, val bookRisk: BookRiskReport? = null, val evidence: EvidenceEnvelope? = null, val accounting: AccountingSnapshot? = null, val finalPositionsByStrategy: Map<String, Map<String, Position>> = emptyMap(), val runawayBreaker: RunawayBreakerReport? = null, val inputSummary: ReplayInputReport? = null, val causality: ReplayCausalityReport? = null, val dailyEquity: List<DailyEquity> = emptyList(), val monthlyReturns: List<MonthlyReturn> = emptyList(), val windows: List<WindowReport> = emptyList(), val rolls: List<RollEntry> = emptyList(), val contractFills: List<ContractFill> = emptyList(), val settlements: List<Settlement> = emptyList(), val marginDaily: List<MarginDay> = emptyList(), val liquidations: List<Liquidation> = emptyList(), val structures: List<StructureRow> = emptyList())
Link copied to clipboard
class BarFills(synthesized: Set<String>)

Which replayed symbols fill triggered stops and limits at their own level rather than at the triggering tick: exactly the symbols whose ticks are synthesized from bars, where the only intrabar prints are the bar's extremes (see com.qkt.broker.PaperBroker). A symbol replayed from real ticks fills at the tick, as live does. A continuous futures stream (VENUE:ROOT@front) synthesized from bars covers the contracts it trades (VENUE:ROOT_240927), whose fills the venue sees by contract.

Link copied to clipboard
data class BookAnalytics(val contributionToReturn: Map<String, BigDecimal>, val returnCorrelation: List<CorrelationPair>, val riskContribution: Map<String, BigDecimal>, val drawdownContribution: Map<String, BigDecimal>)

Cross-strategy ("book") analytics for a portfolio backtest — the relationships the per-strategy reports cannot show on their own. Null on a single-strategy run.

Link copied to clipboard
class BookReturnCollector(cadence: SampleCadence, bus: EventBus, pnl: PnLProvider, strategyPnL: StrategyPnL, strategyIds: List<String>, startingBalance: BigDecimal)

Online cross-strategy return statistics for a book of strategies sharing one account.

Link copied to clipboard
sealed interface BookRiskEvent

An auditable book-risk action. Empty until the limit/de-risk/allocation phases populate it.

Link copied to clipboard
class BookRiskMonitor(cadence: SampleCadence, bus: EventBus, source: BookStateSource, strategyCount: Int, startingBalance: BigDecimal, controller: BookRiskController? = null, curveCap: Int = EquityCurveCollector.DEFAULT_CURVE_CAP)

Accumulates the book-risk measurement series for a portfolio run. Subscribes to the same sample cadence as EquityCurveCollector; on each sample it pulls a com.qkt.risk.book.BookSnapshot from the source, decimates the exposure/equity series, tracks peak gross/net exposure, and folds the book return (Δ equity / starting balance) into an online variance for annualized book volatility.

Link copied to clipboard
data class BookRiskReport(val series: List<BookRiskSample>, val bookVol: BigDecimal?, val maxGrossExposure: BigDecimal, val maxNetExposure: BigDecimal, val events: List<BookRiskEvent> = emptyList())

The book-risk dataset for a portfolio run: a decimated time series of exposure + equity, summary stats, and the event log. Null on single-strategy runs (no book). This is the "exact data we need" to see how the book behaved — surfaced in --json (summary) and the --report bundle (full csv).

Link copied to clipboard
data class BookRiskSample(val timestampMs: Long, val grossExposure: BigDecimal, val netExposure: BigDecimal, val bookEquity: BigDecimal)

One book-risk reading over time: exposure + equity at a sample instant.

Link copied to clipboard

Selects which simulated broker backs a Backtest run.

Link copied to clipboard
data class ConditionalAutocorr(val perHour: Map<Int, BigDecimal>, val perRegime: Map<Regime, BigDecimal>, val hourCounts: Map<Int, Int>, val regimeCounts: Map<Regime, Int>)

Lag-1 autocorrelation of per-bar close-to-close returns for one symbol, bucketed by the conditions under which the return occurred.

Link copied to clipboard
data class CorrelationPair(val a: String, val b: String, val correlation: BigDecimal)

Pearson correlation of two strategies' per-sample return series over the run.

Link copied to clipboard

Online worst-intraday-drawdown accumulator. For each UTC day it tracks the day-open equity and the running intraday minimum; that day's drawdown is (open − min) / open. maxDailyDrawdown is the largest such value across all days. Constant memory — no per-day or full-curve retention.

Link copied to clipboard
data class DailyEquity(val date: LocalDate, val open: BigDecimal, val high: BigDecimal, val low: BigDecimal, val close: BigDecimal)

Account equity over one UTC trading day: first, highest, lowest and last sample (#1277).

Link copied to clipboard

Folds full-resolution equity samples into one DailyEquity row per UTC day, so a consumer never has to rebuild a calendar from the thinned chart curve. Days are keyed the same way as pnl_components.csv (UTC midnight). Memory is one row per day seen, about 1,500 for six years.

Link copied to clipboard
class DecimatedCurve(cap: Int)

A bounded, even-coverage view of an equity curve for charting.

Link copied to clipboard
class DecimatedSeries<T>(cap: Int)

Bounded, even-coverage view of any time-ordered series for charting — the generic form of DecimatedCurve. Keeps at most cap samples by retaining every stride-th one and halving + doubling the stride whenever the kept set would exceed cap. The first sample is always kept and snapshot always ends at the most recent sample, so endpoints survive thinning.

Link copied to clipboard
data class DrawdownPeriod(val peakTimestamp: Long, val peakEquity: BigDecimal, val troughTimestamp: Long, val troughEquity: BigDecimal, val recoveryTimestamp: Long?, val depthPct: BigDecimal, val durationMs: Long, val ongoing: Boolean)
Link copied to clipboard
class EquityCurveCollector(cadence: SampleCadence, bus: EventBus, pnl: PnLProvider, strategyPnL: StrategyPnL, strategyIds: List<String>, curveCap: Int = DEFAULT_CURVE_CAP, candleSymbols: Set<String> = emptySet(), startingBalance: BigDecimal = BigDecimal.ZERO, windowStartMs: Long? = null)
Link copied to clipboard
data class EquityFanPoint(val tradeIndex: Int, val p5: BigDecimal, val p25: BigDecimal, val p50: BigDecimal, val p75: BigDecimal, val p95: BigDecimal)
Link copied to clipboard
class EquityMetrics(drawdownThreshold: BigDecimal = DRAWDOWN_PERIOD_THRESHOLD)

Equity-curve performance metrics computed online, one sample at a time.

Link copied to clipboard
data class EquitySample(val timestamp: Long, val equity: BigDecimal)
Link copied to clipboard
Link copied to clipboard
data class ExecutionSimulationConfig(val preset: ExecutionPreset = ExecutionPreset.PAPER_FAST, val seed: Long? = null, val latencyMs: Long = 0, val orderSpacingMs: Long = 0, val stopLatencyMs: Long = 0, val takeProfitFill: TakeProfitFill = TakeProfitFill.PRINT, val candleCloseGraceMs: Long = com.qkt.app.LiveSession.DEFAULT_CANDLE_CLOSE_GRACE_MS, val heartbeatIntervalMs: Long, val slippage: SlippageSpec = SlippageSpec.ZERO, val slippagePoints: Int = 0, val rejectEvery: Int? = null, val partialFillFraction: BigDecimal? = null, val enforceStopsLevel: Boolean = false, val positionMode: PositionAccountingMode = com.qkt.broker.PositionAccountingMode.NETTING)
Link copied to clipboard
data class FillState(val accountPositionBefore: Position?, val accountPositionAfter: Position?, val strategyPositionBefore: Position?, val strategyPositionAfter: Position?, val contractSize: BigDecimal? = null, val netAccountRealized: BigDecimal = BigDecimal.ZERO, val reducedExposure: Boolean = false, val legId: String? = null, val legAction: StrategyPositionTracker.LegAction? = null)

Position snapshot captured around a single fill.

Link copied to clipboard
class GatedChild(strategyId: String, inner: DslCompiledStrategy, hold: Boolean, gateFor: (String) -> Boolean, flattenSymbols: List<String>) : DslCompiledStrategy, PerStreamWarmable

Wraps a portfolio child strategy in backtest so its behaviour matches a live com.qkt.cli.daemon.portfolio.PortfolioSupervisor:

Link copied to clipboard

Thrown when, after fetching, the data still has holes and the caller did not allow incompleteness.

Link copied to clipboard
data class MetricsWindow(val name: String, val fromMs: Long, val toMs: Long)

A named sub-window of one run, [fromMs, toMs), whose metrics are computed from the same full-resolution equity samples and closing fills as the run's global report (#1276) — e.g. an out-of-sample tail. A window covering the whole run reproduces global.

Link copied to clipboard
data class MonteCarloSummary(val simulations: Int, val finalEquityP5: BigDecimal, val finalEquityP25: BigDecimal, val finalEquityP50: BigDecimal, val finalEquityP75: BigDecimal, val finalEquityP95: BigDecimal, val maxDrawdownP5: BigDecimal, val maxDrawdownP95: BigDecimal, val probabilityNegativeFinal: BigDecimal, val equityFanByTradeIndex: List<EquityFanPoint>)
Link copied to clipboard
data class MonthlyReturn(val month: YearMonth, val value: BigDecimal)

Equity return of one calendar month: month-end close over the previous month-end close, minus one.

Link copied to clipboard
data class PerformanceReport(val realizedTotal: BigDecimal, val unrealizedTotal: BigDecimal, val totalPnL: BigDecimal, val tradeCount: Int, val winRate: BigDecimal, val maxDrawdown: BigDecimal, val profitFactor: BigDecimal?, val avgWin: BigDecimal, val avgLoss: BigDecimal, val largestWin: BigDecimal, val largestLoss: BigDecimal, val maxConsecutiveLosses: Int, val sharpeRatio: BigDecimal?, val calmarRatio: BigDecimal?, val equityCurve: List<EquitySample>, val drawdownPeriods: List<DrawdownPeriod> = emptyList(), val monteCarlo: MonteCarloSummary? = null, val commissionPaid: BigDecimal = BigDecimal.ZERO, val swapPaid: BigDecimal = BigDecimal.ZERO, val rollCostsPaid: BigDecimal = BigDecimal.ZERO, val fundingPaid: BigDecimal = BigDecimal.ZERO, val dailyPnL: Map<LocalDate, BigDecimal> = emptyMap(), val maxDailyDrawdown: BigDecimal = BigDecimal.ZERO, val sortinoRatio: BigDecimal? = null, val turnover: BigDecimal = BigDecimal.ZERO, val annualizationFactor: BigDecimal? = null)
Link copied to clipboard
data class ProvisionStream(val broker: String, val bareSymbol: String)

A symbol the backtest needs data for. bareSymbol has no NAME: prefix (e.g. XAUUSD).

Link copied to clipboard
enum Regime : Enum<Regime>

Volatility regime of a bar, split by its absolute return against the run's median absolute return: HIGH is |return| >= median, LOW is below. A two-level proxy for "was this a busy bar or a quiet one", used to test whether short-horizon continuation concentrates in volatile bars.

Link copied to clipboard
data class ReplayCausalityReport(val approvedOrders: List<OrderEvent>, val ruleDecisions: List<RuleDecisionEvent>, val decisionOrderLinks: List<DecisionOrderLinkedEvent>, val accountedFills: List<FillAccountedEvent>)

Ordered causal evidence retained from the shared engine pipeline during replay.

Link copied to clipboard
data class ReplayInputReport(val attemptedFeedTicks: Long, val liveTicks: Long, val warmupTicks: Long, val warmupCandles: Long, val liveCandles: Long, val malformedTicks: Long, val droppedLateTicks: Long, val streamCandles: Map<String, Long> = emptyMap(), val strategyCandleEvaluations: Map<String, Long> = emptyMap())

Market inputs actually attempted, accepted, and emitted by one replay.

Link copied to clipboard
Link copied to clipboard

Computes ConditionalAutocorr online from the closed-bar stream, one bar at a time.

Link copied to clipboard
data class RunawayBreakerReport(val enforceLiveBreakers: Boolean, val maxRoundTrips: Int, val roundTripWindowMs: Long, val maxRejections: Int, val rejectionWindowMs: Long, val trips: List<RunawayBreakerTrip>)

Runaway-breaker thresholds and trip evidence attached to a replay result.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

The run's option structures, one row each in the order they first appeared, from their books' events.

Link copied to clipboard
data class StructureRow(val strategyId: String, val structureId: String, val alias: String, val legs: List<StructureLegPosition>, val openedAt: Long? = null, val credit: BigDecimal? = null, val closedAt: Long? = null, val outcome: StructureOutcome? = null, val realized: BigDecimal? = null)

One option structure of a run: legs with their entries; openedAt and credit once every leg filled (null for one unwound before it opened whole); closedAt, outcome and realized (premium P&L before fees) once it left its book (null for one still live when the run ended).

Link copied to clipboard
data class TradeRecord(val trade: Trade, val realized: BigDecimal, val strategyId: String, val orderType: String? = null, val riskUsd: BigDecimal? = null, val stopLossPrice: BigDecimal? = null, val takeProfitPrice: BigDecimal? = null, val nativeRealized: BigDecimal? = null, val nativeCurrency: String? = null, val accountRealized: BigDecimal? = null, val accountCurrency: String? = null, val fxRate: BigDecimal? = null, val fxRateTimestamp: Long? = null, val fxSource: String? = null, val accountPositionBefore: Position? = null, val accountPositionAfter: Position? = null, val strategyPositionBefore: Position? = null, val strategyPositionAfter: Position? = null, val contractSize: BigDecimal? = null, val reducedExposure: Boolean = true, val legId: String? = null, val legAction: StrategyPositionTracker.LegAction? = null)
Link copied to clipboard
data class WindowReport(val window: MetricsWindow, val samples: Int, val closingFills: Int, val equityStart: BigDecimal, val equityEnd: BigDecimal, val report: PerformanceReport)

One window's finished report. report carries the same fields as the run's global (PerformanceReport); its totalPnL is the equity change between the window's first and last samples (equityStart to equityEnd) and its trade statistics count the closing fills stamped inside the window.

Link copied to clipboard
class WindowSamples(val window: MetricsWindow)

The online metrics of one MetricsWindow, fed only the samples inside it.

Properties

Link copied to clipboard

Functions

Link copied to clipboard

Month-over-month equity returns from a daily series. The first month is measured from the first day's open, every later month from the previous month's last close, so compounding every return gives exactly finalClose / firstOpen - 1 (the run's total return). Empty when daily is empty.

Link copied to clipboard

What the run's evidence.execution records about this execution model.