Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/theonetrade/backtest-kit/llms.txt

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

addSizingSchema registers a named position sizing calculator that computes how many units to buy or sell for a given trade. Backtest Kit ships three sizing methods out of the box—fixed percentage of account balance, Kelly Criterion, and ATR-based—each with optional position constraints. Once registered, a sizing schema is invoked via PositionSize.fixedPercentage, PositionSize.kellyCriterion, or PositionSize.atrBased inside a strategy’s getSignal function to produce a cost value before returning the signal.

Function Signature

addSizingSchema(sizingSchema: ISizingSchema): void
ISizingSchema is a discriminated union selected by the method field:
  • ISizingSchemaFixedPercentage (method: "fixed-percentage")
  • ISizingSchemaKelly (method: "kelly-criterion")
  • ISizingSchemaATR (method: "atr-based")

Common Parameters (all methods)

sizingName
string (SizingName)
required
A unique identifier for this sizing configuration. Used as the routing key in PositionSize.* calls.
method
"fixed-percentage" | "kelly-criterion" | "atr-based"
required
Selects the sizing algorithm. Must match the corresponding interface (ISizingSchemaFixedPercentage, etc.).
maxPositionPercentage
number
Optional cap expressed as a percentage of account balance (0–100). The calculated size is clamped so it never exceeds this fraction of the account.
minPositionSize
number
Optional floor for the calculated position size (absolute value in quote currency).
maxPositionSize
number
Optional ceiling for the calculated position size (absolute value in quote currency).
callbacks
Partial<ISizingCallbacks>
Optional lifecycle callbacks:
  • onCalculate(quantity, params) — called after every size calculation with the result and input parameters. Useful for logging or auditing.
note
string
Optional developer note.

Method-Specific Parameters

method: "fixed-percentage"

riskPercentage
number
required
Percentage of account balance at risk per trade (0–100). The position size is derived from the distance between entry and stop-loss so that the maximum loss equals riskPercentage of the account.

method: "kelly-criterion"

kellyMultiplier
number
default:"0.25"
Fractional Kelly multiplier (0–1). 0.25 = quarter Kelly, which reduces variance compared to full Kelly while still achieving long-run growth. Lower values are more conservative.

method: "atr-based"

riskPercentage
number
required
Percentage of account balance at risk per trade (0–100).
atrMultiplier
number
default:"2"
Multiplier applied to the ATR value to set the stop distance. A larger multiplier gives more room for noise.

Default Sizing Behavior

If a strategy does not call PositionSize.* inside getSignal, the signal’s cost field defaults to CC_POSITION_ENTRY_COST (default: $100 per DCA entry). This flat-dollar default is suitable for backtesting without capital management, but production strategies should always compute size explicitly.

Example

import { addSizingSchema, PositionSize, addStrategySchema, getCandles } from 'backtest-kit';

// Fixed-percentage: risk 1% of account per trade
addSizingSchema({
  sizingName: 'conservative',
  method: 'fixed-percentage',
  riskPercentage: 1,
  maxPositionPercentage: 10,   // never exceed 10% of account in one position
});

// Kelly Criterion with quarter multiplier
addSizingSchema({
  sizingName: 'kelly-q',
  method: 'kelly-criterion',
  kellyMultiplier: 0.25,
  maxPositionPercentage: 20,
});

// ATR-based with 2× ATR stop distance
addSizingSchema({
  sizingName: 'atr-dynamic',
  method: 'atr-based',
  riskPercentage: 2,
  atrMultiplier: 2,
  callbacks: {
    onCalculate: (quantity, params) => {
      console.log(`Sized ${params.symbol}: $${quantity.toFixed(2)}`);
    },
  },
});

// Use sizing inside a strategy
addStrategySchema({
  strategyName: 'sized-strategy',
  interval: '5m',
  getSignal: async (symbol, when, currentPrice) => {
    const accountBalance = 10_000; // fetch from your portfolio API
    const priceStopLoss = currentPrice * 0.985;

    const cost = await PositionSize.fixedPercentage(
      symbol,
      accountBalance,
      currentPrice,
      priceStopLoss,
      { sizingName: 'conservative' },
    );

    return {
      position: 'long',
      priceTakeProfit: currentPrice * 1.03,
      priceStopLoss,
      cost,   // ← dynamically calculated position size
    };
  },
});

Build docs developers (and LLMs) love