diff --git a/assets/hierarchy.js b/assets/hierarchy.js index 85bba4612d57d0993cb303da53d28cfca273d32a..c755044c904b8177be79674fc135875af700661c 100644 --- a/assets/hierarchy.js +++ b/assets/hierarchy.js @@ -1 +1 @@ -window.hierarchyData = "eJylmV1v2zYYhf+LrtlO/BAl+q51MSBYOhjOsF4MveAkxhEsS4VId8uK/PeBouKQMmWR6o3txDo6D/m+FJmTH0nfdUomm79gxjIAc0oBLAoCIEshgAzqT4gCyAgGkGUIQEYZgIwRgNIUA5RCClCK9AvOAUqJ/pQVAKVU/5gzgFCKAML6E2EpQFk6vDBAcpx9BUkvHhtRqrprZbL5kUBEcv3e8pNINsnHvjuK/iOXIgHJsW6rZANRAZJz3ySbpGy4lEL+op6/Cfn+7dr3T+rUJMB8n2wSJat3WvzO/OIFJHq8ls2d0V48UEZfPepWif6Rlxeb8dpZj4tAf/lUN1UvWj3DiORftXOO7QHe3XeHMNv77hDgOThQOnE4hI7NXBs9thybsRUFsZ13ope1VE75btpbglgGjCkZGFgKfQy94EfxXbR3rVS8LSOBpupoOpKmhg76ZmjL26oRq9BcaTwXwoYLUQ/XnVZ9580qsqk4no1kho1gD9t9d1iFZeniiajpc5YhD9FnweW5X1fGiTaerBj7izIv2anrn1eC2dJorixFhov5+v73TtWPdcn1438Vne8G8Yx46DO9o3kYd7xX9colMNHGk2WpIYO+1bkXpWjVKjBXGs+VY8PlfWrsa3lcR2UJ45lYbpjc/XW89UP5JKrzymfsVBzNRuHIRnzz9SCkXLsAJtp4MkwNWVb4yOpDu7L1XWk8V1YYLuqtpuJqZSltZTxVPtYx9z1lH1TX88NaLkcbTzZ2P4TOuXZ3/rupS1OLffdPIJIrimVBCJqeQqmzS+rVvX0S5fFDf5BhJI4kniOHhsN9euqbRs6IIwk7hWv3qeufvKmrYa/a8eem41W4+5U0lKJwavD6JKvMaLa618KnYU4dyIIRucGylmJVhxbDqUT/WeoQDTf8pLpAkNfLo/1xUQCExyWLi+Ia4vXwHAljyUKLwvJr9/BarC4BhBnQHTFMAckmU/Bf3R52vOcn+eGPfSiKIwocPqFszvnX+l9R7USvT0r8EPg4v3GDUKJpT77d8DfRNM/xHIMs1J2l1+56xZ14ZCUuoujWIOPen6WzLD9RG+8N4hkpGxk91TIW0dWyZPE8ueGhhbPrfOHNUfR7Ic+NCtxzHUlY1+jsxXL1xT6zqV1I5HOJ7XSM4jGazXYWXYNzHQsB4WuEmQBnyT8wvLHMSXZtPpvSLNkHJzQWgHMevxHFLHmHxDCWbeGp+1zesmQdmrW82WfOSfZ2qLLsHhSoWObYU/ObyckSQlRqYoFkniLMxSNLDKHRiGWfexbeTAay5B6Yf1jmzNP33qBj0Tok5HgzptBjPJtmLJkHJxkWAKYegJnIYtE/MK6w7J2j4e1cYtE9LJOwzHPf5HvDh0XvoODBsvY13FzCsGweli5c7PU/5yx7cybYdqdvjVBi27Wq56UKOk/4pdHnG1pAQHI6HAz1+xWcnt9aqrqUn7tKNBFsE2XIkefl5X+CUNVF" \ No newline at end of file +window.hierarchyData = "eJylmVFv2zYUhf+LntlOvCIl0W+tiwHB0sFwhvVh6AMnMY5gWSpEultW5L8PNBWHtCmLVF/sxNbh+cRLUjcnP5Kh75VMVn/hnGCESwwIsyxFmJECYZbrnwr9WckQZqxEkGKKICWpfmEI0hwQpIV+KTMEKQMEOCUIMM4QYKAIgJQIiP6JZiUCqn+ltECkKLOvKBnEYysq1fSdTFY/EgwF0+8dP4hklXwc+r0YPnIpEpTsm65OVhhKlByHNlklVculFPIX9fxNyPdv175/Uoc2Qeb7ZJUoWb/T4nfmgxeU6Pu1bO6M9uwBNH/1aDolhkdenW3Gayc9zgL95VPT1oPo9AxDwb5q56LMbOf7fhdme9/vAjy1Q4nhwmEXem/m2uh706XUzixLbeeNGGQjlVO+m/aWIJYhIxgMAyl8DIPge/FddHedVLyrIoEu1fF0pDR0uW+G1ryrW7EIzZXGcxXYcBXg4brTqu+8XUR2KY5nY+OqKpmH7b7fLcKydNFEFFNDxEoP0WfB5XFYVsYLbTwZnNaXPp+9ZId+eF4IZkvjuWhquIhv3f/eq+axqbg+/hfR+QaIZzSnl36ieRg3fFDNwi1woY0nY2NVc9/u3IpKdGoRmCuN5soBGy7vqbFt5H4ZlSWMZyLUMLnP13Hoh+pJ1MeFZ+ylOJ4tH9mYb74ehJRLN8CFNp6sJCcynBIfWbPrFi59VxrNVaS54cLeaiquFpbSVsZTgakjBt8p+6D6ge+WcjnaeLJx9ePc6Ws3x7/bpjK12Pb/BCK5olgWgPzUienO32bRu3v9JKr9h2Enw0gcSTRHhgvD4Z6eetDIGXEkYV24dr90/ZO3TX16Vm34c9vzOtz9ShpKAU4NXk+y2tzNWq+18GmYUoeyFOkNlqUUS1ZoNnZLxN3HZsBPqg8Eeb082p9kFAEZtyzJPBCvzXMkjCULLAohHvfwWiwuAc4x0iviNAU0zV2I/5put+EDP8gPf2xDURxR4O1Td5fag/za/CvqjRh0p8R3gcf5jQFCiWCS6DfRts/xHCdZqHtWXrvrHXfgkZU4i6KXBh2f/ZRMsvxEbbwDxDOOzxZKPdUyFtHVsmTxPGB4CnD+hvnC270YtkIeWxX4zHUkYatGZy+Wqy/2mUztQiKfc2ynYxSP0WS2M+sanOtYCAW+RpgIcOb8A8Mby5xl1+aTKc2cfXBC8wZAnXzhRhQz5x0Sw1i24Kn7VN4yZx2atVj2NPXZe0OVefegQMUyLz01v5mczCFEpSYWCPMUYSoemWMIjUbe7HPwbLyJDGTOPTD/sMyJZ917g45Z65CQwzLOPcaTacaceXCSYQGUxAMwEVnM+gfGFW/2hdMa3s4lZt3DMgnLHHyT7w0fZr2DggfL2rfgphKGefOwdOFsT9z/UpmeYN0fvrVCiXXfqYFXKqif8Euj+5sCGCIlPjWG+v0KTs9vI1VTyc99LdoItgtlSMvz8vI/AmXVAw==" \ No newline at end of file diff --git a/assets/highlight.css b/assets/highlight.css index 22fc99554d820d4f8d18003b23a9242408a57c70..75021fab8cdc038b41a6c15781ff764c39204b15 100644 --- a/assets/highlight.css +++ b/assets/highlight.css @@ -39,6 +39,8 @@ --dark-hl-18: #CE9178; --light-hl-19: #000000; --dark-hl-19: #D7BA7D; + --light-hl-20: #EE0000; + --dark-hl-20: #DCDCAA; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -64,6 +66,7 @@ --hl-17: var(--light-hl-17); --hl-18: var(--light-hl-18); --hl-19: var(--light-hl-19); + --hl-20: var(--light-hl-20); --code-background: var(--light-code-background); } } @@ -88,6 +91,7 @@ --hl-17: var(--dark-hl-17); --hl-18: var(--dark-hl-18); --hl-19: var(--dark-hl-19); + --hl-20: var(--dark-hl-20); --code-background: var(--dark-code-background); } } @@ -112,6 +116,7 @@ --hl-17: var(--light-hl-17); --hl-18: var(--light-hl-18); --hl-19: var(--light-hl-19); + --hl-20: var(--light-hl-20); --code-background: var(--light-code-background); } @@ -136,6 +141,7 @@ --hl-17: var(--dark-hl-17); --hl-18: var(--dark-hl-18); --hl-19: var(--dark-hl-19); + --hl-20: var(--dark-hl-20); --code-background: var(--dark-code-background); } @@ -159,4 +165,5 @@ .hl-17 { color: var(--hl-17); } .hl-18 { color: var(--hl-18); } .hl-19 { color: var(--hl-19); } +.hl-20 { color: var(--hl-20); } pre, code { background: var(--code-background); } diff --git a/assets/navigation.js b/assets/navigation.js index e5bb5a7e613085ab09ff98fef57dea1463b47a37..29d2e3de5169440ae82beda21914479c5661e94a 100644 --- a/assets/navigation.js +++ b/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "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" \ No newline at end of file +window.navigationData = "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" \ No newline at end of file diff --git a/assets/search.js b/assets/search.js index fd35b05b821170ea771abaddd2e5d6414dc6f518..3d5d32b7cf217cfabfa81a4b693781bdef365ba4 100644 --- a/assets/search.js +++ b/assets/search.js @@ -1 +1 @@ -window.searchData = "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"; \ No newline at end of file +window.searchData = "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"; \ No newline at end of file diff --git a/classes/types.ActionBase.html b/classes/types.ActionBase.html index 2d9b1d8be37f2dda8cbe2c7ac539c8d4a0c964e4..3e18779aec319ed7d3e19e75d7309ed7a8efa499 100644 --- a/classes/types.ActionBase.html +++ b/classes/types.ActionBase.html @@ -40,7 +40,7 @@ Extend this class to implement custom action handlers for:

// Redux state management example
class ReduxAction extends ActionBase {
constructor(
strategyName: StrategyName,
frameName: FrameName,
actionName: ActionName,
private store: Store
) {
super(strategyName, frameName, actionName);
}

signal(event: IStrategyTickResult) {
this.store.dispatch({
type: 'STRATEGY_SIGNAL',
payload: { event, strategyName: this.strategyName, frameName: this.frameName }
});
}

partialProfit(event: PartialProfitContract) {
this.store.dispatch({
type: 'PARTIAL_PROFIT',
payload: { event, strategyName: this.strategyName }
});
}
}
-

Implements

Constructors

Implements

Constructors

Properties

actionName backtest frameName @@ -62,7 +62,7 @@ Extend this class to implement custom action handlers for:

  • frameName: string

    Timeframe identifier this action is attached to

  • actionName: string

    Action identifier

  • backtest: boolean

    If running in backtest

    -
  • Returns ActionBase

    Properties

    actionName: string
    backtest: boolean
    frameName: string
    strategyName: string

    Methods

    • Handles breakeven events when stop-loss is moved to entry price.

      +

    Returns ActionBase

    Properties

    actionName: string
    backtest: boolean
    frameName: string
    strategyName: string

    Methods

    • Handles breakeven events when stop-loss is moved to entry price.

      Called once per signal when price moves far enough to cover fees and slippage. Breakeven threshold: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2 + CC_BREAKEVEN_THRESHOLD

      Triggered by: ActionCoreService.breakevenAvailable() via BreakevenConnectionService @@ -73,7 +73,7 @@ Frequency: Once per signal when threshold reached

    • Optionalsource: string

    Returns void | Promise<void>

    async breakevenAvailable(event: BreakevenContract) {
    await this.telegram.send(
    `[${event.strategyName}] Breakeven reached! ` +
    `Signal: ${event.data.side} @ ${event.currentPrice}`
    );
    }
    -
    • Cleans up resources and subscriptions when action handler is disposed.

      +
    • Cleans up resources and subscriptions when action handler is disposed.

      Called once when strategy execution ends. Guaranteed to run exactly once via singleshot pattern.

      Override to:

      @@ -88,7 +88,7 @@ Guaranteed to run exactly once via singleshot pattern.

      Parameters

      • Optionalsource: string

      Returns void | Promise<void>

      async dispose() {
      super.dispose(); // Keep parent logging
      await this.db?.disconnect();
      await this.telegram?.close();
      await this.cache?.quit();
      console.log('Action disposed successfully');
      }
      -
    • Initializes the action handler.

      +
    • Initializes the action handler.

      Called once after construction. Override to perform async initialization:

      • Establish database connections
      • @@ -100,7 +100,7 @@ Guaranteed to run exactly once via singleshot pattern.

      Parameters

      • Optionalsource: string

      Returns void | Promise<void>

      async init() {
      super.init(); // Keep parent logging
      this.db = await connectToDatabase();
      this.telegram = new TelegramBot(process.env.TOKEN);
      }
      -
    • Handles partial loss level events (-10%, -20%, -30%, etc).

      +
    • Handles partial loss level events (-10%, -20%, -30%, etc).

      Called once per loss level per signal (deduplicated). Use to track loss milestones and implement risk management actions.

      Triggered by: ActionCoreService.partialLossAvailable() via PartialConnectionService @@ -111,7 +111,7 @@ Frequency: Once per loss level per signal

    • Optionalsource: string

    Returns void | Promise<void>

    async partialLossAvailable(event: PartialLossContract) {
    await this.telegram.send(
    `[${event.strategyName}] Loss ${event.level}% reached! ` +
    `Current price: ${event.currentPrice}`
    );
    // Optionally adjust risk management
    }
    -
    • Handles partial profit level events (10%, 20%, 30%, etc).

      +
    • Handles partial profit level events (10%, 20%, 30%, etc).

      Called once per profit level per signal (deduplicated). Use to track profit milestones and adjust position management.

      Triggered by: ActionCoreService.partialProfitAvailable() via PartialConnectionService @@ -122,7 +122,7 @@ Frequency: Once per profit level per signal

    • Optionalsource: string

    Returns void | Promise<void>

    async partialProfitAvailable(event: PartialProfitContract) {
    await this.telegram.send(
    `[${event.strategyName}] Profit ${event.level}% reached! ` +
    `Current price: ${event.currentPrice}`
    );
    // Optionally tighten stop-loss or take partial profit
    }
    -
    • Handles active ping events during active pending signal monitoring.

      +
    • Handles active ping events during active pending signal monitoring.

      Called every minute while a pending signal is active (position open). Use to monitor active positions and track lifecycle.

      Triggered by: ActionCoreService.pingActive() via StrategyConnectionService @@ -133,7 +133,7 @@ Frequency: Every minute while pending signal is active

    • Optionalsource: string

    Returns void | Promise<void>

    pingActive(event: ActivePingContract) {
    const holdTime = getTimestamp() - event.data.pendingAt;
    const holdMinutes = Math.floor(holdTime / 60000);
    console.log(`Active signal holding ${holdMinutes} minutes`);
    }
    -
    • Handles idle ping events when no signal is active.

      +
    • Handles idle ping events when no signal is active.

      Called every tick while no signal is pending or scheduled. Use to monitor idle strategy state and implement entry condition logic.

      Triggered by: ActionCoreService.pingIdle() via StrategyConnectionService @@ -141,7 +141,7 @@ Source: idlePingSubject.next() in CREATE_COMMIT_IDLE_PING_FN callback Frequency: Every tick while no signal is pending or scheduled

      Default implementation: Logs idle ping event.

      Parameters

      • event: IdlePingContract

        Idle ping data with symbol, strategy info, current price, timestamp

        -
      • Optionalsource: string

      Returns void | Promise<void>

    • Handles scheduled ping events during scheduled signal monitoring.

      +
    • Optionalsource: string

    Returns void | Promise<void>

    • Handles scheduled ping events during scheduled signal monitoring.

      Called every minute while a scheduled signal is waiting for activation. Use to monitor pending signals and track wait time.

      Triggered by: ActionCoreService.pingScheduled() via StrategyConnectionService @@ -152,7 +152,7 @@ Frequency: Every minute while scheduled signal is waiting

    • Optionalsource: string

    Returns void | Promise<void>

    pingScheduled(event: SchedulePingContract) {
    const waitTime = getTimestamp() - event.data.timestampScheduled;
    const waitMinutes = Math.floor(waitTime / 60000);
    console.log(`Scheduled signal waiting ${waitMinutes} minutes`);
    }
    -
    • Handles risk rejection events when signals fail risk validation.

      +
    • Handles risk rejection events when signals fail risk validation.

      Called only when signal is rejected (not emitted for allowed signals). Use to track rejected signals and analyze risk management effectiveness.

      Triggered by: ActionCoreService.riskRejection() via RiskConnectionService @@ -163,7 +163,7 @@ Frequency: Only when signal fails risk validation

    • Optionalsource: string

    Returns void | Promise<void>

    async riskRejection(event: RiskContract) {
    await this.telegram.send(
    `[${event.strategyName}] Signal rejected!\n` +
    `Reason: ${event.rejectionNote}\n` +
    `Active positions: ${event.activePositionCount}`
    );
    this.metrics.recordRejection(event.rejectionId);
    }
    -
    • Handles signal events from all modes (live + backtest).

      +
    • Handles signal events from all modes (live + backtest).

      Called every tick/candle when strategy is evaluated. Receives all signal states: idle, scheduled, opened, active, closed, cancelled.

      Triggered by: ActionCoreService.signal() via StrategyConnectionService @@ -174,7 +174,7 @@ Frequency: Every tick/candle

    • Optionalsource: string

    Returns void | Promise<void>

    signal(event: IStrategyTickResult) {
    if (event.action === 'opened') {
    console.log(`Signal opened: ${event.signal.side} at ${event.signal.priceOpen}`);
    }
    if (event.action === 'closed') {
    console.log(`Signal closed: PNL ${event.signal.revenue}%`);
    }
    }
    -
    • Handles signal events from backtest only.

      +
    • Handles signal events from backtest only.

      Called every candle in backtest mode. Use for actions specific to backtesting (e.g., collecting test metrics).

      Triggered by: ActionCoreService.signalBacktest() via StrategyConnectionService @@ -185,7 +185,7 @@ Frequency: Every candle in backtest mode

    • Optionalsource: string

    Returns void | Promise<void>

    signalBacktest(event: IStrategyTickResult) {
    if (event.action === 'closed') {
    this.backtestMetrics.recordTrade(event.signal);
    }
    }
    -
    • Handles signal events from live trading only.

      +
    • Handles signal events from live trading only.

      Called every tick in live mode. Use for actions that should only run in production (e.g., sending real notifications).

      Triggered by: ActionCoreService.signalLive() via StrategyConnectionService @@ -196,7 +196,7 @@ Frequency: Every tick in live mode

    • Optionalsource: string

    Returns void | Promise<void>

    async signalLive(event: IStrategyTickResult) {
    if (event.action === 'opened') {
    await this.telegram.send('Real trade opened!');
    await this.placeRealOrder(event.signal);
    }
    }
    -
    +

    Utilities for calculating take profit and stop loss price levels. Automatically inverts direction based on position type (long/short).

    -

    Constructors

    Constructors

    Properties

    Constructors

    Properties

    bracket: (
        dto: {
            currentPrice: number;
            percentStopLoss: number;
            percentTakeProfit: number;
            position: "long" | "short";
        },
    ) => {
        position: "long"
        | "short";
        priceStopLoss: number;
        priceTakeProfit: number;
    }

    Calculates levels for a bracket order with custom TP and SL.

    @@ -9,12 +9,12 @@ Automatically inverts direction based on position type (long/short).

  • percentTakeProfit: number

    take profit percentage from 0 to 100

  • position: "long" | "short"

    position type: "long" or "short"

  • Returns { position: "long" | "short"; priceStopLoss: number; priceTakeProfit: number }

    priceTakeProfit and priceStopLoss in fiat

    -
    moonbag: (
        dto: {
            currentPrice: number;
            percentStopLoss: number;
            position: "long" | "short";
        },
    ) => {
        position: "long"
        | "short";
        priceStopLoss: number;
        priceTakeProfit: number;
    }

    Calculates levels for the "moonbag" strategy — fixed TP at 50% from the current price.

    +
    moonbag: (
        dto: {
            currentPrice: number;
            percentStopLoss: number;
            position: "long" | "short";
        },
    ) => {
        position: "long"
        | "short";
        priceStopLoss: number;
        priceTakeProfit: number;
    }

    Calculates levels for the "moonbag" strategy — fixed TP at 50% from the current price.

    Type declaration

      • (
            dto: {
                currentPrice: number;
                percentStopLoss: number;
                position: "long" | "short";
            },
        ): {
            position: "long"
            | "short";
            priceStopLoss: number;
            priceTakeProfit: number;
        }
      • Parameters

        • dto: { currentPrice: number; percentStopLoss: number; position: "long" | "short" }
          • currentPrice: number

            current asset price

          • percentStopLoss: number

            stop loss percentage from 0 to 100

          • position: "long" | "short"

            position type: "long" or "short"

        Returns { position: "long" | "short"; priceStopLoss: number; priceTakeProfit: number }

        priceTakeProfit and priceStopLoss in fiat

        -
    +

    💸 Escaping zero expectation: from a fixed-sum game to a growing-sum game

    +

    The source code discussed in the article is published in this repository.

    +
    +

    cover_zero_expectation_escape

    +

    Any trading strategy, on an infinite time horizon, tends toward zero expected value per trade: you earned nothing, you paid the exchange a commission. One might assume this is due to information leakage, that the strategy is being used by other market participants and they take the liquidity. But the reason is different: it is the fundamental law of large numbers. Market volume is forecastable, which means it is a finite sum. In a game with a finite sum the capital on the market is constant and only migrates between participants: your earnings are someone's losses.

    +

    luxalgo_plateau

    +

    Look at the chart: portfolio return growth first increases, then runs into a plateau without any pronounced upward or downward movement. The nearest analogy: an object thrown upward, when acceleration and gravity balance out, stops at a point and then falls back down.

    +

    Any effective quant strategy is an exploit of a market inefficiency. As soon as everyone uses the exploit — the inefficiency disappears, because what created it in the first place was precisely the fact that nobody was arbitraging it. The market comes into equilibrium. And equilibrium for a participant means a simple thing: the mathematical expectation of a trade becomes zero minus exchange commission. Not "a small profit", but a strictly negative number.

    +

    There is only one way out of this trap: look at what brings money into the system from the outside, rather than redistributing what is already there. One might think this is the accounting reports of companies or funds, but no: the publication of accounting data does not guarantee deterministic behavior of market participants. Mathematically, the guarantee of a growing-sum game is a direct recommendation to the public, if its size tends to infinity.

    +

    Earlier I covered the stop hunting pattern for liquidity harvesting: market participants get a post with panic sentiment published to them to trigger mass selling, and as a consequence the asset can be bought up all at once for cheaper. But you can also make money on euphoria.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MetricValue
    Total trades22
    Wins / Losses15 / 7
    Winrate68%
    Mean trade PNL+2.374%
    Std dev per trade7.676%
    Sharpe Ratio (per-trade)+0.302
    +

    A Telegram channel publishes signals, they are successful in 68% of cases. The average retail investor will not look any further. And this is a trap: risk management does not insure against the black swan scenario at all.

    +

    Risks:

    +
      +
    1. +

      High volatility relative to average profit

      +

      The average trade is +2.37%, but the standard deviation is ±7.86%. One or two strong losses easily eat up the profit of ten small wins, while the winrate still looks "pretty".

      +
    2. +
    3. +

      Low Sharpe = weak risk compensation

      +

      Sharpe 0.3 indicates that the profit is not large enough compared to the risk being taken. Good trading aims for Sharpe > 1.0.

      +
    4. +
    +

    This is a different pattern of crowd liquidity usage: pump and dump. Let us verify the hypothesis by picking only those signals where the asset's price had already been rising over the previous N hours.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MetricValue
    Total trades11
    Wins / Losses11 / 0
    Winrate100%
    Mean trade PNL+6.972%
    Std dev per trade8.642%
    Sharpe Ratio (per-trade)+0.807
    +

    What improved:

    +
      +
    1. +

      Sharpe Ratio grew 2.67x (0.302 → 0.807)

      +

      Profit now compensates the assumed risk much better.

      +
    2. +
    3. +

      The average trade became almost 3x more profitable (+2.37% → +6.97%)

      +

      Portfolio drawdowns went away: fewer losing trades.

      +
    4. +
    +

    The price growth over the last N hours is an empirical criterion. I knew where to look in advance, but I did not perform an analysis of the matrix of recommendation posts. If you take the top 100 channels, using publication time and recommendation direction you can identify a single author behind several anonymous accounts. Further, with the link to a single author, you can find out how many more channels he is potentially capable of using to continue the pump.

    +

    Using a self enforcement runtime, a parser and a high-performance backtest one can update the empirical entry criteria automatically. The channel parser extracts the direction, entry zone, targets and stop from the text with simple regex rules:

    +
    const SIGNAL_FORMAT: ParseFormat<SignalFields> = {
    symbol: {
    pattern: /#([A-Z0-9]+)\/USDT/,
    group: 1,
    },
    direction: {
    pattern: /(ШОРТ|ЛОНГ)/i,
    transform: (raw) => (raw.toUpperCase() === "ШОРТ" ? "short" : "long"),
    },
    entry: {
    pattern: /зоне\s+\$?([\d.,]+)\s*[-–—]\s*(?:\$?[\d.,]+\s*[-–—]\s*)?\$?([\d.,]+)(?=\s)/i,
    transform: (_, m) => ({ from: num(m[1]), to: num(m[2]) }),
    },
    targets: {
    pattern: /Закрыть(?:\s+ордер)?\s+по(?:\s+цене)?\s+\$?([\d.,]+)/gi,
    transform: (_, m) => num(m[1]),
    multi: true,
    },
    stoploss: {
    pattern: /СТОП-?ЛОСС:\s*\$?([\d.,]+)/i,
    transform: (_, m) => num(m[1]),
    },
    }; +
    + +

    A high-performance backtest computes metrics on pre-publication data:

    +
    const PRE_CANDLES_LIMIT = 1440; // 24h of 1m candles for baseline

    // the getCandles(.., 1440) window covers exactly the 24h BEFORE the signal publication
    const preCandles = await getCandles(symbol, "1m", PRE_CANDLES_LIMIT);

    // momentum24h — total price change over the 24h before publication.
    // Positive = a pump is already in progress; negative = the market is falling.
    const momentum24hPct =
    ((preCandles[preCandles.length - 1].close - preCandles[0].open) /
    preCandles[0].open) * 100;

    Logger.log("pre-publication data", { momentum24hPct }) +
    + +

    The AI agent programs the filters, changing them as code on each update:

    +
    const SHORT_MIN_AVG_RANGE_PCT = 0.07;
    const LONG_MIN_MOMENTUM_24H_PCT = -1;

    // Filter 1: SHORT on a "sleeping" asset (avgRange < 0.07% over the day, like TRX) —
    // thin liquidity, an ideal target for a stop-hunt. This is the case of liquidity
    // harvesting: the signal must not be followed.
    if (signal.direction === "short" && avgRangePct < SHORT_MIN_AVG_RANGE_PCT) {
    return null;
    }

    // Filter 2: LONG when the price has fallen more than 1% over the day — "catching knives".
    // There is no capital inflow, there is a decline; subscribers are being led against the trend.
    if (signal.direction === "long" && momentum24hPct < LONG_MIN_MOMENTUM_24H_PCT) {
    return null;
    } +
    + +

    Filter 1 catches the scam mode of liquidity harvesting (zero inflow, stop manipulation) and says "do not enter". Filter 2 catches the absence of fundamental inflow (the market is falling, there is no pump) and also says "do not enter". What remains is exactly what the whole thing was started for: signals under which there is real capital inflow.

    +

    A Telegram pump is not a market bug that will be arbitraged away and disappear. It is crowd behavior that reproduces every time the author has an audience. As long as there are subscribers — there is inflow. And that means there is a fundamental factor to which the arithmetic of equilibrium does not apply: it is a game with a growing sum.

    +
    +

    Thank you for your attention

    +
    + + + + + + + + + diff --git a/documents/data_test-guidelines.html b/documents/data_test-guidelines.html new file mode 100644 index 0000000000000000000000000000000000000000..314be8cee002ae7219d5a4a41b83657d5cd2ea00 --- /dev/null +++ b/documents/data_test-guidelines.html @@ -0,0 +1,76 @@ +data/test-guidelines | backtest-kit

    Test Guidelines

      +
    • src/helpers/getEffectivePriceOpen.ts — cost-basis replay algorithm (DO NOT MODIFY)
    • +
    • src/helpers/toProfitLossDto.ts — weighted PNL with partial close replay (DO NOT MODIFY)
    • +
    • test/spec/dca.test.mjs — 35 unit tests for DCA+partial logic
    • +
    • test/e2e/dca.test.mjs — 9 e2e tests: partial profit/loss interleaved with DCA
    • +
    • test/migration/migrate7.test.mjs — 2 migration tests: trailing stop breakeven, partialLoss
    • +
    • test/e2e/average.test.mjs — reference pattern for e2e backtest tests
    • +
    • test/README.md — comprehensive test writing guide (read before writing e2e tests)
    • +
    +

    Running costBasis through all partials sequentially:

    +
    costBasis = 0
    for each partial[i]:
    newEntries = entryCountAtClose[i] - entryCountAtClose[i-1] (0 for i=0)
    costBasis += newEntries * 100
    dollarValue = (percent[i] / 100) * costBasiscorrect running basis
    costBasis *= (1 - percent[i] / 100) ← reduce after each close
    weight[i] = dollarValue[i] / totalInvested +
    + +
      +
    • snap[0] = hm(entries[0..cnt[0]]) when no prior partials
    • +
    • snap[i≥1] = must use getEff(entries[0..cnt[i]], partials[0..i-1]) — NOT plain harmonic mean +
        +
      • Formula: (remainingCostBasis + newDCA*100) / (remainingCostBasis/snap[i-1] + Σ100/newPrice)
      • +
      +
    • +
    +
    addExchangeSchema({ exchangeName: "binance-X", getCandles, formatPrice, formatQuantity })
    addStrategySchema({ strategyName: "test-X", interval: "1m", getSignal, callbacks: { onActivePing, onClose, ... } })
    addFrameSchema({ frameName: "Nm-X", interval: "1m", startDate, endDate })
    const awaitSubject = new Subject();
    listenDoneBacktest(() => awaitSubject.next());
    const unsubscribeError = listenError((error) => { errorCaught = error; awaitSubject.next(); });
    Backtest.background("BTCUSDT", { strategyName, exchangeName, frameName });
    await awaitSubject.toPromise();
    unsubscribeError(); +
    + +
      +
    • Buffer candles ABOVE priceOpen for LONG (below for SHORT) before startTime — prevent early scheduled activation
    • +
    • All candles rebuilt inside first getSignal call (signalGenerated flag); getCandles returns from allCandles array
    • +
    • LONG activates when candle.low <= priceOpen; SHORT when candle.high >= priceOpen
    • +
    • SL checked BEFORE activation — activation candle low must not hit SL simultaneously
    • +
    • getAveragePrice(symbol) needs min 5 candles
    • +
    • Frame endDate must match candle count exactly (N candles = N minutes with 1m interval)
    • +
    • CC_MAX_STOPLOSS_DISTANCE_PERCENT: 20 — SL can be at most 20% from entry; violations silently break tests
    • +
    • CC_AVG_PRICE_CANDLES_COUNT: 5 — VWAP window; first 4 candles skipped as buffer in pending processing
    • +
    • minuteEstimatedTime must fit within frame; if candles run out before time expires → error thrown
    • +
    • onPartialProfit / onPartialLoss fire based on VWAP (averagePrice), not candle.close
    • +
    • revenuePercent in onPartialProfit = % progress toward TP (0–100), NOT P&L %
    • +
    • revenuePercent in onPartialLoss = % progress toward SL (0–100)
    • +
    +
      +
    • commitPartialProfit(symbol, percentToClose) — close X% at profit; requires currentPrice > effectivePriceOpen for LONG
    • +
    • commitPartialLoss(symbol, percentToClose) — close X% at loss; requires currentPrice < effectivePriceOpen for LONG
    • +
    • commitAverageBuy(symbol) — DCA entry (rejected if price unfavorable direction)
    • +
    • commitTrailingStop(symbol, percentShift, currentPrice) — shift SL by percent from original distance
    • +
    • All called from callbacks (onActivePing, onPartialProfit, onPartialLoss) with await
    • +
    • Backtest.getPendingSignal(symbol, context) — returns current signal state including priceOpen, priceStopLoss
    • +
    +
      +
    • No _entry → returns signal.priceOpen immediately (line 23)
    • +
    • No change in math for plain entries; refactor only affects DCA+partial cases
    • +
    +

    test/index.mjs — import list controls which test files run

    +
    + + + + + + + + + diff --git a/documents/docs.html b/documents/docs.html index 54f16e8ddb7289862bc448a7f77585374ab0c8bf..5fab4545efc104ba7edf75ba27e706399fcb3f4c 100644 --- a/documents/docs.html +++ b/documents/docs.html @@ -92,6 +92,7 @@
  • ExchangeUtils
  • CacheUtils
  • IntervalUtils
  • +
  • CronUtils
  • BreakevenMarkdownService
  • BreakevenUtils
  • StrategyMarkdownService
  • @@ -123,13 +124,13 @@
  • SizingGlobalService
  • RiskGlobalService
  • BacktestLogicPrivateService
  • +
  • FrameSchemaService
  • BacktestLogicPublicService
  • WalkerSchemaService
  • WalkerLogicPrivateService
  • WalkerLogicPublicService
  • WalkerCommandService
  • ExchangeSchemaService
  • -
  • FrameSchemaService
  • SizingSchemaService
  • ActionSchemaService
  • LiveLogicPrivateService
  • @@ -302,21 +303,25 @@
  • listenMaxDrawdownOnce
  • listenSignalNotify
  • listenSignalNotifyOnce
  • +
  • listenBeforeStart
  • +
  • listenBeforeStartOnce
  • +
  • listenAfterEnd
  • +
  • listenAfterEndOnce
  • hasTradeContext
  • getCandles
  • getAveragePrice
  • getClosePrice
  • formatPrice
  • formatQuantity
  • +
  • getOrderBook
  • +
  • getRawCandles
  • +
  • getNextCandles
  • +
  • getAggregatedTrades
  • getDate
  • getTimestamp
  • getMode
  • getSymbol
  • getContext
  • -
  • getOrderBook
  • -
  • getRawCandles
  • -
  • getNextCandles
  • -
  • getAggregatedTrades
  • getLatestSignal
  • getMinutesSinceLatestSignalCreated
  • getSignalState
  • @@ -461,6 +466,8 @@
  • HighestProfitContract
  • MaxDrawdownContract
  • SignalInfoContract
  • +
  • BeforeStartContract
  • +
  • AfterEndContract
  • IStateInstance
  • IStateParams
  • MessageModel
  • @@ -545,6 +552,8 @@
  • IMemoryInstance
  • IDumpContext
  • IDumpInstance
  • +
  • CronEntry
  • +
  • CronHandle
  • IBroker
  • WalkerStopContract
  • IParseArgsParams
  • @@ -681,6 +690,7 @@
  • IntervalFileFunction
  • DropFirst
  • IntervalFileKeyArgs
  • +
  • CronCallback
  • Columns$1
  • Columns
  • BrokerSignalOpenPayload
  • @@ -710,7 +720,9 @@
  • TWalkerLogicPublicService
  • ILiveLogicPrivateService
  • TLiveLogicPrivateService
  • +
  • Keys$1
  • TLiveLogicPublicService
  • +
  • Keys
  • TBacktestLogicPublicService
  • TPartial
  • TBreakeven
  • diff --git a/documents/docs_class_BacktestLogicPublicService.html b/documents/docs_class_BacktestLogicPublicService.html index 98d588ad2b5fa0e836fe9811f8e1f8c460e2b355..fc23a334229cf91bb1b1a346eeafb86cb15ee7c4 100644 --- a/documents/docs_class_BacktestLogicPublicService.html +++ b/documents/docs_class_BacktestLogicPublicService.html @@ -7,19 +7,28 @@ explicit context parameters.

    constructor();
     
    -
    loggerService: any
    +
    loggerService: { readonly methodContextService: { readonly context: IMethodContext; }; readonly executionContextService: { readonly context: IExecutionContext; }; ... 7 more ...; setLogger: (logger: ILogger) => void; }
     
    -
    backtestLogicPrivateService: any
    +
    backtestLogicPrivateService: BacktestLogicPrivateService
     
    -
    run: (symbol: string, context: { strategyName: string; exchangeName: string; frameName: string; }) => AsyncGenerator<IStrategyTickResultScheduled | IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, any>
    +
    timeMetaService: TimeMetaService
    +
    + +
    frameSchemaService: FrameSchemaService
    +
    + +
    exchangeConnectionService: ExchangeConnectionService
    +
    + +
    run(symbol: string, context: {
    strategyName: StrategyName;
    exchangeName: ExchangeName;
    frameName: FrameName;
    }): AsyncGenerator<IStrategyTickResultScheduled | IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, any>;

    Runs backtest for a symbol with context propagation.

    Streams closed signals as async generator. Context is automatically injected into all framework functions called during iteration.

    -
    +

    CronUtils

    Utility class for registering periodic tasks that fire on candle-interval +boundaries of the virtual time produced by parallel backtests.

    +

    Exported as singleton instance Cron for convenient usage.

    +

    Key property — singleshot coordination across parallel backtests: +when several Backtest.background(symbol, ...) runs hit the same aligned +boundary concurrently, the handler is invoked exactly once. Every parallel +tick for that boundary awaits the same in-flight promise and is released +together when the promise settles. After settlement the slot is cleared and +the next boundary produces a fresh promise.

    +

    Typical wiring:

    +
    constructor();
    +
    + +
    _entries: any
    +
    + +

    Registered entries by name.

    +

    Each record carries a monotonically increasing generation counter that +is bumped on every register(entry) call for the same name. The +generation participates in firedKey so writes from a still-in-flight +handler of a previous incarnation cannot poison _firedOnce for the +current incarnation — their key has a different generation suffix and +is simply ignored on lookup.

    +
    _generationCounter: any
    +
    + +

    Monotonic counter used to mint new entry generations on register.

    +
    _inFlight: any
    +
    + +

    In-flight handler slots.

    +

    Slot key shape (always includes the generation suffix :g${generation}; +the :${symbol} scope is present only in fan-out mode):

    +
      +
    • Periodic global: ${name}:${alignedMs}:g${generation}.
    • +
    • Periodic fan-out: ${name}:${alignedMs}:${symbol}:g${generation}.
    • +
    • Fire-once global: ${name}:once:g${generation}.
    • +
    • Fire-once fan-out: ${name}:once:${symbol}:g${generation}.
    • +
    +

    Value is the shared in-flight handler promise. Every parallel tick for +the same slot key awaits this exact promise (mutex semantics) and is +released together when it settles. _inFlight is owned exclusively by +_runEntryclear() does not touch it, so the singleshot promise +survives concurrent clear calls and continues to coordinate parallel +ticks until it settles.

    +
    _firedOnce: any
    +
    + +

    Keys of fire-once entries whose handler has already settled successfully.

    +

    Key shape (always includes the entry generation suffix :g${generation}):

    +
      +
    • Global fire-once: ${name}:g${generation}.
    • +
    • Fan-out fire-once: ${name}:${symbol}:g${generation} — one entry per +whitelisted symbol.
    • +
    +

    The generation suffix isolates incarnations of the same name: writes +landing from a still-in-flight handler of a previous register() carry +the old generation and are never matched by the new entry's lookup. +Stale entries are pruned by _clearFiredOnceFor on register/unregister +and wiped by clear().

    +

    Looked up by _tick to decide whether to skip; written by _runEntry +on successful settle.

    +
    _lastBoundary: any
    +
    + +

    Last interval boundary already fired per periodic slot.

    +

    Key shape (no alignedMs segment — one entry per logical slot, not per +boundary; always carries the generation suffix :g${generation}, and the +:${symbol} scope only in fan-out mode):

    +
      +
    • Periodic global: ${name}${genSuffix}.
    • +
    • Periodic fan-out: ${name}:${symbol}${genSuffix}.
    • +
    +

    Value is the aligned-boundary epoch ms (alignedMs) most recently opened +for that slot. _tick fires a periodic entry whenever the incoming tick's +aligned boundary is strictly greater than the stored value, instead of +requiring the tick to land exactly on the boundary. This fixes the +dropped-boundary bug: when virtual time jumps over a boundary (e.g. a +5m-driven loop skipping from 00:14 to 00:29 never lands on the 15m +00:15 boundary), the old ts === alignedMs check silently lost the tick. +With the watermark, the next tick whose alignedMs advanced past the +stored value fires once for the newest crossed boundary (catch-up +collapses multiple skipped boundaries into a single invocation at the +latest one).

    +

    Written synchronously in _tick at slot-open time (before the await), +so a still-in-flight handler does not let a later tick re-open the same +(or an already-passed) boundary. Fire-once entries never touch this map — +they use _firedOnce. Pruned by _clearBoundaryFor on +register/unregister and wiped by dispose.

    +
    _clearBoundaryFor: any
    +
    + +

    Garbage-collect every _lastBoundary key that belongs to the entry name +(any generation, global or fan-out).

    +

    Called from register/unregister alongside _clearFiredOnceFor. Like +that helper this is memory hygiene, not correctness — the generation suffix +already isolates re-registrations, so a stale watermark from an old +generation can never gate a new entry.

    +
    _clearFiredOnceFor: any
    +
    + +

    Garbage-collect every _firedOnce key that belongs to the entry name +(any generation, global or fan-out).

    +

    Called from register/unregister to free memory; not required +for correctness — the generation suffix already isolates re-registrations, +so leftover keys from old generations can never block a new entry. +They just sit unused until they are GC'd here or wiped by clear().

    +
    _runEntry: any
    +
    + +

    Build the singleshot promise for a single in-flight slot.

    +

    Invokes entry.handler(symbol, aligned, backtest), swallows and logs +any error via console.error, and clears the _inFlight slot +in .finally() so the next boundary produces a fresh promise. For +fire-once entries firedKey is added to _firedOnce on success so +subsequent ticks skip it.

    +
    register: (entry: CronEntry) => CronHandle
    +
    + +

    Register a periodic cron entry.

    +

    Idempotent on name: re-registering the same name replaces the previous +entry (interval/symbols/handler can all change). Re-registration does +not clear in-flight promises — entries still resolving complete with +the previous handler.

    +
    unregister: (name: string) => void
    +
    + +

    Remove a registered entry by name.

    +

    Does not cancel handlers already in flight — those resolve on their own +and clear their slot via .finally().

    +
    clear: (symbol?: string) => void
    +
    + +

    Clear fire-once marks so that fire-once entries can fire again.

    +

    Does not touch _inFlight — that map holds shared in-flight handler +promises through which parallel ticks coordinate. Wiping it mid-flight +would let a new tick start a second handler for a boundary that's +already running, breaking the singleshot contract.

    +

    Two modes:

    +
      +
    • Per-symbol (symbol provided): clears only fan-out fire-once +marks for that symbol — keys of the shape ${name}:${symbol}:g${gen}. +Global fire-once marks (${name}:g${gen}, no symbol component) are +left intact, since they are not attributable to a single symbol. +Useful for re-arming fan-out fire-once entries when a particular +symbol's run finishes and you want a future re-run to fire again.
    • +
    • All (no argument): wipes every fire-once mark across all entries +and symbols. Registered entries are not removed — use unregister +(or the disposer returned by register) for that.
    • +
    +

    Race with in-flight handlers. _firedOnce is written in +_runEntry's .finally(), which can run after a concurrent +clear() call. In that case the fire-once mark reappears immediately +after being wiped, and the next tick will treat the entry as already +fired. This is consistent with the singleshot promise itself surviving +clear() — the handler is allowed to finish — and the entry's +generation suffix in firedKey guarantees the stale mark cannot +outlive a subsequent register() of the same name. If you need a hard +re-arm, unregister + register bumps the generation and makes any +late write a no-op.

    +
    _tick: any
    +
    + +

    Process a virtual-time tick for symbol and fire any due cron entries.

    +

    Private. Invoked exclusively by the lifecycle bridge installed in +enable — beforeStart / idlePing / activePing / schedulePing +are funneled here through a shared singlerun queue, so calls to +_tick are serialised end-to-end. Do not call directly.

    +

    Algorithm (per registered entry): +0. Base-align the incoming when down to the 1-minute boundary (ts). +Lifecycle subjects may emit with sub-second jitter; rounding here +guarantees that beforeStart / idlePing / activePing / +schedulePing for the same virtual minute all hash to the same +slot key.

    +
      +
    1. If entry.symbols is non-empty and does not include symbol, skip.
    2. +
    3. Decide scope from entry.symbols: +
        +
      • Empty/undefined → global (slot key has no symbol component).
      • +
      • Non-empty → fan-out, slot key carries :${symbol} so each +whitelisted symbol gets its own slot and handler invocation.
      • +
      +
    4. +
    5. Append the current entry generation suffix :g${generation} to both +slot key and fired-once key. This isolates incarnations of the same +name: a register() after an in-flight handler bumps the +generation, so the late _firedOnce write from the old handler can +never block the new entry.
    6. +
    7. Fire-once (entry.interval === undefined): +
        +
      • If the entry's fired-once key is already in _firedOnce, skip.
      • +
      • Slot key: ${name}:once (+ scope) (+ gen).
      • +
      • aligned = the 1-minute-aligned when from step 0.
      • +
      +
    8. +
    9. Periodic (entry.interval set): +
        +
      • Align when to the entry's interval via alignToInterval to +get alignedMs, the boundary this tick belongs to.
      • +
      • Compare against the slot's watermark in _lastBoundary (keyed by +${name} + scope + gen, without the alignedMs segment). If a +watermark exists and alignedMs &lt;= lastBoundary, this boundary was +already fired — skip.
      • +
      • This watermark check replaces the old exact ts === alignedMs +match. The exact match required virtual time to land precisely on +the boundary; when a tick jumped clean over a boundary (e.g. a 5m +loop going 00:14 → 00:29 never touching the 15m 00:15 boundary) +the boundary was silently lost. With the watermark, the first tick +whose alignedMs advanced past the stored value fires once, at the +newest crossed boundary (catch-up collapses several skipped +boundaries into a single invocation at the latest one).
      • +
      • The watermark is advanced to alignedMs synchronously when the slot +is opened (before the await), so a concurrent tick on the same or +an already-passed boundary cannot open a duplicate slot while the +handler is still in flight.
      • +
      • Slot key: ${name}:${alignedMs} (+ scope) (+ gen).
      • +
      +
    10. +
    11. Singleshot per slot key: look up the slot in _inFlight. If a promise +already exists, await the same promise. Otherwise invoke +entry.handler, store the promise, and await it. The slot is +removed in .finally() so the next boundary creates a fresh promise; +for fire-once entries the fired-once key is also added to +_firedOnce on success so subsequent ticks skip it.
    12. +
    +

    Errors thrown by handler are caught, logged via console.error, and +not rethrown — a failing handler must not break the per-symbol +tick loop or unblock other parallel backtests with an unhandled +rejection. A failed fire-once handler is not marked as fired and +will retry on the next tick.

    +

    Requires active method context and execution context.

    +
    enable: (() => (...args: any[]) => any) & ISingleshotClearable<() => (...args: any[]) => any>
    +
    + +

    Subscribe Cron to the engine's strategy lifecycle subjects so registered +entries fire automatically — no manual wiring of listenTickBacktest / +listenSchedulePing etc. needed.

    +

    Subjects funneled into _tick:

    +
      +
    • beforeStartSubject — first event of every run.
    • +
    • idlePingSubject — every tick when no signal is pending or scheduled.
    • +
    • activePingSubject — every tick while a pending signal is being monitored.
    • +
    • schedulePingSubject — every tick while a scheduled signal is being monitored.
    • +
    +

    All four subjects are subscribed to a single singlerun-wrapped +handler that builds _tick(event.symbol, new Date(event.timestamp), event.backtest). singlerun merges the four streams into one serial +queue: at most one _tick runs at a time, the next waits. This matters +because the engine can emit beforeStart and an immediate idlePing +on the very same minute, and concurrent _ticks on the same +(symbol, minute) would otherwise race to open the same _inFlight +slot before either commit. Together these four sources cover every +tick the engine processes for every (symbol, virtual-minute) pair +regardless of whether the strategy is idle, active, or scheduled.

    +

    enable itself is wrapped in singleshot, so calling it repeatedly is +a no-op — subsequent calls return the same disposer. The disposer +unsubscribes from every subject and resets the singleshot so a future +enable() can re-subscribe cleanly. Equivalent to the +RecentAdapter.enable pattern.

    +

    The .subscribe callbacks are synchronous wrappers around the +singlerun-async handler; _tick's returned promise is awaited inside +singlerun to enforce ordering but not bubbled back to the subject. +Errors are caught and logged inside _runEntry.

    +
    disable: () => void
    +
    + +

    Tear down the lifecycle subscriptions installed by enable.

    +

    Safe to call multiple times and safe to call before enable() — both +are no-ops. Does not unregister entries, does not touch +_inFlight, and does not wipe _firedOnce (use unregister or +clear() for those).

    +
    dispose: () => void
    +
    + +

    Hard-reset the entire Cron state.

    +

    Performs in order:

    +
      +
    1. disable — tears down lifecycle subscriptions and resets the +enable singleshot so a future enable() re-subscribes cleanly.
    2. +
    3. Wipes _entries — every register'ed entry is forgotten. +Disposers returned by previous register() calls become no-ops +(their unregister(name) will not find anything to remove).
    4. +
    5. Wipes _firedOnce — all fire-once marks are dropped, so any future +re-registration of the same name fires again on the next matching +tick.
    6. +
    7. Wipes _lastBoundary — all periodic watermarks are dropped, so a +re-registered periodic entry starts firing from its next crossed +boundary again.
    8. +
    9. Does not touch _inFlight — in-flight handlers continue to +settle in the background and clear their own slots via .finally(). +Their final _firedOnce.add(firedKey) writes carry old-generation +keys and are harmless (lookup uses the post-dispose generation).
    10. +
    +

    Use from a CLI/session teardown when you want to throw away every +registration along with the lifecycle wiring — e.g. between two +independent runner scopes. For "just snap the subscriptions but keep +registrations" use disable instead; for "just re-arm fire-once +marks" use clear.

    +

    Idempotent. Safe to call multiple times and safe to call before +enable() / without any registrations.

    +
    + + + + + + + + + diff --git a/documents/docs_class_LiveLogicPublicService.html b/documents/docs_class_LiveLogicPublicService.html index 12586639a2a7f0a7b588321849ea54442976d748..fb928ea676bdb252c0101433081690a5c77c8242 100644 --- a/documents/docs_class_LiveLogicPublicService.html +++ b/documents/docs_class_LiveLogicPublicService.html @@ -13,20 +13,23 @@ explicit context parameters.

    constructor();
     
    -
    loggerService: any
    +
    loggerService: { readonly methodContextService: { readonly context: IMethodContext; }; readonly executionContextService: { readonly context: IExecutionContext; }; ... 7 more ...; setLogger: (logger: ILogger) => void; }
     
    -
    liveLogicPrivateService: any
    +
    liveLogicPrivateService: LiveLogicPrivateService
     
    -
    run: (symbol: string, context: { strategyName: string; exchangeName: string; }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, unknown>
    +
    exchangeConnectionService: ExchangeConnectionService
    +
    + +
    run(symbol: string, context: {
    strategyName: StrategyName;
    exchangeName: ExchangeName;
    }): AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, unknown>;

    Runs live trading for a symbol with context propagation.

    Streams opened and closed signals as infinite async generator. Context is automatically injected into all framework functions. Process can crash and restart - state will be recovered from disk.

    -
    +

    listenAfterEnd

    declare function listenAfterEnd(fn: (event: AfterEndContract) => void): () => void;
    +
    + +

    Subscribes to after end events with queued async processing. +Emits when the engine has completed processing a strategy execution for a symbol. +Events are processed sequentially in order received, even if callback is async. +Uses queued wrapper to prevent concurrent execution of the callback.

    + + + + + + + + + + + + + +
    ParameterDescription
    fnCallback function to handle after end events
    +
    + + + + + + + + + diff --git a/documents/docs_function_listenAfterEndOnce.html b/documents/docs_function_listenAfterEndOnce.html new file mode 100644 index 0000000000000000000000000000000000000000..c81e885e3ecb5c5b2bf7f695539eb8b04cad7398 --- /dev/null +++ b/documents/docs_function_listenAfterEndOnce.html @@ -0,0 +1,49 @@ +docs/function/listenAfterEndOnce | backtest-kit

    listenAfterEndOnce

    declare function listenAfterEndOnce(filterFn: (event: AfterEndContract) => boolean, fn: (event: AfterEndContract) => void): () => void;
    +
    + +

    Subscribes to filtered after end events with one-time execution. +Listens for events matching the filter predicate, then executes callback once +and automatically unsubscribes.

    + + + + + + + + + + + + + + + + + +
    ParameterDescription
    filterFnPredicate to filter which events trigger the callback
    fnCallback function to handle the filtered event (called only once)
    +
    + + + + + + + + + diff --git a/documents/docs_function_listenBeforeStart.html b/documents/docs_function_listenBeforeStart.html new file mode 100644 index 0000000000000000000000000000000000000000..3b66c80a20a0a19f740a0fcfcf8bbb12a5d3f255 --- /dev/null +++ b/documents/docs_function_listenBeforeStart.html @@ -0,0 +1,46 @@ +docs/function/listenBeforeStart | backtest-kit

    listenBeforeStart

    declare function listenBeforeStart(fn: (event: BeforeStartContract) => void): () => void;
    +
    + +

    Subscribes to before start events with queued async processing. +Emits when the engine is about to start a new strategy execution for a symbol. +Events are processed sequentially in order received, even if callback is async. +Uses queued wrapper to prevent concurrent execution of the callback.

    + + + + + + + + + + + + + +
    ParameterDescription
    fnCallback function to handle before start events
    +
    + + + + + + + + + diff --git a/documents/docs_function_listenBeforeStartOnce.html b/documents/docs_function_listenBeforeStartOnce.html new file mode 100644 index 0000000000000000000000000000000000000000..7b5d1f7c64395cf45554830ef069b78e995b57dd --- /dev/null +++ b/documents/docs_function_listenBeforeStartOnce.html @@ -0,0 +1,49 @@ +docs/function/listenBeforeStartOnce | backtest-kit

    listenBeforeStartOnce

    declare function listenBeforeStartOnce(filterFn: (event: BeforeStartContract) => boolean, fn: (event: BeforeStartContract) => void): () => void;
    +
    + +

    Subscribes to filtered before start events with one-time execution. +Listens for events matching the filter predicate, then executes callback once +and automatically unsubscribes.

    + + + + + + + + + + + + + + + + + +
    ParameterDescription
    filterFnPredicate to filter which events trigger the callback
    fnCallback function to handle the filtered event (called only once)
    +
    + + + + + + + + + diff --git a/documents/docs_interface_AfterEndContract.html b/documents/docs_interface_AfterEndContract.html new file mode 100644 index 0000000000000000000000000000000000000000..79bb08c9f4bf43fff912643045cb88ae7c445bfd --- /dev/null +++ b/documents/docs_interface_AfterEndContract.html @@ -0,0 +1,103 @@ +docs/interface/AfterEndContract | backtest-kit

    AfterEndContract

    Contract for the afterEnd lifecycle event of strategy execution.

    +

    Emitted by the engine after the strategy iterator has finished — whether +by reaching the end of the frame, being stopped via stopStrategy, +throwing an error, or being cancelled by the consumer (e.g., breaking out +of for await). Used by subscribers to perform teardown that should +happen exactly once per run: flushing buffers, closing files, computing +final aggregates, sending a "run completed" notification, etc.

    +

    Guarantees:

    +
      +
    • Fires exactly once per run() invocation, paired with the matching +BeforeStartContract event. The pairing holds for every termination +path including exceptions and external cancellation (delivered via the +generator's try/finally block).
    • +
    • Listener errors are caught and routed to the global errorEmitter; they +never propagate to the original caller.
    • +
    +

    Mode differences:

    +
      +
    • In backtest mode, when is the cursor position from TimeMetaService +at the moment of completion — i.e., the historical time of the last +processed candle. If the run was interrupted before any candle was +processed (e.g., empty frame, immediate cancellation), when falls +back to the frame's planned start date so it equals +BeforeStartContract.when for the same run. This means +afterEnd.when - beforeStart.when is always the real processed +duration, never an inflated planned one.
    • +
    • In live mode, when is the current wall-clock time aligned to the +1-minute boundary at the moment of emission.
    • +
    +
    symbol: string
    +
    + +

    Trading symbol the run was for (e.g., "BTCUSDT", "ETHUSDT"). +Matches the symbol from the paired BeforeStartContract.

    +
    strategyName: string
    +
    + +

    Name of the strategy that was executed. Use this to demultiplex events +when subscribing globally to runs across multiple strategies on the +same symbol.

    +
    exchangeName: string
    +
    + +

    Name of the exchange that provided market data for this run.

    +
    frameName: string
    +
    + +

    Name of the frame (timeframe / date range) the run used. Empty string +in live mode, where frames are not used.

    +
    backtest: boolean
    +
    + +

    true if this event was emitted from a backtest run, false if from a +live trading run. Use this to branch listener logic without inspecting +other fields.

    +
    currentPrice: number
    +
    + +

    Average symbol price observed at the moment the event was emitted, +fetched from ExchangeConnectionService.getAveragePrice(symbol). +Provided as a convenience so subscribers don't need to query the +exchange themselves.

    +
    when: Date
    +
    + +

    Event time as a Date instance.

    +

    In backtest: cursor position from TimeMetaService at completion (the +time of the last processed candle), with fallback to the frame's +planned start date if no candle was processed.

    +

    In live: wall-clock now, aligned to 1-minute boundary.

    +

    Always equal to new Date(timestamp).

    +
    timestamp: number
    +
    + +

    Same value as when, expressed as milliseconds since the Unix epoch. +Provided so subscribers can avoid calling .getTime() and to keep the +payload trivially serialisable (e.g., for forwarding over IPC or +writing to a log).

    +
    + + + + + + + + + diff --git a/documents/docs_interface_BacktestStatisticsModel.html b/documents/docs_interface_BacktestStatisticsModel.html index 826214eaa8db08074ea222f3e093a410fd30fd04..bc300f8330fd6b74f5102481cfc02784d6b2d90c 100644 --- a/documents/docs_interface_BacktestStatisticsModel.html +++ b/documents/docs_interface_BacktestStatisticsModel.html @@ -40,7 +40,7 @@ Provides comprehensive metrics for strategy performance analysis.

    annualizedSharpeRatio: number
     
    -

    Annualized Sharpe Ratio (sharpeRatio × √365), null if unsafe. Higher is better.

    +

    Annualized Sharpe Ratio (sharpeRatio × √tradesPerYear), null if unsafe. Higher is better.

    certaintyRatio: number
     
    @@ -60,7 +60,7 @@ Provides comprehensive metrics for strategy performance analysis.

    sortinoRatio: number
     
    -

    Sortino Ratio (avgPnl / downside deviation — stdDev of losses only), null if unsafe. Higher is better.

    +

    Sortino Ratio (avgPnl / downside deviation — RMS of losing trades only), null if unsafe. Higher is better.

    calmarRatio: number
     
    diff --git a/documents/docs_interface_BeforeStartContract.html b/documents/docs_interface_BeforeStartContract.html new file mode 100644 index 0000000000000000000000000000000000000000..6d1e457c382aa6d73f5262f78a6308f48bdd0a7e --- /dev/null +++ b/documents/docs_interface_BeforeStartContract.html @@ -0,0 +1,97 @@ +docs/interface/BeforeStartContract | backtest-kit

    BeforeStartContract

    Contract for the beforeStart lifecycle event of strategy execution.

    +

    Emitted by the engine immediately before it begins iterating the strategy +for a given symbol — after validation and context setup, but before the +first candle/tick is processed. Used by subscribers to perform +initialization that should happen exactly once per run: opening log files, +resetting per-run accumulators, sending a "run started" notification, +snapshotting initial state, etc.

    +

    Guarantees:

    +
      +
    • Fires exactly once per run() invocation, before any signal is yielded.
    • +
    • Always paired with an AfterEndContract event for the same run, even if +the iterator is interrupted, throws, or is cancelled externally. If +beforeStart fires, afterEnd is guaranteed to fire afterwards.
    • +
    • Listener errors are caught and routed to the global errorEmitter; they +never abort the run.
    • +
    +

    Mode differences:

    +
      +
    • In backtest mode, when is the planned start of the frame (from +FrameSchemaService.startDate, aligned to 1-minute boundary). It is the +intended beginning of the historical replay, not wall-clock time.
    • +
    • In live mode, when is the current wall-clock time aligned to the +1-minute boundary.
    • +
    +
    symbol: string
    +
    + +

    Trading symbol the run is for (e.g., "BTCUSDT", "ETHUSDT"). +Same value that was passed to Backtest.run / Live.run.

    +
    strategyName: string
    +
    + +

    Name of the strategy being executed. Use this to demultiplex events when +subscribing globally to runs across multiple strategies on the same +symbol.

    +
    exchangeName: string
    +
    + +

    Name of the exchange providing market data for this run.

    +
    frameName: string
    +
    + +

    Name of the frame (timeframe / date range) for the run. Empty string in +live mode, where frames are not used.

    +
    backtest: boolean
    +
    + +

    true if this event was emitted from a backtest run, false if from a +live trading run. Use this to branch listener logic without inspecting +other fields.

    +
    currentPrice: number
    +
    + +

    Average symbol price observed at the moment the event was emitted, +fetched from ExchangeConnectionService.getAveragePrice(symbol). +Provided as a convenience so subscribers don't need to query the +exchange themselves.

    +
    when: Date
    +
    + +

    Event time as a Date instance.

    +

    In backtest: the planned start of the frame (aligned to 1-minute +boundary). Represents intended start time, not the moment of emission.

    +

    In live: wall-clock now, aligned to 1-minute boundary.

    +

    Always equal to new Date(timestamp).

    +
    timestamp: number
    +
    + +

    Same value as when, expressed as milliseconds since the Unix epoch. +Provided so subscribers can avoid calling .getTime() and to keep the +payload trivially serialisable (e.g., for forwarding over IPC or +writing to a log).

    +
    + + + + + + + + + diff --git a/documents/docs_interface_CronEntry.html b/documents/docs_interface_CronEntry.html new file mode 100644 index 0000000000000000000000000000000000000000..db73d2f6084fc6f62124e18196a81a057e58b088 --- /dev/null +++ b/documents/docs_interface_CronEntry.html @@ -0,0 +1,65 @@ +docs/interface/CronEntry | backtest-kit

    CronEntry

    Configuration for a registered cron entry.

    +
    name: string
    +
    + +

    Unique name of the entry. Used as the dedup key on register (re-registering +the same name replaces the previous entry) and as part of the singleshot +coordination key.

    +

    Must be non-empty and must not contain :: is reserved as the slot-key +segment separator and would otherwise create ambiguity between global and +fan-out fire-once keys.

    +
    interval: CandleInterval
    +
    + +

    Candle interval at whose boundaries the handler fires. +Same scale as CandleInterval used by Interval and Cache: +"1m" &vert; "5m" | "1h" | "1d" etc.

    +

    If omitted, the entry switches to fire-once mode: the handler is +invoked on the very first matching tick (no boundary check) and never +again. If the handler throws, the entry is not marked as fired and +will retry on the next tick.

    +
    symbols: string[]
    +
    + +

    Symbol whitelist that doubles as the fan-out switch.

    +
      +
    • Empty/undefined → global singleshot: across all parallel backtests +the handler runs once per boundary. The first symbol to reach the +boundary opens the slot; others await the same promise.
    • +
    • Non-empty → per-symbol fan-out: ticks whose symbol is not in the +list are skipped, and ticks whose symbol is in the list each open +their own slot. The handler runs once per whitelisted symbol per +boundary.
    • +
    +

    The same rule applies in fire-once mode: global → handler runs once +total; fan-out → once per whitelisted symbol.

    +

    Each symbol must not contain : (same reason as CronEntry.name).

    +
    handler: CronCallback
    +
    + +

    Handler invoked on the first parallel tick to reach a new boundary.

    +
    + + + + + + + + + diff --git a/documents/docs_interface_CronHandle.html b/documents/docs_interface_CronHandle.html new file mode 100644 index 0000000000000000000000000000000000000000..5d989ef04db4daa260972124ca4788acab3ee142 --- /dev/null +++ b/documents/docs_interface_CronHandle.html @@ -0,0 +1,27 @@ +docs/interface/CronHandle | backtest-kit

    CronHandle

    Handle returned from register. Call it to unregister the entry — +equivalent to Cron.unregister(name).

    +
    + + + + + + + + + diff --git a/documents/docs_interface_IHeatmapRow.html b/documents/docs_interface_IHeatmapRow.html index 8514a8a2d79a7b6a6f5b310e4c908174e7928c84..a7c3d9e50990721c5bef16a84eb8f2919a37063d 100644 --- a/documents/docs_interface_IHeatmapRow.html +++ b/documents/docs_interface_IHeatmapRow.html @@ -11,7 +11,7 @@ Aggregated metrics across all strategies for one trading pair.

    sharpeRatio: number
     
    -

    Risk-adjusted return (Sharpe Ratio)

    +

    Risk-adjusted return per trade (Sharpe Ratio = avgPnl / stdDev)

    maxDrawdown: number
     
    @@ -75,7 +75,7 @@ Aggregated metrics across all strategies for one trading pair.

    sortinoRatio: number
     
    -

    Sortino Ratio (avgPnl / downside deviation — stdDev of losses only). Higher is better.

    +

    Sortino Ratio (avgPnl / downside deviation — RMS of losing trades only). Higher is better.

    calmarRatio: number
     
    diff --git a/documents/docs_interface_ISignalDto.html b/documents/docs_interface_ISignalDto.html index ddbe329c82e9b7ee22f5ee882f3eec62bde0658e..709b4a8497282152792f6edd7dc32341f34fd9dd 100644 --- a/documents/docs_interface_ISignalDto.html +++ b/documents/docs_interface_ISignalDto.html @@ -4,6 +4,10 @@ Will be validated and augmented with auto-generated id.

    Optional signal ID (auto-generated if not provided)

    +
    symbol: string
    +
    + +

    Symbol of a ticker on exchange

    position: "long" | "short"
     
    @@ -34,7 +38,7 @@ Default: GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES

    Cost of this entry in USD. Default: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST

    -
    +

    CronCallback

    type CronCallback = (symbol: string, when: Date, backtest: boolean) => void | Promise<void>;
    +
    + +

    Callback signature for a cron entry handler.

    +

    Invocation cardinality depends on entry.symbols (see CronEntry):

    +
      +
    • Global mode (symbols empty/undefined): invoked once per aligned +boundary across all parallel backtests. The first symbol to reach the +boundary opens the slot and runs the handler; others await the same +promise.
    • +
    • Fan-out mode (symbols non-empty): invoked once per aligned +boundary per whitelisted symbol. Each symbol has its own slot.
    • +
    +
    + + + + + + + + + diff --git a/documents/docs_type_Keys.html b/documents/docs_type_Keys.html new file mode 100644 index 0000000000000000000000000000000000000000..2a267810bbfccc2c3e2e969354023b077b942fc0 --- /dev/null +++ b/documents/docs_type_Keys.html @@ -0,0 +1,30 @@ +docs/type/Keys | backtest-kit

    Keys

    type Keys = Omit<BacktestLogicPublicService, keyof {
    exchangeConnectionService: never;
    backtestLogicPrivateService: never;
    frameSchemaService: never;
    timeMetaService: never;
    loggerService: never;
    }>; +
    + +

    Type definition for keys of BacktestLogicPublicService. +Omits private dependencies. Used for creating a public API surface.

    +
    + + + + + + + + + diff --git a/documents/docs_type_Keys_1.html b/documents/docs_type_Keys_1.html new file mode 100644 index 0000000000000000000000000000000000000000..b1a4ee603923279e894a7f4416bf12646beb7ac7 --- /dev/null +++ b/documents/docs_type_Keys_1.html @@ -0,0 +1,28 @@ +docs/type/Keys$1 | backtest-kit

    Keys$1

    type Keys$1 = Omit<LiveLogicPublicService, keyof {
    loggerService: never;
    liveLogicPrivateService: never;
    exchangeConnectionService: never;
    }>; +
    + +
    + + + + + + + + + diff --git a/documents/docs_type_TBacktestLogicPublicService.html b/documents/docs_type_TBacktestLogicPublicService.html index 083ab999280484ccd216b4cf5a2ea71cbb0f3596..b62d562fbcfe45e1140372fb67fcd78e747d0e44 100644 --- a/documents/docs_type_TBacktestLogicPublicService.html +++ b/documents/docs_type_TBacktestLogicPublicService.html @@ -1,4 +1,4 @@ -docs/type/TBacktestLogicPublicService | backtest-kit

    TBacktestLogicPublicService

    type TBacktestLogicPublicService = {
    [key in keyof BacktestLogicPublicService]: any;
    }; +docs/type/TBacktestLogicPublicService | backtest-kit

    TBacktestLogicPublicService

    type TBacktestLogicPublicService = {
    [key in keyof Keys]: any;
    };

    Type definition for BacktestLogicPublicService. diff --git a/documents/docs_type_TLiveLogicPublicService.html b/documents/docs_type_TLiveLogicPublicService.html index 81bccbee0e47f424223f065ab9dc7f621227de61..fe4b6a2122a52835229f8104e9090e03d276fb98 100644 --- a/documents/docs_type_TLiveLogicPublicService.html +++ b/documents/docs_type_TLiveLogicPublicService.html @@ -1,4 +1,4 @@ -docs/type/TLiveLogicPublicService | backtest-kit

    TLiveLogicPublicService

    type TLiveLogicPublicService = {
    [key in keyof LiveLogicPublicService]: any;
    }; +docs/type/TLiveLogicPublicService | backtest-kit

    TLiveLogicPublicService

    type TLiveLogicPublicService = {
    [key in keyof Keys$1]: any;
    };

    Type definition for LiveLogicPublicService. diff --git a/documents/private_classes.html b/documents/private_classes.html index 9f90b50aaaaeb4dc680eca96d82fa49ed5b7ea34..90d94e9861865297ef02ff7fa11f8c3a57f3ae58 100644 --- a/documents/private_classes.html +++ b/documents/private_classes.html @@ -122,762 +122,753 @@

  • createAwaiter from functools-kit for async coordination
  • Background execution with Backtest.background() and event-driven completion detection
  • -

    backtest-kit classes

    The WalkerValidationService helps you keep track of and verify your parameter sweep configurations, which are used for things like optimizing trading strategies or tuning hyperparameters. Think of it as a central place to register and check if your parameter sets are correctly defined before you start running tests.

    -

    It essentially manages a collection of these parameter sets (called walkers).

    -

    You can add new walkers to the system using the addWalker() method.

    -

    Before running any tests or analyses using a specific walker, you'll want to use validate() to make sure it’s properly registered. This prevents errors and ensures everything is set up correctly.

    -

    If you need to see all the walkers you've registered, the list() function provides a quick way to get a list of all configurations.

    -

    The service also optimizes its performance by remembering the results of validations, so it doesn't have to repeatedly check the same walkers.

    -

    WalkerUtils simplifies interacting with and managing walker comparisons, which are essentially automated tests of trading strategies. It provides a straightforward way to execute these tests and offers tools for monitoring their progress and generating reports. The class acts as a central hub for these operations, automatically handling details like identifying the specific trading system and comparison setup to use.

    -

    You can run walker comparisons directly, execute them in the background for tasks like logging or triggering callbacks without needing to process every update, or halt ongoing comparisons to prevent new signals from being generated. It also allows retrieving complete results and generating a formatted markdown report detailing the comparison.

    -

    Finally, WalkerUtils lets you check the status of running walker instances and save the generated reports to a file. It's designed to be easily accessible throughout your application, ensuring a consistent way to manage and observe these critical trading tests.

    -

    The WalkerSchemaService helps you keep track of and manage your walker schemas, which are essentially blueprints for how your walkers operate. It uses a special system to store these schemas in a type-safe way, reducing errors.

    -

    You can add new walker schemas using the addWalker() method (represented here as register) and find them again later by their name using get().

    -

    Before a new schema is officially added, the validateShallow() method quickly checks if it has all the necessary parts and if those parts are of the expected types – this helps prevent issues down the line.

    -

    If a schema already exists, you can update it with new information using override(), which lets you change specific parts without having to redefine the whole schema.

    -

    The service also has a built-in logging system (loggerService) to help you track what’s happening. Finally, it holds the actual schema registry internally (_registry), though you typically won’t interact with it directly.

    -

    WalkerReportService helps you keep track of how your trading strategies are performing during optimization. It listens for events from your optimization process and records key details like metrics and statistics. This allows you to easily compare different strategies and see how your optimization is progressing over time.

    -

    The service uses a database to store these results, making it simple to analyze and understand your optimization journey.

    -

    You can start receiving these updates by using the subscribe function, which will return a function to stop the updates with unsubscribe. It’s designed to prevent accidental duplicate subscriptions, ensuring smooth operation.

    -

    This service helps you create reports about your trading strategies, specifically focusing on what’s happening during "walker" simulations. It listens for updates from these simulations and gathers information about how different strategies are performing.

    -

    It keeps track of results for each simulation separately, ensuring that data for one strategy doesn't interfere with another. It then organizes this data into easy-to-read tables, which it can save as markdown files for detailed analysis.

    -

    You can subscribe to receive updates as the simulations run, and unsubscribe when you no longer need them. The service allows you to retrieve specific data points, generate full reports, and save them to disk. It can also clear out old data when you want to start fresh. If you're looking to generate reports on how your trading strategies are doing, this service is designed to help.

    -

    This service helps coordinate and manage the execution of walkers, which are essentially the building blocks of your trading strategies. It builds upon a private service to seamlessly pass along important information like the strategy name, exchange, frame, and walker identifier.

    -

    Think of it as a conductor ensuring everything runs smoothly and consistently.

    -

    The run method is the key – it takes a symbol (like a stock ticker) and context data, then kicks off the walker comparison process. This function handles the actual execution of your backtests. It will iterate through all strategies.

    -

    WalkerLogicPrivateService helps you compare different trading strategies against each other. It manages the process of running these strategies and provides updates as they finish.

    -

    The service keeps track of the best performance seen so far and then delivers a final report showing how all the strategies stack up in a ranked order.

    -

    It relies on BacktestLogicPublicService to actually execute the individual trading strategies.

    -

    The run method is the main way to use the service - you give it a stock symbol, a list of strategies to test, and the metric you want to optimize for (like profit or drawdown). It then runs each strategy one after another, providing progress updates along the way.

    -

    WalkerCommandService acts as a central access point for interacting with walker functionality within the system. Think of it as a convenient layer on top of WalkerLogicPublicService, designed to make it easier to incorporate walker operations into different parts of your application.

    -

    It manages several services involved in the process, including validation services for strategies, exchanges, frames, walkers, and risk assessment, as well as services that handle schemas and logging.

    -

    The primary function it exposes is the run method. This method allows you to execute a walker comparison, specifying the symbol you want to analyze, along with important context details like the names of the walker, exchange, and frame being used. It returns a generator that yields the results of the walker comparison, allowing for a stream of information.

    -

    The TimeMetaService helps you get the most recent candle timestamp for a specific trading setup – think symbol, strategy, exchange, and timeframe – even when you're not actively running a trade. It’s like having a reliable clock that always knows the latest time for your trading.

    -

    It keeps track of these timestamps in a smart way, storing them and updating them automatically as your strategies run. If you need that timestamp outside of the usual trading loop, the service provides it to you. If a timestamp hasn't arrived yet, it waits briefly for it.

    -

    To keep things clean and efficient, the service manages these stored timestamps, allowing you to clear them out entirely or just for a specific trading setup. This ensures you're always working with the freshest data and avoids potential issues caused by old timestamps. The service is designed to work seamlessly with other parts of the trading system, and it's automatically updated and reset as needed.

    -

    The SystemUtils class helps keep your backtesting sessions separate and clean. It prevents one backtest from accidentally affecting another, which is crucial for reliable results.

    -

    Think of it as creating a temporary "safe zone" for each test.

    -

    The createSnapshot function lets you create a backup of the current event listeners before a backtest starts. This backup lets you restore everything to its original state once the test is finished, ensuring a fresh start for the next session. It’s like hitting a reset button for the event listeners.

    -

    SyncUtils helps you understand what’s happening with your trading signals over time. It gathers information about when signals are opened and closed.

    -

    This class provides ways to get data about the signals—like how many were opened and closed—and create easy-to-read reports.

    -

    You can retrieve summarized statistics about signal activity, or generate detailed markdown reports that show each signal's specifics, including its entry and exit details and performance.

    -

    Finally, SyncUtils can automatically save these reports as files, organizing them by symbol, strategy, and whether they are backtest or live data. This makes it simple to track and analyze your trading activity.

    -

    The SyncReportService is designed to keep a record of when your trading signals are created and closed. It listens for signal events, specifically when a signal is opened (like a limit order being filled) and when a signal is closed (when a position is exited).

    -

    It diligently logs detailed information about these events – for signal openings, it captures the full signal details, and for signal closures, it includes profit and loss data along with the reason for the exit.

    -

    This service then uses a ReportWriter to store these events persistently, ensuring an audit trail for order management. To prevent accidental duplicates, it uses a mechanism to ensure only one subscription is active at a time.

    -

    You can start listening for these events by using the subscribe method, which returns a function you can call later to stop listening. The unsubscribe method provides a clean way to end the subscription process, ensuring no further events are recorded.

    -

    This service is responsible for creating and saving reports detailing the lifecycle of signals, such as when they are opened and closed. It keeps track of these signal events and organizes them by symbol, strategy, exchange, timeframe, and whether it’s a backtest or live trade.

    -

    The service listens for signal events, recording each one and generating detailed reports in markdown format. These reports will include a summary of the signal's journey, including when it opened, when it closed, and any reasons for closure. You also get statistics like the total number of events, opens, and closes.

    -

    To start receiving signal events, you need to subscribe to a designated event stream. The system prevents accidental duplicate subscriptions, so the first subscription call returns a way to unsubscribe. When you’re finished, you can unsubscribe, which cleans up everything and stops the service from listening for new events.

    -

    The getData function provides a snapshot of the accumulated statistics for a specific signal, letting you check the overall health and performance of a particular signal. You can also generate reports on demand using the getReport function. The dump function takes the report and saves it as a file. Finally, clear allows you to wipe the accumulated data, either for a specific signal setup or everything entirely.

    -

    The StrategyValidationService helps you keep track of your trading strategies and make sure they're set up correctly. It acts like a central manager, registering your strategies and checking if they exist before you try to use them.

    -

    It also verifies that any linked risk profiles and actions are also valid, ensuring a smooth and error-free trading experience.

    -

    To speed things up, it remembers the results of previous validation checks.

    +

    backtest-kit classes

    The WalkerValidationService helps you keep track of and make sure your parameter sweep setups – we call them "walkers" – are working correctly. It's like a central place to register your walkers, define what they are, and check that they exist before you try to use them.

    +

    This service remembers how often it validates walkers, so things run smoothly and quickly.

    Here's what you can do with it:

      -
    • Register new strategies: Use addStrategy to add your strategy configurations.
    • -
    • Validate strategies: validate makes sure your strategies and their related settings are in order.
    • -
    • See all registered strategies: list gives you a complete overview of all the strategies you’ve registered.
    • +
    • Register walkers: Use addWalker to tell the service about your parameter sweep configurations.
    • +
    • Verify walkers: validate makes sure a walker exists before you proceed, preventing errors.
    • +
    • See your walkers: list provides a simple way to see all the walkers you've registered.
    -

    It relies on other services—the logger, risk validation, and action validation—to handle specific checks.

    -

    StrategyUtils helps you understand how your trading strategies are performing by providing tools to analyze and report on their activity. Think of it as a central place to gather information about what your strategies are doing – whether they're closing positions, taking profits, or adjusting stops.

    -

    It lets you easily pull out key statistics like how often a strategy is taking certain actions. You can also generate detailed reports in a readable format that shows all the events your strategies have triggered, including important details like price, percentage values, and timestamps.

    -

    Finally, it can automatically save these reports to files, so you can keep a record of your strategies' behavior over time. You can specify which columns to display in the report and customize the file naming. The system keeps a limited history of events – about 250 events per strategy and symbol combination – so you don't get overwhelmed with data.

    -

    This service acts as a central hub for managing and storing strategy schemas, ensuring they are consistently structured and typed. It uses a specialized registry to keep track of these schemas in a type-safe way.

    -

    You can add new strategies to the registry using the addStrategy() function (represented here as register). To find a specific strategy, just use its name with the get() function.

    -

    Before a new strategy is added, the service performs a quick check (validateShallow) to make sure it has the basic, necessary properties.

    -

    If you need to update an existing strategy, you can use the override() function to apply changes, ensuring you don’t have to redefine the entire schema.

    -

    The service also has an internal logger to help track and debug any issues that might occur during strategy management.

    -

    This service helps you keep a detailed audit trail of what your trading strategies are doing. It records key events like canceling scheduled orders, closing pending orders, taking partial profits or losses, adjusting stop-loss and take-profit levels, and moving the stop-loss to breakeven.

    -

    Think of it as a way to create a persistent log of your strategy’s actions, which is great for reviewing and debugging. Unlike a service that accumulates data in memory, this one writes events directly to files as they happen.

    -

    To start using it, you need to "subscribe" to begin logging. Once subscribed, events are saved to JSON files. When you're done, you can "unsubscribe" to stop the logging process. It’s important to subscribe before logging events and unsubscribe when you no longer need the audit trail. Each event type (cancel-scheduled, close-pending, etc.) has its own method to record the details.

    -

    This service helps you keep track of what's happening with your trading strategies during backtesting or live trading. It acts like a central log, collecting details about actions like canceling orders, closing trades, and adjusting stop-loss levels.

    -

    Instead of immediately saving every action, it temporarily stores them, allowing for more efficient batch reporting and analysis.

    -

    To start using it, you need to "subscribe" to begin collecting events. It then automatically records events as your strategy executes. You can later retrieve statistics, generate formatted reports in Markdown, or export those reports to files. When you're finished, you "unsubscribe" to stop collecting data and clean up the memory.

    -

    The service uses a clever caching system to manage the storage of events for each strategy and symbol combination.

    -

    It provides functions to record specific trade actions:

    +

    The service also uses a loggerService to keep track of what's happening and has an internal _walkerMap to organize everything.

    +

    WalkerUtils provides helpful tools for working with walkers, which are essentially automated trading systems. It simplifies the process of running and managing these systems, making it easier to execute comparisons and analyze results.

    +

    Think of it as a central hub for interacting with your walkers. You can trigger a walker to run, execute it in the background without constantly monitoring the progress, or stop it entirely.

    +

    You can also retrieve complete data sets from your walkers, generate reports summarizing their performance, or save those reports directly to a file.

    +

    To keep things organized, WalkerUtils automatically keeps track of each walker running for a specific trading symbol, ensuring each one operates independently. It also offers a way to view a list of all currently active walkers and their status. This singleton instance ensures easy access to these helpful functions throughout your system.

    +

    The WalkerSchemaService helps keep track of different schema definitions for walkers, ensuring consistency and type safety. It’s like a central place to store and manage these schemas.

    +

    It uses a registry to store these schemas, and you add new ones using the addWalker (or register) method.

    +

    You can then easily find a specific schema by its name using the get method.

    +

    Before a new schema is added, validateShallow checks that it has the essential building blocks in place.

    +

    If a schema already exists, you can update parts of it using the override method, which lets you make changes without completely replacing the original.

    +

    The service also has internal components for logging and managing context, which are used behind the scenes.

    +

    WalkerReportService helps you keep track of your strategy optimization efforts. It's designed to capture the results of your backtesting experiments and store them neatly in a SQLite database.

    +

    Think of it as a recorder that listens for updates from your optimization process – it takes notes on each test run, including important metrics and performance data. This allows you to compare different strategy configurations and see how your optimization is progressing.

    +

    You can easily sign up to receive these updates, and there's a built-in safeguard to prevent accidental double-subscriptions. When you're finished, simply unsubscribe to stop receiving updates. The service uses a logger to provide some helpful debugging output too.

    +

    The WalkerMarkdownService is designed to automatically create and save detailed reports about your trading strategies. It listens for updates as your trading strategies run (called "walker" events) and keeps track of how each strategy is performing.

    +

    It organizes this information, using a special memoization technique to keep things efficient, and then formats it into easy-to-read markdown tables. These reports are saved as files on your computer, specifically in the logs/walker/{walkerName}.md directory.

    +

    You can control when the service starts and stops listening for updates, ensuring you're only collecting the data you need. It also allows you to retrieve specific data points, generate customized reports, and clear out the accumulated results when needed, either for a single strategy or all of them. The service uses a logger to provide debug information.

    +

    This service helps manage and run the "walkers" that perform trading simulations. Think of walkers as individual trading strategies. It automatically passes along important information like the strategy's name, the exchange used, the simulation's name, and the walker's own name to each simulation.

    +

    Essentially, it acts as a middleman between your trading logic and the underlying engine, ensuring that all the necessary context is provided without you having to manually manage it.

    +

    The run method is the key function. It takes a stock symbol and a context object – which provides the walker's identity – and then kicks off the simulations, returning a stream of results. This method orchestrates running your trading strategies on a given symbol, ensuring they all have the correct setup and context.

    +

    WalkerLogicPrivateService helps you compare different trading strategies against each other. It orchestrates the process, providing updates as each strategy finishes running.

    +

    Think of it as a conductor leading an orchestra of backtests.

    +

    It keeps track of the best performing strategy as things progress, and finally delivers a complete ranking of all strategies tested.

    +

    Behind the scenes, it relies on BacktestLogicPublicService to actually run each individual strategy.

    +

    You use it by giving it a symbol to trade, a list of strategy names to test, the metric you want to optimize for, and some contextual information.

    +

    The run method then executes these strategies one after another and gives you progress updates along the way.

    +

    WalkerCommandService acts as a central access point for interacting with the walker functionality within the backtest-kit framework. It's designed to make using the walker logic easier by providing a simple way to inject dependencies.

    +

    Think of it as a helpful intermediary that manages different services involved in the walker process.

    +

    It includes access to services for managing walker logic, schemas, validations (for strategies, exchanges, frames, walkers, risks and actions) and strategy schemas.

    +

    The run method is the main way you'll interact with the service; it allows you to execute a walker comparison for a specific trading symbol, while also providing context about which walker, exchange, and frame are being used. This allows for running complex tests and comparisons across different setups.

    +

    The TimeMetaService keeps track of the most recent candle timestamp for each trading setup – considering the symbol, strategy, exchange, and timeframe – so you can reliably get the current candle time even when you're not actively executing trades. It's designed to be used when you need the time outside of the typical trading tick cycle, like when triggering commands between trades.

    +

    Essentially, it creates a snapshot of the latest timestamp for each unique combination of those factors. If a timestamp hasn't been recorded yet, it will wait a short time to see if one arrives.

    +

    Think of it as a helper that stores and provides the candle time, automatically updating it as your strategies run. If you're already in the middle of a trade, it'll grab the timestamp from a related service; otherwise, it looks up the cached value.

    +

    It’s managed centrally within the system, updated automatically by the strategy connection service, and can be cleared to free up resources or reset the data when you start a new backtest or trading session. You can clear everything at once or just specific time setups.

    +

    SystemUtils helps keep backtest sessions independent of each other. It prevents one session's actions from accidentally affecting another.

    +

    Think of it as creating a temporary "clean slate" for each backtest.

    +

    The createSnapshot function lets you freeze the current state of all the global event listeners. This is useful because it allows you to take a look at what's currently happening without being affected by any running tests. After you're done, you can easily restore everything to its original state.

    +

    SyncUtils helps you understand how your trading signals are working by providing a way to track and report on their lifecycle. It gathers information about signal openings and closings, providing statistics and detailed reports.

    +

    You can use it to get aggregated data about your signals, showing things like the total number of events, opens, and closes. It can also generate nicely formatted markdown reports.

    +

    These reports will give you a clear picture of what’s happening with your signals, including details like the signal ID, direction, entry/exit prices, and profit/loss.

    +

    Finally, you can easily save these reports as files for later analysis or sharing. The file names clearly indicate the symbol, strategy, exchange, frame, and whether it’s a backtest or live data.

    +

    The SyncReportService is designed to keep a record of signal synchronization events, specifically when a signal is opened (like a limit order being filled) or closed (when a position is exited). It listens for these events and diligently logs them, including important details like the signal specifics, profit/loss, and the reason for closing. This creates an audit trail useful for managing orders and understanding trading activity.

    +

    You can think of it as a data keeper that ensures you have a history of what's happening with your signals.

    +

    The service uses a logger to help with debugging and it has a built-in mechanism to prevent accidental duplicate subscriptions.

    +

    To make it work, you need to subscribe to listen for signal events and you can unsubscribe when you no longer need to track those events. The subscribe method provides a function to unsubscribe, ensuring you don’t continue receiving updates unnecessarily.

    +

    This service is designed to create and save reports detailing the lifecycle of trading signals. It keeps track of signal events like openings and closings.

    +

    It listens for these signal events and organizes them, keeping track of data for each unique combination of symbol, strategy, exchange, frame, and whether the backtest is live or historical.

    +

    The core function is to generate reports in markdown format, providing a clear and readable record of signal activity including statistics like the total number of events and how many signals were opened or closed.

    +

    You can subscribe to receive these signal events, and when you're finished, you can unsubscribe to stop listening and clear out the accumulated data.

    +

    You can request data for a specific combination of symbol, strategy, exchange, frame, and backtest to see accumulated statistics or to get the full report as a markdown string. The reports can also be saved directly to disk.

    +

    Finally, it's possible to clear the stored data, either for a specific signal combination or for all signal combinations, essentially resetting the tracking.

    +

    The StrategyValidationService helps you manage and double-check your trading strategy setups. It keeps track of all your defined strategies and makes sure everything is in order before you start trading.

    +

    Think of it as a central place to register your strategies using addStrategy, allowing you to give them names and configurations.

    +

    When you need to use a strategy, validate will confirm that the strategy exists and that any related risk profiles or actions are set up correctly. This service also remembers validation results, speeding things up with memoization.

    +

    Finally, if you need a quick overview, list provides a handy list of all the strategies currently registered with the service.

    +

    StrategyUtils helps you analyze and understand how your trading strategies are performing. Think of it as a reporting tool that gathers information about events like closing trades, taking profits, or setting stop-loss orders. It provides ways to get summaries of this data, create detailed reports, and even save those reports to files.

    +

    You can request statistical information about a strategy's actions, like how many times it took profits versus how many times it closed pending orders.

    +

    It can also generate comprehensive markdown reports, showing you a table of all the events that occurred, including details like the price, percentage values, and timestamps.

    +

    Finally, StrategyUtils can automatically save these reports to files, organizing them by symbol, strategy name, exchange, and frame, making it easy to track performance over time. These reports are formatted to be human-readable and provide useful insights into your strategies.

    +

    The StrategySchemaService helps keep track of different trading strategy blueprints, ensuring they're consistent and well-defined. It uses a special system to store these blueprints in a way that catches errors early on.

    +

    You can add new strategy blueprints using the addStrategy() method, and then retrieve them later using their names.

    +

    Before a new blueprint is added, it's quickly checked to make sure it has all the necessary parts and that those parts are the right types. This helps prevent problems down the road.

    +

    If a blueprint already exists, you can update it with new information using the override() method. Finally, the get() method lets you find a specific strategy blueprint by its name.

    +

    This service is designed to keep a detailed audit trail of what's happening with your trading strategies. It focuses on recording key events like canceling scheduled trades, closing pending orders, taking partial profits or losses, adjusting stop-loss orders (trailing stops and take profits), and setting breakeven points.

    +

    Think of it as a way to ensure you have a permanent, verifiable record of your strategy's actions, written directly to JSON files as they happen.

    +

    To start using it, you need to "subscribe" to the service. After subscribing, each trading event (cancel, close, profit, loss, etc.) will automatically be logged. When you're finished, "unsubscribe" to stop the logging process.

    +

    Each event type has its own specific function (cancelScheduled, closePending, partialProfit, etc.) that you'll call whenever that event occurs within your strategy. These functions record the details of the event, including the symbol traded, prices, profitability metrics, and other relevant context. It’s important to note that this service is different from services that accumulate data in memory for reports - it writes everything directly to disk for continuous auditing.

    +

    This service helps you track and report on what's happening in your trading strategies during backtesting or live trading. Think of it as a detailed event logger and reporter.

    +

    It gathers information about key actions within your strategy, like canceling orders, closing positions, and adjusting stop-loss or take-profit levels. Instead of writing each of these events immediately to a file, it temporarily holds them in memory for efficiency.

    +

    You can then use this service to generate summaries and detailed markdown reports, customize the information displayed, and save them to files with descriptive names. It offers options to clear the data—either specific parts or everything—and it has a clear lifecycle: you subscribe to start collecting data, and unsubscribe to stop and clear everything.

    +

    The cancelScheduled, closePending, partialProfit, partialLoss, trailingStop, trailingTake, breakeven, activateScheduled, and averageBuy methods essentially act as "event listeners" that record these different types of trading actions.

    +

    The getData method lets you retrieve the raw event data, getReport generates formatted markdown reports, and dump saves those reports to files. Finally, clear lets you wipe the collected data, and subscribe/unsubscribe manage the service's active state.

    +

    This service acts as a central hub for managing strategy execution and provides tools for inspecting a live or backtested position. It leverages other services to handle things like logging, connecting to exchanges, and validating strategies.

    +

    It offers a wide range of methods for querying the status of a pending or scheduled signal, including information on profit/loss, position size, entry prices, and time-related metrics (like estimated duration and waiting time).

    +

    You can use it to validate strategies, retrieve signals, check if a strategy is stopped or breakeven, and even execute actions like closing a position or canceling a scheduled order. It also offers functions for partial profit or loss management and getting historical data points regarding peak profit and maximum drawdown. Finally, it includes methods for disposal, clearing caches, and handling edge-cases like backtesting.

    +

    The StrategyConnectionService acts as a central router for trading strategies within the backtest-kit framework. It's designed to efficiently manage and execute strategies by ensuring the right strategy implementation handles requests based on the trading symbol and strategy name.

    +

    Here's a breakdown:

      -
    • cancelScheduled: Records when a scheduled order is canceled.
    • -
    • closePending: Records when a pending order is closed.
    • -
    • partialProfit/Loss: Records when a portion of the position is closed for profit or loss.
    • -
    • trailingStop/Take: Records adjustments to trailing stop-loss or take-profit levels.
    • -
    • breakeven: Records when the stop-loss is adjusted to the entry price.
    • -
    • activateScheduled: Records when a scheduled signal is activated early.
    • -
    • averageBuy: Records when a new averaging entry (DCA) is made.
    • +
    • Smart Routing: It automatically directs calls to the correct strategy implementation, based on the symbol and strategy name.
    • +
    • Performance Boost: It uses a caching system to store and reuse strategy implementations, minimizing overhead.
    • +
    • Initialization: It ensures that strategies are properly initialized before any trading actions are performed.
    • +
    • Handles Both Live and Backtesting: It's equipped to manage both live trading (tick) and historical backtesting (backtest) scenarios.
    -

    You can get a summary of the events (getData) or a detailed report (getReport) in markdown format. The dump function combines these two, creating a file. The clear method allows you to erase any accumulated event data.

    -

    This service acts as a central hub for managing trading strategies within the backtest framework. It wraps other services to inject relevant information, like the trading symbol, timeframe, and backtest settings, into the trading execution process. It handles validations, retrieves key data points about a position (like cost, P&L, and entry prices), and provides methods to interact with the strategy, such as closing positions, stopping signals, and performing backtests. It's a key component used internally by other backtesting services.

    -

    The service offers a range of methods to query the status of a position, including its total cost, P&L, entry prices, partial closures, and more. It also provides functionality to adjust stop-loss and take-profit levels, cancel scheduled signals, and dispose of strategies. Memoization is used to optimize validation performance. Data returned by these functions provides useful insights into a position’s performance and history.

    -

    The StrategyConnectionService acts as a central router for your trading strategies. It intelligently finds the right strategy implementation based on the trading symbol and its specific configuration, optimizing performance by caching these strategy instances.

    -

    Essentially, it handles requests to strategies, ensuring they're correctly initialized and executed, whether you're running live trades or backtesting historical data.

    -

    Here’s a breakdown of what it does:

    +

    The service relies on several other services, like loggerService, exchangeConnectionService, and timeMetaService, to manage logging, communication with exchanges, and time-related operations.

    +

    Key functions allow for actions such as getting pending signals, calculating position costs, managing partial closes, and executing various trading commands like partialProfit, trailingStop, and averageBuy. It also provides methods to stop, cancel, or close strategies, and to check their status and performance metrics.

    +

    The StorageLiveAdapter provides a flexible way to manage how your trading signals are stored, allowing you to easily switch between different storage methods. It acts as a middleman, adapting to various storage implementations like persistent storage on disk, in-memory storage, or even a dummy adapter for testing.

    +

    You can choose your storage method using convenient functions like usePersist, useMemory, and useDummy, and the adapter will remember your choice for future operations. If you need to change your storage location, like when running a new test with a different working directory, calling clear ensures a fresh start.

    +

    The adapter handles events like signals being opened, closed, scheduled, or cancelled, forwarding these actions to the selected storage backend. You can also retrieve signals by their ID or list all stored signals through this adapter. It also manages "ping" events to update signal timestamps when they are actively scheduled or running. If you want to use a completely custom storage solution, you can register a new adapter.

    +

    The StorageBacktestAdapter provides a flexible way to manage how trading signals are stored during backtesting. It uses a design pattern that allows you to easily switch between different storage methods – like persistent storage to disk, memory-only storage, or even a dummy storage for testing – without changing your core backtesting logic.

    +

    The adapter itself doesn't directly handle storage; it delegates that to a chosen "storage utils" implementation. You can configure which storage method is used by calling methods like usePersist(), useMemory(), or useDummy(). The useStorageAdapter method offers even more control, allowing you to specify a custom storage implementation.

    +

    Several methods, such as handleOpened, handleClosed, and findById, provide ways to interact with the underlying storage, essentially acting as a middleman between your backtesting code and the actual storage mechanism. These methods proxy requests to the currently active storage adapter. The clear() method is important to call if your working directory changes, ensuring a fresh storage instance is used. The adapter uses caching to improve performance, rebuilding the storage utils only when needed.

    +

    The StorageAdapter handles the storage of both your backtesting data and live trading signals, keeping everything organized in one place. It automatically updates the storage as new signals are generated.

    +

    To start using the storage, you need to "enable" it, which subscribes it to the signal emitters, and it's designed to only subscribe once. Conversely, you can "disable" the storage at any time to unsubscribe from these signals, and you can safely call disable multiple times.

    +

    You can easily find a specific signal using its ID, or retrieve lists of all backtest signals and all live signals stored. This adapter provides a straightforward way to manage your signal data.

    +

    The StateLiveAdapter helps manage the ongoing state of your trading strategies, particularly useful for complex logic like LLM-driven capitulation rules. Think of it as a central place to track information about each trade, like its peak performance and how long it’s been open.

    +

    It's designed to be flexible, letting you choose where that trade data is stored – in memory for quick access, on disk for persistence across restarts, or even a dummy adapter if you just want to test things out without saving anything. The system remembers these settings to avoid needing to recreate them frequently.

    +

    Importantly, this adapter saves critical data like peak profit and the duration a trade has been open, so it can be used to inform decisions. For example, if a trade hasn’t performed as expected after a certain amount of time, the system can automatically react.

    +

    When a signal is finished, like when a trade is closed, the disposeSignal method ensures that associated data is properly cleaned up. The clear method is important to call when things like your working directory change to prevent issues with how the adapter functions. You can easily switch between the different storage methods using the helper functions like useLocal(), usePersist(), and useDummy().

    +

    The StateBacktestAdapter provides a flexible way to manage and store the state information used during backtesting. It lets you easily switch between different storage methods, like keeping data only in memory, saving it to files, or using a dummy adapter that simply ignores all data. This adaptability is achieved through an adapter pattern, allowing for swappable state implementations.

    +

    The adapter automatically creates and manages state instances, remembering them for each signal and bucket combination to avoid unnecessary re-creation. When a signal is finished, you can use disposeSignal to clear these cached instances.

    +

    You can quickly switch to the default in-memory storage using useLocal(), persist data to disk with usePersist(), or discard data entirely with useDummy(). For advanced users, useStateAdapter() lets you plug in your own custom state adapter implementations. If your working directory changes, clear() will remove the memoized caches so that new instances are initialized with the updated path.

    +

    This framework is particularly useful for implementing complex trading rules, such as those involving monitoring trade performance over time and using LLMs to evaluate market confirmations – where you need to track metrics like peak percentage and minutes open for each trade.

    +

    The StateAdapter is the central piece for managing how your backtest and live trading data is stored and accessed. It's designed to keep things clean and efficient.

    +

    It automatically handles subscribing and unsubscribing from signals, ensuring old data is removed when signals are no longer active, which prevents issues with outdated information.

    +

    You can use enable to get things started and disable to stop the storage. Calling disable multiple times won't cause problems.

    +

    getState lets you retrieve the current value of a signal, figuring out whether to pull from the backtest or live data based on your settings.

    +

    Finally, setState provides a way to update the stored values of a signal, again intelligently routing to the correct backtest or live location.

    +

    The SizingValidationService helps you keep track of your position sizing strategies and make sure they're set up correctly before you start trading. Think of it as a central place to register and check your sizing methods.

    +

    It allows you to add new sizing strategies using addSizing, so you have a complete record of all your available options.

    +

    The validate function is your safety net; it verifies that a sizing strategy exists before you try to use it, preventing potential errors.

    +

    To speed things up, the service caches the results of these validations.

    +

    Finally, list provides a simple way to see all the sizing strategies you've registered.

    +

    The SizingSchemaService helps you manage and store sizing schema definitions in a safe and organized way. It uses a registry to keep track of these schemas, ensuring type correctness.

    +

    You can add new sizing schemas using the register method, and update existing ones using override.

    +

    To use a specific sizing schema, simply retrieve it by its name with the get method.

    +

    Before a schema is added, validateShallow checks its basic structure to make sure it has all the necessary properties and they are of the right type. This helps to prevent errors later on.

    +

    The SizingGlobalService helps determine how much of an asset to trade, managing the sizing process. It relies on other services – a connection service for actual size calculations and a validation service to ensure sizing requests are correct. Think of it as the central hub for figuring out the right size for each trade, providing a consistent and reliable approach used both behind the scenes and by the tools you use directly. It keeps track of important things like logging and validation to help maintain a clear picture of sizing operations.

    +

    The SizingConnectionService acts as a central hub for calculating trade sizes. It figures out which specific sizing method to use based on a name you provide.

    +

    Think of it as a dispatcher; it directs sizing requests to the right implementation.

    +

    To improve speed, it remembers (caches) which sizing methods it’s already set up, so it doesn't have to recreate them every time.

    +

    The service uses sizingName to route sizing method calls to the right sizing implementation.

    +

    When no sizing configuration is needed, the sizingName is simply left blank.

    +

    The getSizing property handles retrieving the correct sizing method, using caching to avoid unnecessary setup.

    +

    The calculate method performs the actual sizing calculation, taking into account risk management and the chosen sizing method like fixed percentage or Kelly Criterion.

    +

    The SessionLiveAdapter helps manage and store data during live trading sessions, making it easy to swap out different storage methods. It acts as a central point for accessing and modifying session data, allowing you to use various storage backends depending on your needs.

    +

    You can choose between several storage options: a file-system based persistent storage (the default), an in-memory solution, or even a dummy adapter that simply discards any data written to it.

    +

    The useLocal, usePersist, and useDummy methods provide simple ways to switch between these storage options. If you need more flexibility, useSessionAdapter allows you to plug in your own custom storage implementation.

    +

    The adapter intelligently caches session instances to avoid unnecessary reloads, and the clear method lets you refresh that cache, which is particularly useful when the working directory changes. Ultimately, this component simplifies how you handle and persist data throughout your trading sessions.

    +

    This component provides a flexible way to manage session data during backtesting. It acts as a bridge, allowing you to easily swap out different storage mechanisms for your session information.

    +

    By default, it uses an in-memory storage, which is fast but doesn't save data between runs. You can switch to a file-based storage to persist your session data to disk, or a dummy storage for testing purposes where data isn’t saved.

    +

    The getData and setData methods allow you to read and write session values, identified by a symbol, strategy name, exchange, and frame name.

    +

    Convenience methods like useLocal, usePersist, useDummy, and useSessionAdapter simplify switching between these different storage options. The clear method helps refresh the stored data when the working directory changes.

    +

    The SessionAdapter acts as a central hub for handling data storage during both simulated (backtest) and live trading sessions. It intelligently directs data requests and updates to the appropriate storage mechanism – either the backtest storage or the live storage – depending on whether you're running a test or a real-time trade.

    +

    You can use getData to retrieve existing data, specifying the symbol, the context of the trade (strategy, exchange, frame), whether it’s a backtest, and the timestamp. Similarly, setData allows you to update the data, sending the information to the correct storage based on whether it's a backtest or live scenario. This adapter simplifies managing your data across different operational modes.

    +

    The ScheduleUtils class helps you understand how your scheduled signals are performing. It's a single, easy-to-use resource for getting insights into signal scheduling.

    +

    You can retrieve data about scheduled signals for specific symbols and strategies, allowing you to monitor their queue status, cancellations, and wait times.

    +

    It also generates detailed markdown reports summarizing signal events, making it simple to identify potential bottlenecks or issues.

    +

    Finally, you can save these reports directly to a file for later analysis or sharing.

    +

    The ScheduleReportService helps you keep track of when signals are scheduled, opened, and cancelled. It listens for these signal events and records them in a database, allowing you to analyze how long it takes for signals to be acted upon.

    +

    Think of it as a detective, diligently noting down the milestones of a signal’s journey.

    +

    It calculates the time elapsed between a signal being scheduled and when it's either executed or cancelled.

    +

    The service uses a logger to output debug information and prevents accidental double-subscription to signal events.

    +

    To start using it, you’ll subscribe to signal events, and when you're done, you’ll unsubscribe to stop listening. The subscribe method gives you a function that you can call to stop listening.

    +

    The ScheduleMarkdownService helps you keep track of your automated trading signals. It watches for signals that are scheduled or cancelled and organizes them by strategy.

    +

    It automatically creates easy-to-read reports in Markdown format, displaying details about each signal, like when it was scheduled and if it was later cancelled. The service even calculates useful statistics, like the cancellation rate and how long signals typically wait before being executed.

    +

    These reports are saved as files on your computer, making it simple to review your automated trading system's performance. You can also request specific data or generate reports on demand. It also offers a convenient way to clear out the historical data when it is no longer needed.

    +

    The RiskValidationService helps you keep track of and verify your risk management settings. It acts like a central record keeper for your risk profiles, ensuring they're all accounted for before you start trading.

    +

    It lets you register new risk profiles, a process that involves providing a name and a set of rules.

    +

    Before any operation that uses a risk profile, you can ask the service to validate it, which quickly checks if the profile actually exists.

    +

    To speed things up, the service remembers the results of these validations, so it doesn't have to re-check profiles repeatedly.

    +

    Finally, you can get a complete list of all the risk profiles that are currently registered with the system.

    +

    The RiskUtils class helps you analyze and understand risk rejection events within your trading system. Think of it as a tool for inspecting what went wrong and why. It gathers information about rejections – like the symbol involved, the trading strategy used, the position taken, and the reason for the rejection – and provides ways to view and export this data.

    +

    You can use it to get overall statistics on the rejections, such as how many occurred, broken down by symbol and strategy. It can also create detailed reports in markdown format, presenting each rejection event in an organized table. These reports include details like the price at the time of rejection, the number of positions held, and a description of the reason for the rejection.

    +

    Finally, this class provides a simple way to save those detailed reports to a file, so you can review them later or share them with others. The file names are automatically generated, combining the symbol and strategy name for easy organization.

    +

    The RiskSchemaService helps you keep track of your risk schemas in a structured and reliable way.

    +

    It uses a special system for storing these schemas, ensuring that the data types are correct and consistent.

    +

    You can add new risk schemas using the addRisk() method (represented by the register property) and easily find existing ones by their names using the get method.

    +

    Before adding a schema, it checks the basic structure to make sure everything is set up properly (validateShallow).

    +

    If a risk schema already exists, you can update parts of it without replacing the whole thing using the override method.

    +

    The service also has a logger to help you debug and monitor how it's working.

    +

    The RiskReportService helps you keep a record of when your risk management system blocks trades. It listens for these rejections and saves details like why the trade was rejected and what the trade was supposed to be.

    +

    Think of it as an audit log specifically for risk-related decisions.

    +

    It uses a logger to help with debugging.

    +

    To start using it, you'll subscribe to the risk rejection events. This gives you a function to later stop the service. If you try to subscribe multiple times, it prevents that to ensure things are handled correctly. The unsubscribe function makes sure you’re not needlessly processing events when you don’t need to.

    +

    This service helps you automatically generate and save reports about rejected trades, which is useful for understanding why your trading strategies aren't executing as expected. It listens for "risk rejection" events, essentially tracking when trades are blocked.

    +

    It organizes these rejections by symbol (the asset being traded) and strategy (the trading rule being used). The service then creates easy-to-read markdown tables summarizing these rejected trades, including overall statistics like the total number of rejections.

    +

    You can retrieve data and reports for specific symbol-strategy combinations or clear all accumulated data. These reports are saved as markdown files on your system, making it simple to review and analyze rejection patterns. You can also customize the columns shown in the reports. The service keeps data for each combination of symbol, strategy, exchange, frame, and backtest separate, preventing data mixing.

    +

    This service acts as a central hub for managing risk during trading. It's responsible for ensuring that trades adhere to predefined risk limits and works closely with a connection service to validate those limits.

    +

    It keeps track of validations to avoid unnecessary repetition and provides logging for these activities.

    +

    The core functionality involves checking if a trading signal is permissible based on risk rules, with a special version that guarantees safety in concurrent scenarios. When a signal is approved, it registers the trade with the risk system, and when a trade closes, it removes the signal. Finally, it offers the ability to clear existing risk data, either for a specific risk setup or a complete reset.

    +

    This service acts as a central point for managing risk checks during trading, ensuring that all risk-related operations are handled by the correct, specialized risk implementation. It intelligently caches these risk implementations to improve performance, avoiding repeated creation of the same risk checks.

    +

    The service receives instructions on which risk rules to apply through a riskName parameter, and the specific risk implementation is selected based on this parameter. To handle different trading environments, it also considers the exchange and frame names alongside whether the test is a backtest or live trade.

    +

    Several key functions are provided: getRisk fetches cached risk implementations, checkSignal validates trading signals against predefined limits, and checkSignalAndReserve is a safe version used when placing trades. The addSignal and removeSignal functions manage the lifecycle of open and closed trades respectively, and clear allows for invalidating the cache when necessary. This service provides a structured and efficient way to manage risk within the trading framework.

    +

    The ReportWriterAdapter helps you collect and store data from your trading strategies, offering flexibility in how that data is saved. It uses a pattern that allows you to easily swap out different storage methods without changing your core code.

    +

    It keeps track of your storage instances, ensuring that you only have one storage instance for each type of report (like backtest results or live trading data) throughout the program's lifecycle. The default storage method saves data in JSONL format.

    +

    You can customize the storage method by providing your own adapter, or switch back to the default JSONL method as needed. The adapter handles writing the data, and it will set up the storage automatically the first time it's used.

    +

    There’s also a convenient option to use a dummy adapter which acts as a no-op, effectively discarding all data writes, which is useful for testing or scenarios where you don't need to store data. The adapter also has a clear method to reset the storage cache, useful when you change your working directory.

    +

    ReportUtils helps you control which parts of your trading system generate detailed reports. Think of it as a way to turn on or off logging for specific activities like backtesting, live trading, or analyzing your strategies.

    +

    It’s designed to be used alongside other components, often extended to provide even more reporting options.

    +

    The enable function lets you choose which report services to activate. When you use it, it starts listening for events and writing them to JSONL files—these files contain valuable data for analysis. Critically, you must remember to call the function it returns to stop the logging and prevent problems.

    +

    The disable function does the opposite; it stops the logging for services you've previously enabled. It’s useful for temporarily turning off reporting without affecting other areas of your system. This function doesn't need a cleanup function like enable.

    +

    This class provides a way to save your trading data and analysis results to files in a structured format. It's designed to write events as individual lines within JSON files, making it easy to process and analyze your backtest results later.

    +

    The files are organized into directories based on the type of report, and new directories are created automatically. Writes are handled carefully to avoid errors and ensure data isn't lost, with built-in protections against slow or unresponsive writing.

    +

    You can filter the data being written by including metadata like the trading symbol, strategy, exchange, and other identifiers. It's like creating a log file that’s perfectly formatted for searching and analysis.

    +

    Initialization only happens once, even if you call the initialization function multiple times. The write function is your main tool for saving event data, and it automatically adds metadata and a timestamp to each entry.

    +

    The ReportAdapter helps you manage and store your trading data in a flexible way. Think of it as a central hub for collecting information like trades and performance metrics.

    +

    It uses a pluggable design, so you can easily swap out how the data is stored—like switching from a simple file to a database—without changing much of your code.

    +

    It keeps track of different types of reports and remembers which storage method to use for each, making things efficient.

    +

    You can tell it which storage method to use by default, or temporarily disable storage completely to test things out.

    +

    If your working directory changes, clearing the adapter ensures fresh storage is used.

    +

    This utility class, ReflectUtils, provides a way to track key metrics like profit, loss, and drawdown for your trading strategies, especially useful during backtesting and live trading. It acts as a central point for accessing and validating position data, ensuring consistency and reducing potential errors.

    +

    Think of it as a toolkit for understanding how a position has performed. It lets you query things like:

      -
    • Smart Routing: Directs strategy calls to the correct implementation, based on symbols and other configuration details.
    • -
    • Performance Boost: Caches strategy instances to avoid recreating them repeatedly, which speeds things up.
    • -
    • Proper Initialization: Makes sure strategies are ready to go before any trading actions happen.
    • -
    • Handles Live & Historical Data: Works equally well for real-time trading (ticks) and analyzing past performance (backtesting).
    • +
    • Profit & Loss (PnL): Current PnL in percentage and cost (USD).
    • +
    • Peak Performance: Highest profit price, timestamp, and percentage reached.
    • +
    • Drawdown: The extent of losses relative to the peak profit, including timestamps and price/cost values.
    • +
    • Time-based Metrics: How long a position has been active, waiting for activation, or since its peak profit.
    -

    The service provides methods for retrieving signals, position details (like cost, P&L, levels), and managing signals (partial closes, average buy, scheduled activation). It also provides mechanisms to safely stop a strategy and clear cached data. All data access methods are context-aware, ensuring operations are properly isolated based on exchange and trading frame.

    -

    The StorageLiveAdapter provides a flexible way to manage how your trading signals are stored. It acts as a central point for interacting with different storage mechanisms, allowing you to easily switch between persistent storage (saving to disk), in-memory storage (temporary storage), or a dummy adapter (for testing purposes where no actual storage happens).

    -

    You can choose your storage method using methods like usePersist, useMemory, and useDummy, and the system remembers your choice for subsequent operations. The clear method is useful for resetting this choice when your working environment changes.

    -

    The adapter also handles various events related to signal activity – opening, closing, scheduling, and cancellations – forwarding these actions to the currently selected storage implementation. You can also retrieve signals by ID or list all signals, again relying on the active storage adapter. Finally, it provides a factory to control the creation of storage utilities, allowing for even greater customization.

    -

    This component provides a flexible way to manage how trading signal data is stored during backtesting. It allows you to easily switch between different storage methods, like persistent storage on disk, keeping data in memory, or even using a "dummy" adapter that doesn't actually save anything.

    -

    It acts as a middleman, delegating tasks like retrieving, listing, and updating signals to the currently selected storage method. You can swap out the storage backend by using the useStorageAdapter method, which lets you specify which implementation to use.

    -

    There are built-in options for quickly switching to persistent, memory, or dummy storage with usePersist, useMemory, and useDummy, respectively. If you're running multiple backtests where the base directory changes, you’ll want to call clear to force a fresh storage adapter instance to be created. The handleOpened, handleClosed, handleScheduled, and handleCancelled methods pass along signal events to the underlying storage adapter.

    -

    The StorageAdapter acts as a central hub for managing both the signals from your backtesting simulations and any live trading data. It automatically keeps track of new signals as they are generated, streamlining how you access and use this information.

    -

    You can control whether the adapter is actively listening for new signals using the enable property, which ensures a subscription only happens once. Conversely, disable provides a safe way to stop the adapter from receiving and storing signals, and it’s fine to call this multiple times.

    -

    Need to look up a specific signal? findSignalById lets you locate signals based on their unique identifier, regardless of whether they originate from backtest or live data. If you want to see all the signals from your backtesting simulations, use listSignalBacktest. Similarly, listSignalLive retrieves all signals from your live trading environment.

    -

    The StateLiveAdapter provides a flexible way to manage and store the state of your trading signals. Think of it as a central hub for keeping track of important data like peak percentages and how long a position has been open. It's designed to be adaptable; you can easily switch between different storage methods, from keeping data in memory for quick access to persisting it to a file for long-term reliability.

    -

    You can choose to save state data to a file on your computer (the default), keep it only in the current running program’s memory, or even use a "dummy" adapter that essentially ignores any changes. This makes it really useful for testing and experimentation.

    -

    The system is clever in how it manages these state instances, only creating them when needed and clearing them out when signals are closed. This optimization is key to performance.

    -

    It’s particularly helpful for strategies that need to react to specific events, such as automatically closing trades based on performance indicators over time—like the example given about using an LLM to assess a trade's progress and exiting if it doesn’t meet certain criteria. The data it tracks will survive restarts and you don't have to worry about losing that information.

    -

    To completely refresh the state, you can clear the cache, which is especially useful when changing the working directory for a strategy.

    -

    The StateBacktestAdapter provides a flexible way to manage the state of your backtesting environment, allowing you to easily switch between different storage methods. By default, it uses an in-memory storage, meaning all data is held in the process's memory and isn't saved when the process ends.

    -

    You have the option to change this behavior and use a persistent storage solution that saves data to disk, or a dummy adapter that effectively ignores any state changes – useful for testing or isolating certain scenarios.

    -

    The adapter is designed to track specific information like peak performance and how long a position has been open, which is particularly helpful for implementing automated trading rules based on LLM-driven insights. For example, if a trade doesn't reach a certain performance threshold after a set amount of time, the adapter can trigger an automatic exit.

    -

    To manage memory and ensure data consistency, there are methods to dispose of old state data related to a specific signal, and to clear the entire cache of memoized data when needed, like when the working directory changes. Essentially, it’s a modular system for keeping track of your backtesting progress and adapting it to different needs.

    -

    The StateAdapter is the central hub for managing your trading state, whether you're running a backtest or live trading.

    -

    It handles the behind-the-scenes work of keeping track of your data and cleaning up when things change.

    -

    Think of it like this: it listens for events related to your trading signals and automatically makes sure old data gets cleared out, preventing confusion.

    -

    You can use it to either get the current state of a signal, or to update the state when necessary. The adapter figures out whether you're in backtest or live mode and sends the request to the appropriate storage.

    -

    The enable property lets you start tracking state, making sure everything's set up correctly. disable lets you stop that tracking—and it's perfectly safe to call this multiple times.

    -

    This service helps you keep track of and ensure your position sizing strategies are set up correctly. It acts as a central place to register your different sizing approaches, like fixed percentages or Kelly Criterion.

    -

    Before you try to use a sizing strategy, this service will confirm it's actually registered, preventing errors and making your backtesting process more reliable.

    -

    For efficiency, it remembers the results of these checks so it doesn't have to re-validate strategies repeatedly.

    -

    You can use it to:

    +

    It handles things like partial closes, DCA entries, slippage, and fees in its calculations. The backtest parameter lets you tailor the data retrieval to either live trading or historical backtesting scenarios. The class is structured as a singleton, meaning you'll use one instance across your application for easy access. Essentially, it's designed to give you real-time visibility into position health.

    +

    The RecentLiveAdapter helps you manage and access recent trading signals, providing a flexible way to store and retrieve them. It’s designed to work with different storage methods, allowing you to choose between persistent (disk-based) and in-memory storage.

    +

    You can easily switch between storage options using usePersist for long-term storage and useMemory for quicker, temporary access. The adapter remembers the chosen storage method and automatically handles retrieving signals.

    +

    If you need to use a custom storage method, useRecentAdapter lets you specify your own implementation. To ensure data freshness, clear is useful when you need to rebuild the storage adapter, for example, when the working directory changes. The adapter takes care of fetching signals, calculating time elapsed since creation, and responding to "active ping" events, so you can focus on your trading logic.

    +

    This component helps manage and store recent trading signals, allowing you to choose between keeping them in memory or persisting them to disk. It provides a flexible way to adapt to different storage needs without changing the core logic of your backtesting framework.

    +

    You can easily switch between in-memory and persistent storage using useMemory and usePersist methods. The useRecentAdapter function allows you to customize the storage mechanism entirely by providing your own implementation.

    +

    The system keeps a cached version of the storage utilities for efficiency, but you can clear this cache using clear to ensure a fresh instance is used when the environment changes, like when your working directory is updated. The handleActivePing, getLatestSignal, and getMinutesSinceLatestSignalCreated methods act as intermediaries, forwarding requests to the currently active storage adapter.

    +

    The RecentAdapter is a central component responsible for handling and storing recent trading signals, whether you’re running a backtest or a live trading system. It automatically updates its signal storage whenever new data arrives.

    +

    You can easily get the most recent signal for a specific asset and situation. It prioritizes backtest data first, and then checks live data if nothing is found in the backtest.

    +

    To prevent look-ahead bias, the adapter makes sure the signal's timestamp isn't in the future compared to your specified time. It will return null if it finds a signal that’s too recent.

    +

    The adapter uses a clever system to ensure it only subscribes to data updates once, preventing unnecessary subscriptions and potential issues. It's also designed to be safely disabled and re-enabled as needed, even multiple times.

    +

    Finally, you can check how long ago the last signal was generated, also considering a look-ahead cutoff to avoid using future information.

    +

    PriceMetaService is a system that tracks the most recent market prices for trading strategies. It helps you get the current price even when you're not actively executing trades.

    +

    It stores price information for each unique combination of symbol, strategy, exchange, frame, and backtest setting. Think of it as a memory of prices, updated as strategies run.

    +

    If you need the current price, PriceMetaService tries to provide it quickly. If it hasn't received a price yet, it'll wait a short while. It also understands that sometimes you need a live price, and will fetch it from another service if needed.

    +

    You can clear this memory to release resources and make sure you’re working with fresh data. This is especially important when starting a new trading strategy. The service is designed to work behind the scenes, automatically updating and managing prices as your trading system operates.

    +

    This utility class helps you figure out how much to trade based on different strategies.

    +

    It offers pre-built methods for position sizing, like calculating size using a fixed percentage of your account, or using the Kelly Criterion which considers your win rate and loss ratio. You can also use an ATR-based method that factors in the Average True Range to gauge volatility.

    +

    Each method checks to make sure the information you provide matches the sizing technique you've selected, helping prevent errors.

    +

    The class is straightforward to use because it offers these calculations as readily available functions.

    +

    The Position class offers helpful tools for figuring out where to set your take profit and stop loss levels when trading. It simplifies the process by automatically adjusting these levels depending on whether you're going long (buying) or short (selling).

    +

    You have two main calculation methods available:

      -
    • Add new sizing strategies to your registry.
    • -
    • Verify that a sizing strategy exists before using it.
    • -
    • Get a complete list of all the sizing strategies you've registered.
    • -
    -

    The SizingSchemaService helps you keep track of your sizing schemas, which define how much of an asset to trade. It uses a special registry to safely store these schemas.

    -

    You add sizing schemas using addSizing() and find them later by their name.

    -

    Before a sizing schema is added, a quick check makes sure it has all the necessary parts and that they’re the right type.

    -

    The register method lets you add new sizing schemas to the registry. -The override method lets you update existing sizing schemas with just the changes you want to make. -Finally, the get method helps you find a specific sizing schema by its name.

    -

    The SizingGlobalService helps determine how much of an asset to trade. It's a central part of the backtest-kit framework, handling position sizing calculations behind the scenes for both the strategy execution and the tools you use.

    -

    Think of it as a coordinator; it uses a sizing connection service and a validation service to do its job.

    -

    The calculate function is the key – it takes information about your risk parameters and the situation (like the sizing name) and figures out the appropriate position size. The service also has properties for logging and interacting with other services, which are managed internally.

    -

    This service handles the calculations needed to determine how much of an asset to trade, based on your chosen sizing strategy. It acts as a central point, directing sizing requests to the right implementation, whether it's a fixed percentage, a Kelly criterion approach, or something else.

    -

    To improve efficiency, it remembers which sizing strategies it's already set up, so it doesn't have to recreate them every time you need to calculate a size.

    -

    The service relies on a schema service to understand the sizing configurations and a logger for tracking what’s happening. You specify which sizing method to use through a name, and if a strategy doesn't have a custom sizing setup, you’ll use an empty string as the sizing name.

    -

    The getSizing property is the main way to get a sizing instance, remembering past requests to avoid recreating it. calculate then uses this to compute the actual position size, taking into account your risk parameters and the selected sizing method.

    -

    The SessionLiveAdapter provides a flexible way to manage data during live trading sessions. Think of it as a central hub that can store and retrieve session information, and it’s designed to be easily swapped out with different storage methods.

    -

    By default, it uses a persistent storage that saves data to your computer's file system, meaning your data survives even if the program restarts. You also have the option to use a temporary, in-memory storage for quicker testing, or a dummy storage that simply ignores any data changes.

    -

    It intelligently caches these storage options, creating a specific instance based on the trading symbol, strategy name, exchange, and the timeframe being used, avoiding unnecessary overhead.

    -

    You can easily change how data is stored using convenient commands like useLocal, usePersist, useDummy, or even define and use your own custom storage adapter. If your working directory changes during your strategy's runtime, it's helpful to clear the cache using clear to ensure fresh instances are used.

    -

    This component, the SessionBacktestAdapter, provides a flexible way to manage and store data during backtesting. It acts as a bridge, allowing you to easily swap out different storage methods without changing the core backtesting logic.

    -

    By default, it uses an in-memory storage, meaning all data is kept in the program's memory. However, you can switch to storing data on disk for persistence or use a dummy adapter for testing purposes.

    -

    You can control how the data is stored using convenient methods like useLocal, usePersist, and useDummy. If you need even more control, useSessionAdapter lets you plug in your own custom storage solution.

    -

    The adapter keeps track of session data for each trading symbol, strategy name, exchange, and timeframe to optimize performance. If you change the directory where your backtest data is stored (using process.cwd()), you can clear the internal cache with clear to ensure fresh instances are created. The getData and setData methods provide the means to retrieve and update the session data.

    -

    The SessionAdapter acts as a central hub for handling data storage during both backtesting and live trading sessions. Think of it as a traffic director, ensuring that data requests and updates are sent to the correct place – either the backtest storage or the live session storage – depending on whether you’re running a test or a real-time trade.

    -

    You can retrieve existing data using the getData method, specifying the symbol, context (like strategy and exchange names), whether it's a backtest, and the timestamp. Similarly, the setData method allows you to update the stored data, again ensuring it goes to the right location. It simplifies the data management process by abstracting away the underlying differences between backtesting and live trading environments.

    -

    This class offers tools to analyze and report on scheduled trading signals. Think of it as a way to keep tabs on how your automated trading strategies are performing when it comes to signal execution.

    -

    It helps you monitor signals waiting in a queue, signals that were cancelled, and calculate metrics like cancellation rates and average wait times.

    -

    You can also use it to generate easy-to-read markdown reports detailing the signal lifecycle for specific trading strategies.

    -

    The getData method retrieves performance statistics, getReport creates a formatted markdown report, and dump saves those reports directly to a file. It’s designed for simple, consistent access to these reporting functions, using a single, readily available instance.

    -

    The ScheduleReportService helps you keep track of your scheduled signals and how long they take to execute or get cancelled. It listens for events related to signals being scheduled, activated, or cancelled.

    -

    It calculates the time elapsed between when a signal is scheduled and when it either starts running or is cancelled. This information is then saved to a database for later analysis and troubleshooting of any potential delays.

    -

    You can use the subscribe function to start listening for these signal events, and remember to use the returned function to unsubscribe when you no longer need to track them. If you try to subscribe multiple times, it will only register the first attempt, preventing unnecessary processing. The unsubscribe function gracefully stops the service from listening for events, ensuring clean operation.

    -

    This service automatically creates reports detailing scheduled trading signals, helping you analyze your strategies. It monitors when signals are scheduled and cancelled, keeping track of events for each strategy.

    -

    The reports are presented in a readable markdown format, showing detailed information about each event, and include helpful statistics like the cancellation rate and how long signals typically wait before execution.

    -

    These reports are saved to your logs folder, making it easy to review and understand the performance of your trading strategies over time.

    -

    You can subscribe to receive updates on scheduled signals, unsubscribe when you no longer need them, and clear the accumulated data when necessary. You can also request specific reports and dump them to disk in markdown format. The system organizes data into isolated storage for each unique combination of symbol, strategy, exchange, frame, and backtest.

    -

    This service helps you keep track of and confirm your risk management settings. It acts like a central hub for all your defined risk profiles.

    -

    You can register new risk profiles using addRisk, and before you actually use a profile, validate makes sure it exists, preventing errors.

    -

    To improve performance, the results of these validations are cached, so repeated checks don't slow things down.

    -

    If you need to see what risk profiles you've set up, list will give you a complete list of them.

    -

    The service also keeps a record of a logging service and an internal map for managing risk profiles.

    -

    RiskUtils helps you analyze and understand why your trading strategies might be getting flagged for risk. Think of it as a tool to dig into rejection events – moments when your strategy triggered a risk check.

    -

    It gathers information from events related to risk rejections, keeping track of things like the symbol being traded, the strategy used, the position taken, and the reason for the rejection.

    -

    You can use it to get summaries of rejection statistics, like how many times a particular strategy was rejected or how many rejections occurred for a specific symbol. It can also create readable reports in Markdown format, essentially building a table of these rejection events with details like the price, position size, and timestamp.

    -

    Finally, RiskUtils provides a simple way to export these reports to files, making it easier to share or archive your risk rejection data. These files are named based on the symbol and strategy used, like "BTCUSDT_my-strategy.md".

    -

    This service helps manage and store risk schema definitions. It uses a special system to keep track of different schema types safely.

    -

    You can add new risk profiles using the addRisk() function (which is registered via register), and find them again later by their names using the get() function.

    -

    Before a new risk schema is added, it's quickly checked to make sure it has all the necessary parts with the validateShallow() function. If a risk schema already exists, you can update parts of it using the override() function. The loggerService property provides access to logging and context information for debugging and monitoring.

    -

    The RiskReportService helps you keep track of when your risk management system flags and rejects trades. It listens for those rejection events and saves details like why the trade was rejected and what the trade looked like.

    -

    Think of it as a logbook for your risk controls.

    -

    You can tell the service to start listening for these rejection events using the subscribe method, and it will send you back a function to stop listening – use that when you're done.

    -

    To stop listening, simply call the unsubscribe method. It’s designed so you won’t accidentally subscribe more than once.

    -

    The service also uses a logger to help with debugging, and it stores the rejection data for later analysis and auditing.

    -

    This service helps you automatically generate reports about rejected trades due to risk management. It listens for these rejection events and organizes them by symbol and trading strategy.

    -

    The service then creates nicely formatted markdown tables summarizing these rejections, along with overall statistics like the total number of rejections and breakdowns by symbol and strategy.

    -

    These reports are saved as files on your disk, making it easy to review and analyze your risk management performance.

    -

    You can subscribe to receive these events, unsubscribe when you no longer need them, and clear the accumulated data when necessary.

    -

    The service also provides methods to retrieve statistical data and generate reports for specific symbol-strategy combinations and functions to save reports to disk. Each combination has its own storage, ensuring data isolation.

    -

    This service acts as a central point for managing risk-related operations within the backtest-kit framework. It handles tasks like validating risk configurations and ensuring that trading signals adhere to predefined risk limits.

    -

    The service relies on several components, including services for connecting to risk systems, validating configurations, and handling data for different exchanges and trading frames.

    -

    Key functionalities include:

    -
      -
    • Signal Validation: checkSignal and checkSignalAndReserve determine whether a trading signal is permissible based on risk rules. The latter provides a concurrent-safe way to validate and reserve resources, preventing conflicting validations.
    • -
    • Signal Management: addSignal records when a signal is executed, while removeSignal cleans up when a signal is closed.
    • -
    • Data Clearing: clear allows you to wipe out existing risk data, either globally or for a specific risk instance.
    • +
    • +

      moonbag: This strategy places your take profit point a fixed distance above or below your entry price, based on a percentage. It's a simple way to secure profits quickly.

      +
    • +
    • +

      bracket: For more control, you can use the bracket method. This allows you to define your own specific take profit and stop loss percentages, letting you tailor your risk and reward.

      +
    -

    Essentially, it’s a behind-the-scenes engine that keeps your backtesting and trading strategies operating within safe and defined boundaries.

    -

    This service acts as a central hub for managing risk checks within your trading system. It intelligently directs risk-related operations to the correct specialized risk handler, ensuring that each trading activity adheres to the appropriate risk guidelines.

    -

    It keeps track of frequently used risk handlers, storing them for quick access, which speeds up the entire trading process.

    +

    These functions take information about your position type, the current price, and the desired stop loss and take profit percentages to provide you with the appropriate price levels.

    +

    This class offers tools to reliably save and retrieve signal data, especially for backtesting and live trading scenarios. It manages storage instances in a smart way, so you don't have to recreate them repeatedly.

    +

    You can customize how the data is stored using a custom adapter, or easily switch back to the default file-based storage. It ensures that your signal data is written safely, even if unexpected interruptions occur.

    +

    Signals are stored individually as separate files, making it easier to manage and debug individual signal states.

    +

    If your working directory changes during testing, you can clear the cache to force a refresh. There's even a dummy storage option for testing purposes, where nothing is actually saved.

    +

    This component handles saving and loading trading signals to and from files, primarily designed for backtesting scenarios. It's like a digital filing cabinet for your signals, ensuring they're saved individually and safely. Each signal gets its own file, making it easy to manage and retrieve them.

    +

    The backtest property simply indicates whether this is being used for a backtest or not.

    +

    The waitForInit method prepares the underlying file storage for use.

    +

    readStorageData allows you to load all those stored signals back into your system, essentially gathering all the files and putting their contents back together.

    +

    Finally, writeStorageData takes your signals and saves them to those individual files, using a signal's ID as the filename to keep things organized. It uses a safe writing process to protect against data loss in case of interruptions.

    +

    This class helps manage how your trading strategy's data is saved and loaded, making it more resilient to unexpected interruptions. It's designed to keep track of things like the state of your orders or the progress of a backtest.

    +

    It uses a clever system to ensure each piece of data is stored in the right place, and it allows you to easily switch between different storage methods, like saving to files or simulating a no-op for testing.

    +

    You can customize how the data is saved and loaded using your own storage adapters. The class handles the complexities of safely reading and writing data, and it automatically cleans up when signals are no longer needed. The waitForInit method is helpful to control when this initial setup happens, especially if you have dependencies. Clearing the cache is important when your working directory changes.

    +

    This class provides a way to save and load trading state information to a file, ensuring that changes are written reliably. It’s designed to work with a specific trading signal and a bucket name, effectively creating a dedicated storage location for each signal.

    +

    The class handles the complexities of writing data to a file, ensuring that the process is handled safely.

    +

    You can use it to retrieve the saved state or update it with new data, such as parameters or configurations.

    +

    Importantly, when you're finished, there's no need to manually clean up resources; the system takes care of that for you.

    +

    This class helps manage how trading signals are saved and loaded, ensuring their state is reliable even if things go wrong. It automatically handles creating specialized storage areas for each strategy and trading symbol combination, preventing conflicts.

    +

    You can customize how these signals are persisted, swapping out the default storage method with your own custom solution. The system intelligently creates these storage areas the first time they're needed, so you don’t have to manage them manually.

    +

    If you need to switch to a different storage method or clear existing data, you can do so easily with dedicated functions. This utility is particularly important for strategies running in live mode, where reliable persistence is crucial.

    +

    This class helps you save and retrieve signal data for your trading strategies. It's designed to be reliable, even if your program crashes unexpectedly.

    +

    It keeps track of signals associated with a specific trading symbol, strategy name, and exchange. Think of it as a way to remember what your strategy was doing at a particular point in time.

    +

    The class uses a file to store this information, ensuring that data isn't lost.

    Here's a breakdown of what it does:

      -
    • Risk Routing: It decides which specific risk handler to use based on a given identifier (riskName), making sure the right rules are applied.
    • -
    • Caching: It remembers previously accessed risk handlers so that it doesn't have to recreate them every time they're needed.
    • -
    • Signal Validation: It carefully examines trading signals to ensure they comply with predetermined risk limits, like portfolio drawdown or position size.
    • -
    • Concurrency Safety: It has a special function (checkSignalAndReserve) to handle situations where multiple operations might happen at the same time, preventing issues and ensuring accuracy.
    • -
    • Signal Management: It allows you to record when a signal is opened and close it when it’s finished, helping to maintain accurate risk tracking.
    • -
    • Cache Clearing: You can manually clear the cached risk handlers when needed, ensuring the system stays up-to-date.
    • +
    • Initialization: waitForInit makes sure the storage is ready before you try to use it.
    • +
    • Reading Data: readSignalData fetches the saved signal data related to a specific symbol.
    • +
    • Saving Data: writeSignalData allows you to store a new signal or clear the existing one.
    -

    The service relies on several other components to operate, including services for handling schema, time data, and core actions.

    -

    The ReportWriterAdapter is designed to manage and store your trading data in a flexible way. It lets you easily switch between different storage methods, like saving to JSONL files or using other custom solutions.

    -

    The adapter intelligently keeps track of your storage instances, ensuring you only have one active instance for each type of report (like backtest results, live trading data, or walker analysis). This helps to prevent conflicts and ensures efficient data management.

    -

    You can change how data is stored by using useReportAdapter, letting you plug in your preferred storage methods. The adapter automatically creates the necessary storage when you first start writing data.

    -

    To test or temporarily disable data storage, useDummy will discard all writes. If you need to reset the adapter, clear removes existing storage instances. Returning to the standard is done with useJsonl. It’s especially useful if your project’s working directory changes during a strategy run.

    -

    ReportUtils helps you control which parts of the system are generating detailed logs, like for backtesting or live trading. Think of it as a way to turn on and off different "report services."

    -

    You can selectively enable logging for things like backtests, performance analysis, or even just a walker. When you enable a service, it begins recording events in JSONL format, which includes helpful information for analysis. It's really important to remember to unsubscribe when you’re done to prevent memory issues.

    -

    Conversely, you can disable specific logging services without affecting others, which is useful for reducing log clutter. Disabling stops the logging and frees up resources. Unlike enabling, you don't need to unsubscribe after disabling.

    -

    This utility is typically extended by ReportAdapter for more advanced features.

    -

    The ReportBase class provides a way to log trading events to JSONL files, designed specifically for backtesting and analysis. It handles writing data in a sequential, append-only fashion, making it suitable for building up a history of events. The system automatically creates the necessary directories and manages file paths.

    -

    It's built to handle large volumes of data efficiently, incorporating mechanisms to prevent write errors and ensure data isn't lost. It includes a timeout to prevent stalled writes and automatically includes metadata like the trading symbol, strategy, exchange, and timestamp with each log entry. You can use this to create reports for various aspects of your backtest, like order execution, signal generation, or portfolio performance. The initialization process only runs once, and subsequent calls are ignored, ensuring efficient setup. To write data, simply pass the event data and any optional flags – the class automatically formats the information and writes it to the designated file.

    -

    The ReportAdapter helps manage and store trading data in a structured way, like creating reports after each trade. It’s designed to be flexible, letting you easily switch between different storage methods without changing your core trading logic.

    -

    Think of it as a central hub that handles where your reports are saved. It remembers which storage method you're using to avoid creating duplicates.

    -

    By default, it saves reports as JSONL files, but you can change it to use other methods or even disable reporting altogether (using the dummy adapter). It also automatically cleans up old storage instances if your working directory changes, which is useful when running multiple trading simulations. If you need to change how reports are stored, this adapter provides a simple way to do so.

    -

    This utility class, ReflectUtils, provides a way to check on the performance of your trading strategies in real-time, whether you’re live trading or running backtests. Think of it as a tool for monitoring key metrics like profit and loss, peak performance, and how much risk you’ve taken.

    -

    It offers a variety of methods, all designed to give you a clear picture of your position's status. You can find out the unrealized profit or loss in both percentage and dollar terms. You can also track the highest profit achieved, when it was reached, and the drawdown, showing your biggest losses.

    -

    These methods also reveal how long a position has been open, how long a signal has been waiting, and other time-based metrics. They're all accessed through a single, globally available instance, making them easy to use. The backtest parameter allows you to tailor the calculations for either live or historical data. It ensures consistent data access across different environments while validating the provided context.

    -

    This component manages access to recent trading signals, allowing you to choose where those signals are stored – either persistently on disk or just in memory. Think of it as a flexible bridge between your trading strategies and your data storage.

    -

    It uses a pattern that lets you easily swap out the storage mechanism without changing your core code. You can use the default persistent storage, which saves signals to disk, or switch to an in-memory option for faster but temporary data.

    -

    The getInstance property is a smart shortcut; it builds the storage utility only once and reuses it, making things more efficient. You can force a rebuild by using the clear method, which is useful if your environment changes.

    -

    There are also convenient functions to handle incoming ping events, retrieve the most recent signals for a particular trading setup, calculate how long ago a signal was created, and most importantly, to change the storage type.

    -

    This component acts as a bridge for managing recent backtest data, letting you choose where that data is stored – either in memory or on disk. It uses a flexible design, allowing you to easily swap out the storage mechanism without changing the rest of your code.

    -

    The default behavior is to store data in memory, which is convenient for quick testing and development. However, you can easily switch to persistent storage to save your data between sessions.

    -

    You can change the storage method using useMemory and usePersist. The clear function is useful for ensuring that when your project's working directory changes, the adapter reinitializes itself correctly.

    -

    The getInstance property ensures a single, efficient access to the currently configured storage adapter. This adapter handles retrieving signals, calculating time elapsed since signal creation, and responding to ping events, all by delegating to the underlying storage implementation.

    -

    The RecentAdapter is designed to manage and provide access to the most recent trading signals, whether you're running a backtest or a live trading system. It automatically updates signal storage by listening for incoming data and ensures you always have access to the latest signal information for a specific symbol and trading context.

    -

    To prevent duplicate subscriptions, it uses a singleshot pattern.

    -

    You can enable the adapter to start monitoring signals, or disable it to stop the monitoring process; disabling is safe to do repeatedly.

    -

    Retrieving signals is simple: use getLatestSignal to find the most recent signal for a specific symbol, taking into account a time cutoff to avoid look-ahead bias.

    -

    The getMinutesSinceLatestSignalCreated function lets you determine how long ago the latest signal was generated, also using a time cutoff for look-ahead protection.

    -

    PriceMetaService helps you get the latest market prices for your trading strategies, even when you're not actively running a tick. It acts like a memory bank, storing prices for each symbol, strategy, exchange, frame, and backtest configuration.

    -

    This service keeps track of prices received from your strategies and updates them automatically. You can quickly retrieve the most recent price or wait a short time for the first price to arrive.

    -

    If you need a live price outside of a tick execution, PriceMetaService will fetch it from the exchange. To prevent outdated information, you'll want to clear the stored prices when starting a new strategy. Think of it as a way to ensure you’re always working with the right price information.

    -

    It's managed centrally and updated by other components, making it simple to integrate into your backtesting or live trading environments.

    -

    This class helps you figure out how much of an asset to buy or sell in a trade, based on different strategies. It offers a few common position sizing methods, like fixed percentage, Kelly Criterion, and ATR-based approaches.

    -

    Each method has its own formula and a little bit of built-in checking to make sure you're using it correctly. You provide things like your account balance, the price of the asset, and other relevant data, and the class calculates a suggested position size for you.

    -

    Essentially, it's a toolkit for calculating how much to risk and allocate to each trade.

    -

    Here's what's available:

    +

    This class provides tools for safely saving and loading session data, making sure your trading strategies don't lose progress even if things go wrong. It acts as a central manager for session storage, automatically handling the details of where and how data is saved.

    +

    Think of it as a smart helper that keeps track of different trading setups – like a specific strategy, exchange, and timeframe – and remembers their settings. It uses a specific file structure to organize this data.

    +

    It gives you options to customize how these sessions are saved. You can choose to use standard file storage, a dummy adapter that does nothing (useful for testing), or even plug in your own custom storage method.

    +

    You can also instruct it to set up the storage initially or skip the setup if it's already done.

    +

    If you need to clean things up, you can tell it to clear its memory or to remove a specific session’s saved data. This is particularly important if your trading environment changes.

    +

    This class provides a way to save and load session data persistently, specifically designed to work with backtest-kit strategies and exchanges. It acts as a bridge between your trading logic and the file system, ensuring your session information is reliably stored.

    +

    Essentially, it uses the strategy and exchange names, along with a unique identifier called frameName, to organize and locate your session data within files.

    +

    The waitForInit method ensures the underlying storage is ready before you try to save anything. readSessionData retrieves your saved session information using the frameName, and writeSessionData saves new data, again referencing the frameName. Finally, dispose doesn’t actually do anything itself; it relies on a separate utility function to handle clearing out any cached information.

    +

    Think of it as a convenient container for keeping track of your session details so they’re not lost when the backtest ends.

    +

    This class helps manage how scheduled trading signals are saved and loaded, particularly for strategies that need to remember their plans across sessions. It ensures that each strategy working with a specific trading symbol, on a particular exchange, uses its own dedicated storage for these signals.

    +

    The system automatically creates and manages these storage instances, so you usually don't need to worry about the technical details. It's designed to be reliable, even if the system crashes, and allows for custom storage solutions if you need something beyond the defaults.

    +

    You can easily switch between different ways of persisting these signals, such as using a standard file-based storage or even a dummy storage for testing purposes. If you’re using a custom storage option, this utility handles remembering which storage is active for each strategy.

    +

    The readScheduleData method retrieves a saved signal, while writeScheduleData updates it. These functions work together to keep your scheduled signals safe and accessible.

    +

    This class, PersistScheduleInstance, provides a way to reliably save and load scheduled signals for your trading strategies. It's designed to be a concrete implementation of a more general interface, IPersistScheduleInstance.

    +

    Think of it as managing data related to a specific trading symbol, strategy, and exchange. It uses files to store this data, ensuring that it’s kept safely. The class handles the technical details of writing data to files in a way that prevents data loss, even if your program crashes unexpectedly.

    +

    Here's a breakdown of what it does:

      -
    • fixedPercentage: Determines position size by risking a fixed percentage of your account balance.
    • -
    • kellyCriterion: Calculates position size based on win rate and win/loss ratio, aiming to optimize growth.
    • -
    • atrBased: Uses the Average True Range (ATR) to determine position size, reflecting market volatility.
    • +
    • It stores the trading symbol, strategy name, and exchange name it’s working with.
    • +
    • It initializes the storage mechanism, preparing it to hold data.
    • +
    • It reads existing scheduled signal data from a file, based on the trading symbol. If there's no data, it returns null.
    • +
    • It writes new scheduled signal data (or clears existing data) to a file, again using the trading symbol to identify the correct location.
    -

    The Position class provides helpful tools for determining take profit and stop loss prices when you're trading. It’s designed to make setting these levels straightforward, automatically adjusting them based on whether you're holding a long or short position.

    -

    There are two main functions available:

    +

    This class helps manage how your trading positions are saved and retrieved, especially when dealing with different risk profiles. It keeps track of active positions and makes sure that information is stored consistently and safely.

    +

    The system remembers which storage method to use for each risk profile, allowing you to easily switch between different ways of persisting data. It creates storage instances on demand, only when they're needed.

    +

    You can customize how data is stored by providing your own storage constructors, essentially swapping out the default storage with something tailored to your needs.

    +

    If you need to reset the system, like when your working directory changes, you can clear the cached storage instances to ensure fresh data. There’s also a convenient way to switch back to the default file-based storage or even a dummy storage for testing purposes where no actual persistence happens.

    +

    The readPositionData method retrieves the saved active positions at a specific time, while writePositionData saves the current positions. Both functions work together to ensure the persistence of your positions.

    +

    This component handles persistently storing position data for risk management, focusing on reliability and safety. It's designed to work alongside other parts of the backtest-kit framework.

    +

    It utilizes a file-based system for storing this data, ensuring that changes are written securely and consistently. Think of it as a dedicated place to save and retrieve your risk-related information.

    +

    The PersistRiskInstance uses a predefined identifier ("positions") for all data, simplifying management and guaranteeing uniformity.

    +

    You can kickstart the storage process using waitForInit, which sets up the underlying file system. readPositionData lets you load previously saved data, while writePositionData is used to update and save the current state. These functions use a fixed key, ensuring the data is always stored in the expected location.

    +

    This utility class helps manage how recent trading signals are saved and loaded, ensuring that information persists even if there are issues. It's designed to be used in backtesting and live trading scenarios, and it automatically handles storing data based on the specific symbol, strategy, exchange, and timeframe you're working with.

    +

    The class remembers which storage method to use – you can plug in your own custom storage, use a default file-based storage, or even use a dummy storage for testing. It makes sure the reading and writing of these signals happens safely, even if the system crashes, and uses a clever system to avoid creating unnecessary storage instances. If you need to switch to a new storage mechanism, you can easily do so, and the class will automatically update its behavior. Finally, you can clear the stored information when needed, for instance, when the working directory changes.

    +

    This class helps you save and retrieve the most recent trading signal data for a specific strategy and market.

    +

    It’s designed to work with file storage, making sure the data is saved reliably.

    +

    Think of it as a way to remember the last known signal for your trading system.

    +

    The class stores details like the trading symbol, strategy name, exchange, frame name, and whether it's a backtest or live run.

    +

    It manages a file-based storage system, organizing data based on this information to keep things separate and organized.

    +

    You can use the readRecentData method to get the last saved signal and writeRecentData to update it whenever a new signal occurs. The waitForInit method makes sure the storage is ready before you start reading or writing data.

    +

    This class helps manage and safely store the partial profit and loss information for your trading strategies. It's designed to make sure this data doesn't get lost, even if there are unexpected interruptions.

    +

    It smartly creates storage containers for each combination of trading symbol, strategy name, and exchange. These containers ensure that data is stored and retrieved reliably.

    +

    You can customize how this data is stored using different adapters, or simply use the default file-based system. There's also a "dummy" mode for testing where no data is actually saved.

    +

    The readPartialData and writePartialData methods allow you to retrieve and save partial data, respectively, and they work together to ensure data integrity. If you change the working directory of your strategy, you'll need to clear the internal cache to keep things running smoothly.

    +

    This class, PersistPartialInstance, helps you reliably store and retrieve pieces of data related to your trading strategies. It's designed to work with files, ensuring that your data isn't lost even if something unexpected happens during the process.

    +

    Think of it as a safe keeper for partial information about your strategies, identifying each piece of data by a unique signal ID. It's specifically built to handle scenarios where you're working with strategies that run across different exchanges and need to be identified.

    +

    The class takes the symbol, strategy name, and exchange name as input during creation to clearly identify what data it manages. Internally, it utilizes a file-based storage system to ensure data persistence, and it handles file writes in a way that minimizes the risk of data corruption. The waitForInit method ensures the storage is properly set up before you start writing data, and readPartialData and writePartialData methods allow you to access and update those pieces of data.

    +

    This class helps manage how notification data is saved and retrieved, particularly for backtesting and live trading environments. It provides a way to handle the storage of notifications, ensuring that each notification is treated as a separate, identifiable file.

    +

    It uses a clever system of memoization, meaning it creates and reuses storage instances to avoid unnecessary work. You can even swap out the storage method to use your own custom solution, a JSON-based system, or a dummy implementation for testing.

    +

    The readNotificationData and writeNotificationData methods handle the actual loading and saving of notification information, and they only create the necessary storage when they're first needed.

    +

    The clear method is important to use when your working directory changes – it refreshes the storage instances to ensure they're using the correct path.

    +

    This component handles saving and retrieving notification data, particularly useful for persisting information across backtesting sessions. It acts as a bridge between your trading logic and a file system, ensuring that notification details aren't lost. Think of it as a reliable way to keep track of important events.

    +

    It stores each notification as its own JSON file, making it easy to manage and locate individual entries. The system is designed to be resilient to crashes, thanks to its atomic write operations.

    +

    You can initialize the storage, read all the saved notifications, and write new notifications—all with straightforward methods. The backtest property determines the storage mode, and the underlying storage mechanism is managed internally.

    +

    This class helps manage and persist data related to memory entries, ensuring that information isn't lost even if the application crashes. It intelligently caches these memory instances, creating a new one only when needed for a specific signal and bucket combination.

    +

    You can customize how these memory instances are created using a custom adapter, or stick with the default file-based or dummy options for testing. The class provides methods for reading, writing, deleting, and checking for the existence of these memory entries.

    +

    It also allows you to clear the cache when needed, like when the working directory changes, and offers a way to clean up storage associated with signals that are no longer used. A key feature is the ability to iterate through all memory entries to rebuild indexes, and to easily switch between different persistence strategies.

    +

    This class provides a way to persistently store and retrieve memory data to files. It's designed to work with the IPersistMemoryInstance interface, acting as the default file-based implementation.

    +

    It handles saving data to a file, ensuring that updates happen reliably.

    +

    Data can be "soft-deleted" by marking entries as removed, which allows for easy recovery if needed. When listing memory data, only the active, non-removed entries are shown.

    +

    The waitForInit method sets up the underlying storage. You can read individual memory entries using their ID, and hasMemoryData lets you quickly check if a particular entry exists. To update data, use writeMemoryData, and to remove data, use removeMemoryData (which performs a soft delete). Finally, dispose does nothing on its own because the memo cache is managed separately.

    +

    This class, PersistMeasureUtils, helps manage cached data from external APIs, specifically for trading strategies. It provides a way to store and retrieve API responses persistently, ensuring that the same data isn't repeatedly fetched.

    +

    It uses a clever system where each cache bucket (identified by a timestamp and symbol) gets its own dedicated storage instance. You can even customize how these storage instances are created using adapters.

    +

    The class handles reading, writing, and deleting cached data reliably, and it's designed to be safe even if the system crashes. The first time data is accessed for a given bucket, it automatically sets up the storage.

    +

    You can easily swap out the default caching mechanism for alternatives like using a dummy adapter for testing purposes or a custom file-based solution. The clear method helps when the underlying storage location changes.

    +

    This class helps you save and retrieve trading measure data to a file, ensuring your data is handled reliably. It acts as a layer on top of the file storage, making sure writes happen completely or not at all, preventing corrupted data.

    +

    You can mark entries as deleted without actually removing the file – this is called soft deletion and helps with data recovery if needed. When you list your data, the system automatically filters out any entries marked as deleted.

    +

    The waitForInit method ensures the underlying storage is ready before you try to work with it. The readMeasureData method retrieves a specific data entry; if the entry doesn’t exist or is marked as deleted, it returns nothing. writeMeasureData saves a new entry, and removeMeasureData flags an entry for deletion. Lastly, listMeasureData provides a way to see a list of all existing (not deleted) entries.

    +

    This class helps manage how log data is saved and retrieved. It uses a single, persistent log instance that’s created only when needed. You can customize how logs are stored by providing your own log instance creator, essentially swapping out the default behavior.

    +

    The class reads and writes log entries, ensuring data is saved in a way that's safe even if the application crashes. Each log entry is stored as its own file, making updates and retrieval more manageable.

    +

    It also offers quick ways to reset the log instance or switch to a dummy implementation for testing purposes. Changing directories, like when running different strategies, should prompt you to clear the existing log.

    +

    This component helps manage and store your backtesting logs to disk, ensuring data persistence even if your program crashes. It acts as a central place to keep track of your trading history and decisions.

    +

    Think of it as a special file that records each log entry as a separate JSON file, using a unique ID to identify each one.

    +

    The system is designed to be safe; once a log is written, it cannot be changed. When you read the logs, it systematically looks at all available files.

    +

    This implementation provides a simple and reliable way to keep your backtesting results secure and accessible.

    +

    This component handles tracking which intervals have already "fired" or been processed. It keeps records in a specific directory structure under ./dump/data/interval/ to indicate whether an interval has already run for a given combination of a "bucket" and a "key."

    +

    You can customize how these records are stored and managed by providing your own constructors. This lets you use different persistence methods like file-based storage or even a dummy implementation for testing purposes.

    +

    The system lazily loads and initializes data for each bucket as needed, meaning it only loads the information it needs when it needs it. You can retrieve, write, and delete these interval markers using provided functions. The listIntervalData function allows you to see all the non-deleted markers associated with a specific bucket. Finally, if your working directory changes during a backtest, you'll need to clear the internal cache to ensure accurate operation.

    +

    This class helps you reliably store and retrieve data related to specific time intervals, like when a trading strategy should execute. It's designed to work with files to keep everything persistent.

    +

    The bucket property defines where this data is stored. The system uses an internal storage mechanism (_storage) for the actual file operations.

    +

    You can use waitForInit to make sure the storage is ready before you start using it.

    +

    readIntervalData lets you get a specific interval marker, and it handles cases where the marker is missing or has been "soft deleted" by returning null.

    +

    writeIntervalData saves a new interval marker.

    +

    If you need to temporarily disable an interval, removeIntervalData marks it as soft-deleted – it doesn't physically delete the file, but the system treats it as if it’s gone.

    +

    Finally, listIntervalData provides a way to go through all the active interval markers in the bucket, ignoring the ones that have been soft-deleted.

    +

    This class helps manage how candle data (like open, high, low, close prices) is stored and retrieved from files. Think of it as a system for keeping a local, cached copy of your trading data.

    +

    Each candle is saved as a separate file, making organization easier. The system checks if the cached data is still valid before using it, and it automatically updates the cache if data is missing. The reading and writing of these files happen in a way that prevents data corruption.

    +

    You can customize how the data is stored by swapping out the underlying storage mechanism – for example, using a different type of file storage or even using a dummy instance for testing.

    +

    The class also has a clear function to wipe out the current storage, which is handy if you're restarting your application or moving to a different working directory. Finally, it provides methods for switching back to the default file-based storage or using a dummy storage for testing purposes.

    +

    This class helps you save and retrieve historical candle data, like open, high, low, and close prices, for a specific trading symbol and time interval. It stores each candle's information as a separate file, making it easy to manage and access.

    +

    Think of it as a simple database for your historical price data.

    +

    It's designed to be persistent, meaning your data isn't lost when your application restarts.

    +

    Here’s a breakdown of how it works:

      -
    • -

      moonbag: This calculates take profit and stop loss levels based on a "moonbag" strategy, which means your take profit is a fixed percentage above (for long positions) or below (for short positions) your entry price.

      -
    • -
    • -

      bracket: This allows for more customization, letting you define your own specific percentages for both the take profit and stop loss levels.

      -
    • +
    • Initialization: It needs to be initialized before you can read or write any data.
    • +
    • Reading Data: When you request candles, it checks if they’re available. If a candle is missing, it will treat this as a chance to refresh it. If a candle is found but is invalid, a warning is raised and it's treated as a miss.
    • +
    • Writing Data: It only saves complete candles (those with a closing time in the past) and avoids overwriting existing data, ensuring a historical record. This means the cache is always in order and append-only.
    • +
    • Underlying Storage: This class manages the details of saving data to files.
    • +
    • waitForInit: Used to make sure the underlying storage is ready.
    • +
    • readCandlesData: Fetches a range of candles from the saved data.
    • +
    • writeCandlesData: Saves a set of candles to the file storage.
    -

    Both functions take information about your position type, current price, and percentage levels to determine the appropriate take profit and stop loss prices.

    -

    This class helps manage how signal data is saved and loaded persistently, ensuring your backtest and live trading sessions can remember their state. It's designed to be reliable and efficient, automatically handling the creation of storage instances based on the trading mode (backtest or live).

    -

    The class keeps track of storage instances and provides functions to read and write signal data, allowing you to easily retrieve previously stored signals. You can even customize how the data is stored by providing your own storage adapter.

    -

    When working with trading strategies, especially those running for extended periods, this utility ensures that signal states are preserved even if the process restarts.

    -

    Here's a breakdown of what it offers:

    +

    This class helps manage and save breakeven data, ensuring it's reliably stored for your trading strategies. It's designed to work with different strategies and symbols, keeping track of the breakeven points for each.

    +

    Essentially, it handles the behind-the-scenes process of reading and writing this data to files, so you don't have to. The system uses a smart caching mechanism, creating a storage instance only when needed and reusing it for the same symbol and strategy combination.

    +

    You can even customize how the data is stored, either by using the default file-based approach or opting for a dummy instance that doesn't actually save anything - useful for testing. If you’re switching environments or need to refresh the stored data, you can clear the cache. This class takes care of safely saving and retrieving the breakeven information, making it a handy tool for keeping track of your trading progress.

    +

    This class provides a way to store and retrieve breakeven data persistently, using files for storage. It's designed to be reliable, even if your program crashes unexpectedly.

    +

    The class is built to work with a specific trading symbol, strategy name, and exchange name, essentially creating a dedicated storage space for that combination. It uses a unique identifier (signalId) to pinpoint each individual piece of breakeven data.

    +

    Initialization is handled by waitForInit, which sets up the underlying storage. You can then use readBreakevenData to fetch stored data or writeBreakevenData to save new or updated information. This helps in keeping track of breakeven points over time, allowing for analysis and adjustments to your trading strategies.

    +

    This class provides a foundation for storing and retrieving data to files in a reliable way. It handles file operations safely, ensuring that writes are completed fully and that corrupted files are detected and cleaned up. The class manages a base directory where your data files are stored and keeps track of the type of data being persisted.

    +

    It offers methods to read, write, and check for the existence of data, all while dealing with potential issues like file corruption or deletion failures. You can easily get a list of all the data identifiers (IDs) being managed. The initialization process validates existing files and sets up the directory, and this only happens once. The file paths are constructed automatically based on the entity ID.

    +

    This service helps you keep track of how long different parts of your trading strategy take to run. It essentially acts as a performance monitor.

    +

    It listens for timing signals emitted during your strategy's execution and records them, allowing you to identify potential bottlenecks and areas for optimization.

    +

    You can think of it as a way to profile your strategy's performance.

    +

    To start monitoring, you subscribe to the performance events. This returns a function you can call later to stop the monitoring.

    +

    If you don't need to monitor performance anymore, you can unsubscribe to ensure you aren’t accumulating unnecessary data. The service handles ensuring only one subscription exists at a time.

    +

    The PerformanceMarkdownService helps you understand how your trading strategies are performing. It listens for performance data and keeps track of key metrics for each strategy you're using.

    +

    It automatically calculates statistics like average, minimum, and maximum values, providing a comprehensive overview. You can request a report that's formatted in Markdown, making it easy to read and share.

    +

    This service also analyzes potential bottlenecks in your strategies, and it can save these reports directly to your disk. It manages storage for each strategy to keep data organized and separate. You can subscribe to receive performance updates, and unsubscribe when you no longer need them. Finally, it allows you to clear the accumulated data if you want to start fresh.

    +

    The Performance class helps you understand how well your trading strategies are performing. It offers tools to collect and analyze performance data, allowing you to pinpoint areas for improvement.

    +

    You can retrieve detailed performance statistics for specific strategies and symbols, including counts, durations, averages, and percentiles. This data helps identify which parts of your strategy are taking the most time and exhibiting the most volatility.

    +

    It also lets you generate easy-to-read markdown reports that visually represent your performance metrics, making it simple to share results or document progress.

    +

    Finally, you can save these performance reports directly to your file system for later review, with a sensible default location.

    +

    This utility class helps you analyze and understand your partial profit and loss data, particularly useful when backtesting or evaluating trading strategies. It provides easy ways to get aggregated statistics and generate detailed reports of your partial profits and losses.

    +

    You can retrieve summarized data like total profit/loss event counts for a specific symbol and strategy.

    +

    It also allows you to create markdown reports that clearly show all the partial profit and loss events, neatly organized into a table with details such as action type, symbol, strategy, price, and timestamp.

    +

    Finally, you can easily save these reports to files, automatically creating the necessary directory structure if it doesn't already exist, so you can share or preserve your analysis.

    +

    The PartialReportService helps you keep track of when your trading positions are partially closed, either with a profit or a loss. It listens for signals indicating these partial exits and saves details like the price and level at which they occurred into a database.

    +

    Think of it as a meticulous record-keeper for your trading activity, specifically focused on those moments when you're not fully exiting a position.

    +

    You can tell it to start listening for these events using the subscribe method, which will return a function you can call to stop listening (unsubscribe). It’s designed to prevent accidentally subscribing multiple times, ensuring your system doesn't get overwhelmed. If you're using a logging service, you can also set that up through the loggerService property.

    +

    The PartialMarkdownService helps you track and report on your trading performance, specifically focusing on profits and losses. It listens for profit and loss events happening during your backtests or live trading and keeps a record of them for each symbol and strategy you're using.

    +

    It automatically organizes these events and generates clear, readable markdown reports that you can save to your computer. These reports provide detailed information about each profit and loss event, along with overall statistics.

    +

    You can subscribe the service to receive these events, and when you're finished, you can unsubscribe. The dump function lets you save those reports as files, making it easy to review your progress and identify areas for improvement. It’s designed to keep data isolated for each combination of symbol, strategy, exchange, timeframe, and backtest to ensure accuracy and organization. The clear function offers a way to reset the accumulated data when necessary.

    +

    This service acts as a central hub for managing partial profit and loss tracking within the system. Think of it as a gatekeeper that sits between your trading strategy and the underlying connection layer.

    +

    It keeps a record of all partial operations, like profits and losses, and provides a convenient place to log and monitor these activities. The service receives information from your strategy and passes it along to another component (PartialConnectionService) for the actual handling.

    +

    It’s injected into your trading strategy to ensure consistent management of partials. You won't directly interact with this service; it handles the details behind the scenes.

    +

    Key features include validation of your strategy and its associated configurations, and it uses caching to make sure validations aren't repeated unnecessarily. The profit, loss, and clear functions are the primary methods used to track and reset partial states, all while maintaining a log of what's happening.

    +

    The PartialConnectionService manages how your trading system tracks profit and loss for individual signals. It's designed to efficiently handle a potentially large number of signals without consuming excessive resources.

    +

    Think of it as a smart factory that creates and manages "ClientPartial" objects, each responsible for tracking the P&L of a specific signal. It remembers these ClientPartial objects so it doesn’t need to recreate them every time, using a technique called memoization.

    +

    When a signal reaches a profit or loss threshold, this service handles the process: it either finds an existing ClientPartial or creates one, updates its state, and then alerts other parts of the system via event emissions. When a signal is closed out, this service cleans up the associated ClientPartial, ensuring nothing is left behind.

    +

    The service is injected into the core trading strategy to integrate with its functionality, and it utilizes other services for logging and managing actions within the trading environment. It makes sure things like profit calculations and clearing of positions are handled consistently for each signal.

    +

    This component manages notifications related to your trading strategies. It's designed to be flexible, allowing you to easily swap out how notifications are handled, whether that's in memory, persistently to disk, or even as dummy notifications for testing.

    +

    The NotificationLiveAdapter acts as a central point for all notification events, like signal changes, profit/loss updates, and errors. It forwards these events to the currently configured notification backend.

    +

    You can quickly change the backend by using convenience methods like useDummy, useMemory, or usePersist. useMemory is the default, keeping notifications in the program's memory. usePersist saves them to a file, while useDummy effectively silences all notifications.

    +

    The getInstance property holds the currently active notification handler and it is created only once and cached for efficiency, but can be reset if the underlying environment changes (like when the working directory changes during a backtest).

    +

    The handleSignal, handlePartialProfit, handleRisk, and similar methods are the entry points for triggering notifications, and they simply pass the event data to the current notification backend. The getData method retrieves the stored notifications, while dispose clears them.

    +

    Finally, useNotificationAdapter lets you provide your own custom notification handler. The clear method forces a recreation of the notification handling instance, which is particularly useful when the environment changes.

    +

    This service helps manage and send out notifications about important signals within the trading framework. It's like a central hub for ensuring that notifications are accurate and consistent.

    +

    It validates the strategy, exchange, frame, risk, and action configurations to make sure everything is set up correctly, and it cleverly remembers these validations so it doesn't have to repeat the work unnecessarily.

    +

    If you're working with onActivePing callbacks, you’ll use commitSignalNotify to actually trigger and send these notifications, bundling in details like the symbol, price, and relevant context. Think of it as the button you press to send out a signal notification after validating everything is in order. The service handles the rest, ensuring the notification reaches the right places.

    +

    This component helps you manage and send notifications during backtests, offering a flexible way to log important events. It acts as a central hub for various notification types like trade signals, profits, losses, and errors.

    +

    You can easily swap out different notification methods – it comes with built-in options for in-memory storage, persisting notifications to disk, or simply discarding them (a dummy option for testing). The useMemory(), usePersist(), and useDummy() functions make switching between these methods straightforward.

    +

    The handleSignal(), handlePartialProfit(), and similar functions are the entry points for various events, relaying them to the currently selected notification method. getData() retrieves all stored notifications, while dispose() clears them. If you need to use a custom notification method, the useNotificationAdapter() function lets you provide your own notification implementation. The clear() function is particularly useful when the working directory changes during a backtest.

    +

    The NotificationAdapter is the central hub for managing and accessing notifications, whether you're running a backtest or a live trading session. It automatically keeps track of notifications by listening for signals emitted by the trading system.

    +

    This adapter ensures that you don't accidentally subscribe to the same signals multiple times, preventing unnecessary data duplication. It's designed to be easy to use – you can enable it to start receiving notifications, disable it to stop, and retrieve all the stored notifications for either backtest or live data. Finally, when you're finished, the dispose function cleans up and removes all stored notifications.

    +

    This component acts as a central hub for managing your trading memory, allowing you to easily switch between different storage methods. It's designed to be flexible, letting you choose how your data is stored—whether it's in memory, persistently on your file system, or even discarded entirely for testing purposes.

    +

    You can quickly change the storage backend using convenient functions like useLocal, usePersist (the default, which saves data to files), useDummy, and useMemoryAdapter to integrate custom storage solutions. The adapter keeps things organized by memoizing instances based on signal and bucket combinations, and you can clear these memoized instances with disposeSignal when signals are closed, or clear to refresh everything when your working directory changes.

    +

    The framework provides methods for writing, reading, searching, listing, and deleting memory entries, all structured around signal IDs and bucket names. You'll use writeMemory to save data, readMemory to retrieve it, searchMemory to find specific entries using full-text search, listMemory to view all entries, and removeMemory to delete entries.

    +

    This adapter provides a flexible way to manage memory storage for your backtests. Think of it as a central point for how your backtest remembers and retrieves data.

    +

    It offers different storage options, like keeping everything in memory for speed, persisting data to files, or even using a dummy adapter to just discard data for testing. You can easily switch between these options with simple commands like useLocal, usePersist, or useDummy.

    +

    It intelligently caches data based on signal IDs and bucket names, which helps optimize performance. If you need to clear out old cached data, you can use disposeSignal.

    +

    There are methods for writing, searching, listing, removing, and reading data from memory, giving you full control over how your backtest interacts with stored information. For more complex setups, it also allows you to provide your own custom memory adapter implementations. The clear function is useful when the base path for file storage changes.

    +

    This component, the MemoryAdapter, acts as a central hub for managing how your backtesting and live trading environments store and retrieve data. It intelligently directs memory-related operations – writing, searching, listing, removing, and reading – to either the backtest or live memory system depending on the context.

    +

    To ensure efficient and clean operation, it automatically subscribes to signal lifecycle events to automatically clean up old data. This subscription happens only once, preventing unnecessary overhead.

    +

    You can control the adapter's activity by enabling or disabling it, which manages those lifecycle subscriptions. It's safe to disable it multiple times without any issues.

    +

    The adapter provides methods for writing data to memory, searching through existing data using a powerful full-text search, listing all entries, removing specific entries, and reading individual entries. All these functions are aware of whether they're working within a backtest or live trading scenario, routing the request to the appropriate system.

    +

    This class helps you analyze and understand the maximum drawdown experienced during trading simulations or live trading. It acts as a central place to gather information about those periods of significant loss.

    +

    You can think of it as a tool to create reports and get statistics about the worst performance of a trading strategy on a specific asset.

    +

    Specifically, it offers a few key functions:

      -
    • Flexible Storage: You can use the default file-based storage, a dummy storage for testing, or plug in your own custom storage solution.
    • -
    • Efficient Management: It automatically creates storage instances for backtest and live modes.
    • -
    • Data Persistence: Read and write signal data easily to save and load states.
    • -
    • Customization: Adapt the storage behavior to your specific needs.
    • -
    • Clean Up: It allows you to clear the storage cache when necessary, such as when the working directory changes.
    • +
    • getData: This gets a summary of max drawdown statistics, including things like the largest drawdown and when it occurred. You specify the asset, the trading strategy and context to get the data.
    • +
    • getReport: This function generates a detailed report in markdown format, listing all the maximum drawdown events. You can choose which data points (columns) to include in the report.
    • +
    • dump: Similar to getReport, this creates a markdown report but saves it directly to a file on your computer instead of displaying it in the console. Again, you can control what information appears in the report.
    -

    This class provides a way to store and retrieve trading signals persistently, using files on your computer. It's designed to be reliable, even if your system crashes during operations.

    -

    Each signal is saved as its own JSON file, making it easy to manage and understand how your data is organized. When you need to load all signals, it reads through a list of file names.

    -

    The backtest property simply indicates whether the storage is for backtesting purposes. The _storage property handles the actual file operations behind the scenes.

    -

    The waitForInit method ensures that the storage is ready before you start working with it.

    -

    You can use readStorageData to get all the saved signals at once and writeStorageData to update or add new signals to the storage. This framework makes it relatively simple to keep track of your trading data across sessions.

    -

    This class helps manage how your trading strategy’s data is saved and loaded, making it more reliable. It automatically handles creating storage locations for your strategy's state based on signal IDs and bucket names.

    -

    It lets you customize how this storage works, for example, by using a different type of storage or simulating persistence for testing. You can easily switch between using a real file-based storage system or a dummy one that doesn’t actually save anything.

    -

    If your application's working directory changes, you'll need to clear the internal cache to ensure everything is reloaded correctly. It also offers methods to clean up storage after a signal is no longer needed, and you can initialize the storage when needed, skipping initialization if a setup is already done. This class makes sure the data is written and read safely.

    -

    This class provides a way to save and load the state of your trading strategies persistently, using files. It’s designed to work specifically with a signal and a bucket name, which essentially acts as a unique identifier for where the data is stored.

    -

    The signalId and bucketName properties identify the data being managed.

    -

    Initialization happens through waitForInit, and then you can retrieve previously saved state with readStateData or store new state with writeStateData. The writeStateData method ensures that writes are handled safely, preventing data loss.

    -

    Importantly, dispose doesn’t do anything on its own, because the cleanup of any temporary cached data is managed elsewhere.

    -

    This utility class helps manage how signal data is saved and retrieved, particularly for trading strategies. It ensures each strategy gets its own dedicated storage space for signals, making things organized and reliable.

    -

    You can customize how these signals are stored by providing your own storage adapter, or use the built-in options like a file-based system or a dummy adapter for testing.

    -

    The class automatically handles reading and writing signal data, creating the necessary storage if it doesn't already exist. It also manages these operations safely, even in case of unexpected issues.

    -

    If your trading environment changes – for example, if the current working directory shifts – you can clear the storage cache to ensure everything stays consistent.

    -

    This class helps you reliably store and retrieve signal data, specifically designed for trading strategies. It's like a safe keeper for your signal information.

    -

    It combines file storage with a focus on safety, ensuring your data isn't lost even if something unexpected happens. Each signal is identified by a unique combination of the symbol, strategy name, and exchange name.

    -

    The constructor needs the symbol, strategy name, and exchange name to set up the storage location.

    -

    You can use waitForInit to make sure the storage is ready before you start writing data.

    -

    readSignalData lets you fetch the signal data associated with a specific symbol.

    -

    writeSignalData is how you save or clear the signal data, ensuring it's written securely.

    -

    This class provides tools for reliably saving and loading session data during backtesting. Think of it as a way to keep track of important information like order books or account balances between different parts of your backtest.

    -

    It manages these data snapshots and automatically handles where they're stored, usually in files within a specific directory structure.

    -

    You can even customize how this data is stored if you want, or temporarily disable persistence for testing.

    -

    The class keeps track of these storage locations and ensures that the correct one is used for each strategy, exchange, and time frame.

    -

    If you're switching strategies or environments, you might need to clear the cached data to ensure everything is fresh. You can also manually delete the data for a specific session when it's no longer needed.

    -

    This component helps keep track of your trading sessions by saving important data to a file. It’s designed to work specifically with a strategy and exchange pair, identifying each session using a unique frame name. Think of it as a dedicated container for storing information related to a single run of your trading logic.

    -

    It automatically handles saving session data to disk and retrieving it later. The waitForInit method ensures the storage is ready to use before anything else happens.

    -

    When you're finished, the dispose method doesn’t do anything directly—instead, it relies on a separate utility function to clean up any associated memory. This persistent storage provides a way to resume sessions or analyze performance over time.

    -

    This utility class helps manage how scheduled trading signals are saved and loaded, ensuring they are reliable even if there are unexpected interruptions. It keeps track of these signals for each strategy and symbol combination, using a system that remembers which storage method is currently active.

    -

    The class intelligently creates storage instances, allowing you to easily swap out different storage methods (like using a file, a dummy system for testing, or a custom solution).

    -

    You can read existing signals from storage using readScheduleData and save updated signals (or clear them entirely) with writeScheduleData. The first time you access or modify a signal for a particular combination, it automatically sets up the necessary storage.

    -

    If you want to customize the storage mechanism, you can specify a custom constructor with usePersistScheduleAdapter. There are also convenient shortcuts like useJson to use the standard file-based storage or useDummy to create a non-persistent storage for testing purposes. The clear function can be used to refresh the storage if something changes in your environment.

    -

    This class provides a way to save and load schedule data, like signals, to a file. It's designed to be reliable, even if your program crashes unexpectedly.

    -

    Each instance of this class is linked to a specific trading symbol, strategy name, and exchange name, which helps organize the data.

    -

    It uses a file to store the data, making it persistent across program restarts.

    -

    You can use it to retrieve existing schedule data or to save new data, essentially acting as a bridge between your code and the file system. The waitForInit method makes sure the storage is ready before you try to read or write anything.

    -

    This class, PersistRiskUtils, helps manage and save information about active trading positions, making sure that data is handled safely and consistently. It acts as a central hub for storing and retrieving these position details, specifically designed to work with different risk profiles.

    -

    It efficiently creates and manages storage instances, remembering previously created ones to avoid unnecessary work. You can even customize how these instances are created by swapping out the default with your own code.

    -

    The core functions, readPositionData and writePositionData, allow you to fetch and save active positions, and they ensure this process is handled carefully and safely.

    -

    If you need to switch how this data is persisted, like using a different file format or a testing mode where nothing is actually saved, usePersistRiskAdapter, useJson, and useDummy provide easy ways to do so. The clear method is available to refresh the cached data when the environment changes, ensuring everything is up-to-date.

    -

    This class helps you save and retrieve position data persistently, like keeping track of your trades even when your application restarts. It's designed to be reliable, using safe writing methods to prevent data loss in case of unexpected crashes.

    -

    Think of it as a way to store your trading positions in a file, and this class handles all the complex details of reading and writing that data.

    -

    It's tied to a specific risk name and exchange name, organizing data in a structured way.

    -

    The waitForInit method prepares the storage for use. readPositionData lets you retrieve saved positions at a specific time. Finally, writePositionData stores new or updated position information.

    -

    This class helps manage how recent trading signals are saved and retrieved, especially in backtesting and live trading environments. It ensures that the same storage mechanism is used for signals related to a specific trading symbol, strategy, exchange, and timeframe, avoiding inconsistencies.

    -

    The system uses a clever memoization technique, so it only creates one storage instance for each unique combination of these factors.

    -

    You can even customize how these signals are stored by providing your own storage adapter. This lets you experiment with different storage solutions or integrate with existing data management systems.

    -

    The class handles the details of reading and writing signals safely, so you don't have to worry about data corruption. It also provides tools to refresh the storage mechanism, like when the program's working directory changes.

    -

    There are also convenient shortcuts to switch between default storage methods, such as using a file-based system or a dummy instance for testing purposes. Essentially, it makes managing recent signals reliable and adaptable for various use cases.

    -

    This class helps you save and load the most recent trading signal data for a specific trading strategy. It uses a file to store this information, ensuring it's kept reliably.

    -

    The class identifies data by combining the trading symbol, strategy name, exchange, frame name, and whether the test is a backtest or live run – making sure each context has its own isolated storage.

    -

    You can use waitForInit to make sure the storage is ready, and readRecentData to get the last saved signal. writeRecentData is how you save a new signal, associating it with a specific timestamp. Essentially, it's a convenient way to keep track of the last signal your strategy generated.

    -

    This class helps manage and save partial profit and loss information, particularly useful for keeping track of progress during trading. It ensures that this data is saved correctly and reliably, even if there are unexpected interruptions.

    -

    It automatically creates storage areas for each trading symbol and strategy, preventing data from different setups from mixing together.

    -

    You can customize how this data is stored by providing your own storage mechanisms.

    -

    The class handles reading and writing partial data, and it sets up the system so that the storage is initialized automatically the first time it's needed.

    -

    If you need to change how the data is saved (like switching to a different storage format or using a testing mode), you can easily configure it. Clearing the stored data is available, this is important when you restart your application.

    -

    This class helps you save and retrieve incomplete trading data to a file, ensuring data integrity even if something goes wrong. It's designed to work with a specific trading symbol, strategy, and exchange, keeping data organized.

    -

    It manages the underlying file storage automatically and uses a unique identifier for each piece of data.

    -

    The waitForInit method makes sure the storage is ready before you try to use it.

    -

    You use readPartialData to get the data you’ve previously saved, and writePartialData to save new or updated information, always linked to a specific signal. This is useful for scenarios where you might need to pause a process and resume it later without losing any progress.

    -

    This utility class helps manage how notification data is saved and loaded, ensuring it's handled reliably. It keeps track of different storage methods, allowing you to choose between default file-based storage, a custom adapter you provide, or even a dummy storage that doesn’t actually save anything.

    -

    The class automatically creates a storage instance for each mode (backtest or live), and it handles reading and writing notification data safely, even if there are unexpected interruptions.

    -

    You can easily swap out the storage method being used, for example, switching to the default file storage or opting for a dummy storage for testing purposes. This is particularly useful when the working directory changes, as the clear method refreshes the storage to use the new base path. It's designed to work closely with other components like NotificationPersistLiveUtils and NotificationPersistBacktestUtils to ensure consistent data handling.

    -

    This component handles saving and retrieving notifications to persistent storage, typically files. It's designed to be reliable, even if things go wrong during the saving process.

    -

    Each notification is stored as its own JSON file, making it easy to manage and identify individual notifications. When you need to load all notifications, the system looks through all the available files.

    -

    The backtest property determines how the storage is configured – it likely affects how the data is handled in testing environments.

    -

    The waitForInit method ensures that the underlying storage is ready before any operations are attempted.

    -

    To get all notifications, use readNotificationData, which gathers them from the files.

    -

    When saving notifications, writeNotificationData handles writing each one individually and uniquely identified by its ID.

    -

    This class provides a way to reliably store and retrieve data across different parts of your trading strategy, even if the system crashes. It's designed to manage how your strategy remembers things between runs.

    -

    It keeps track of storage locations based on signal IDs and bucket names, creating a dedicated storage area for each combination. You can customize how this storage works by providing your own ways to create and manage these storage areas, or stick with the default file-based approach.

    -

    The class has methods to read, write, delete, and check for existing data. When you need to access data for the first time, it automatically sets up the storage area. You can clear the internal storage cache if your working directory changes during a strategy run. It also offers ways to iterate through all the stored data, which is useful for rebuilding internal indexes. Finally, there are options to use a dummy instance for testing, or switch back to the default JSON-based persistence.

    -

    This class provides a way to store and retrieve memory data to a file, acting as a persistent layer for your trading framework. It's built to manage data related to a specific signal and bucket.

    -

    It handles saving data to files and keeps track of whether a data entry is considered deleted (but not physically removed from disk).

    -

    You can use it to read a single piece of data, check if a specific piece of data exists, write new data or remove existing data.

    -

    When listing all the data, it automatically filters out any entries that have been marked as deleted.

    -

    Importantly, this class doesn't handle its own cleanup; that's managed by a separate utility function, ensuring a clean and organized system.

    -

    This utility class helps manage cached data from external APIs, making sure the information is reliably stored and retrieved. It creates specialized storage areas for each set of data, identified by a combination of timestamp and symbol.

    -

    You can customize how this caching works by providing your own storage "builders," allowing you to use different storage mechanisms. This system ensures data reads and writes happen safely, even if the application unexpectedly crashes.

    -

    The class also offers handy methods like listMeasureData to view all cached entries within a specific storage area, and clear to completely reset the cache when needed, such as when the working directory changes. You can easily switch back to a default file-based storage or use a dummy implementation for testing purposes.

    -

    This component provides a way to save and retrieve measure data persistently, like to a file. It acts as a layer on top of a basic storage system to handle things like safely writing data and marking entries as deleted instead of actually removing them.

    -

    The bucket property defines where this data is stored.

    -

    You can use readMeasureData to fetch a specific piece of data by its key, and writeMeasureData to save new data or update existing entries. removeMeasureData doesn't erase the data entirely; it just flags it as removed, which is useful for keeping historical records. Finally, listMeasureData provides a way to get a list of all available data entries, excluding those that have been marked as removed. waitForInit ensures the storage is ready before you start working with it.

    -

    This class helps manage how log entries are saved and retrieved. It keeps a single, cached instance of the log storage system to avoid creating new ones repeatedly.

    -

    You can customize how the log entries are stored by providing your own storage constructor, essentially swapping out the default storage mechanism.

    -

    The readLogData method retrieves all the existing log entries, while writeLogData adds new entries to the persistent storage. It’s important to know that writes are append-only and duplicates are ignored.

    -

    To ensure reliability, it handles log state safely even if the system crashes. It also offers a clear method to reset the cached log instance, particularly useful when the working directory changes. Finally, it provides convenient shortcuts like useJson to switch back to the standard file-based storage and useDummy for testing where no actual logging is needed.

    -

    This component provides a way to store your trading logs to files, ensuring they’re kept safely and consistently. Think of it as a persistent memory for your backtesting process.

    -

    Each log entry gets its own separate file, organized by a unique ID. This method makes it easy to read the entire history of your backtest.

    -

    The system is designed to be append-only, meaning it will only add new data and will never accidentally erase existing log entries. This protects against data loss even if something unexpected happens during the writing process.

    -

    Before working with logs, you need to initialize the storage. The waitForInit method handles this process.

    -

    Retrieving and saving log data are straightforward actions using readLogData and writeLogData. readLogData retrieves all entries, while writeLogData adds new ones without overwriting any existing data.

    -

    This component handles keeping track of when specific intervals have already fired, helping to avoid redundant calculations. It stores this information in files located in a directory structure under ./dump/data/interval/.

    -

    Think of it as a record-keeping system; if a file exists for a particular interval, it signifies that interval has already been processed. If the file is missing, it means the interval hasn’t fired yet, or it returned null during the last run.

    -

    You can customize how this record-keeping happens, for instance, switching to a file-based system or using a dummy system for testing where no actual persistence takes place. The system lazily loads data and creates bucket instances when they are first accessed, ensuring efficient operation. It also provides a way to completely clear the record cache, which is helpful when the working directory changes.

    -

    This class provides a way to store and manage interval data, essentially markers that trigger actions at specific times. It's designed to work with files, making the data persistent even if your application restarts.

    -

    The data is organized within a "bucket," which is like a folder for your interval markers. When you need to retrieve a marker, readIntervalData fetches it. If the marker doesn’t exist or is marked for deletion, it returns nothing.

    -

    To save a marker, use writeIntervalData. If you need to remove a marker without actually deleting the file, removeIntervalData is your tool—it just adds a flag indicating it's removed. This is useful because it allows the interval to be re-enabled later.

    -

    Finally, listIntervalData gives you a way to see all the active, non-deleted markers in your bucket, providing a list of their keys. waitForInit makes sure the underlying storage is ready before any operations happen.

    -

    This class helps manage a cache of historical candle data, storing each candle as a separate file. It's designed to make accessing and saving candle data efficient, especially when dealing with a large number of candles.

    -

    The class automatically handles checking if the cached data is still valid and will refresh it when needed. It prioritizes speed and reliability, making sure reads and writes happen safely.

    -

    You can customize how the cached data is stored by using different "adapters" – choosing between a standard file-based system, a simpler version for testing, or providing your own custom storage mechanism.

    -

    If your working directory changes, it’s important to clear the internal cache to ensure everything stays synchronized.

    -

    This class provides a way to store and retrieve historical candle data, essentially acting as a persistent layer for your trading system. It uses individual JSON files to represent each candle, organizing them by their timestamp.

    -

    When you request candle data, it checks for the presence of each candle's file. If a file is missing, it’s considered a cache miss, signaling a need to refetch the data.

    -

    The storage system is designed to be append-only. It won't save candles that aren’t fully complete (meaning they haven't reached their close time) or overwrite existing candle data, ensuring the integrity of the historical records. If it finds a problem with the stored data, it will alert you and treat it as a missing candle.

    -

    You can initialize the storage layer, retrieve batches of candles within a specific timeframe, and write new batches of candles to the storage. This lets you keep a history of market data even when your application restarts.

    -

    This class helps manage and save breakeven data for your trading strategies, making sure information persists between runs. It's designed to keep track of breakeven points for specific symbols, strategies, and exchanges, storing this data in files.

    -

    It uses a clever system where it only creates and loads the data storage for a specific symbol and strategy combination the first time it's needed – this is called lazy initialization.

    -

    You can even customize how this data is stored, swapping out the default file storage for other options, like a dummy that does nothing. It acts as a central hub for accessing and saving this data.

    -

    If your working directory changes during a strategy run, you may need to clear the cached data to ensure things are reloaded correctly.

    -

    This class provides a way to reliably store and retrieve breakeven data, essentially acting as a persistent memory for your trading strategies. It’s designed to be crash-safe, ensuring your data isn’t lost even if something unexpected happens.

    -

    It works by storing data in files, using a unique identifier (signalId) to organize the information. Think of it like a digital filing cabinet for your trading calculations.

    -

    The class automatically handles writing data securely, preventing corruption.

    -

    Here’s what you can do with it:

    +

    This service is designed to track and record maximum drawdown events, which are crucial for evaluating trading strategy performance. It monitors for drawdown events and systematically saves this data to a report database in a JSONL format, ready for analysis.

    +

    The service relies on a maxDrawdownSubject to receive these drawdown notifications.

    +

    It also includes a handy way to ensure you only subscribe once – subsequent subscription attempts won’t re-subscribe, preventing unwanted behavior.

    +

    To stop the service from recording further drawdown events, you can unsubscribe, which effectively disconnects it from the data stream.

    +

    The logged data includes detailed information about each drawdown event such as timestamp, symbol, strategy name, exchange, frame, signal ID, position, current price, and order parameters.

    +

    This service helps you create and save reports about maximum drawdowns, which are important for understanding risk in trading. It listens for drawdown events and organizes them based on the symbol, strategy, exchange, and timeframe.

    +

    You can subscribe to receive these drawdown events, and unsubscribe to stop them. It’s designed so you don’t accidentally subscribe multiple times.

    +

    The getData method retrieves the accumulated drawdown statistics for a specific combination of symbol, strategy, exchange, timeframe, and whether it's a backtest. getReport generates a nicely formatted markdown report from those statistics, and dump writes that report directly to a file.

    +

    Finally, there's a clear method to remove the accumulated data; you can either clear everything or just clear the data for a specific symbol/strategy/exchange/timeframe combination.

    +

    The MarkdownWriterAdapter provides a flexible way to manage and store markdown output from your backtesting process. It allows you to easily switch between different storage methods, such as saving each report as a separate file, accumulating everything into a single JSONL file, or completely disabling markdown output. You can customize the markdown adapter used by setting a custom constructor, ensuring that storage instances are unique and efficient. The adapter lazily initializes storage the first time data is written, simplifying setup. To write markdown data, simply call writeData with the appropriate content and options.

    +

    The MarkdownUtils class helps you control when and how markdown reports are generated for your trading activities. It lets you turn on or off report generation for different areas like backtesting, live trading, or performance analysis.

    +

    To use it, you’ll specify which report types you want active. When you enable a report type, it starts collecting data and generating markdown files – be sure to clean up (unsubscribe) when you’re done to avoid memory problems.

    +

    You can also disable individual report types to pause their generation without impacting others. If you only want to clear data, the clear method lets you reset the data collected for a particular report type, without stopping the reporting process itself. This allows for data resets while keeping reporting functionality active.

    +

    This adapter is designed to generate trading reports with each report saved as its own individual markdown file. Think of it as creating a well-organized folder full of readable reports.

    +

    It’s the default choice for generating reports that you want to easily browse and review manually.

    +

    The adapter writes directly to files without managing any streams, making the process straightforward.

    +

    The name of each file is constructed using settings you provide, typically combining a base path and a unique file name.

    +

    You don’t need to do anything special to prepare this adapter for use – it's ready to go.

    +

    Essentially, the dump method takes your report content and saves it to a file based on the specified options, automatically creating any necessary directories.

    +

    The MarkdownFileBase class helps you manage and write markdown reports in a structured way, specifically for backtesting and trading systems. It creates a single JSONL file for each type of markdown report, making it easy to process and analyze your data later using standard JSONL tools.

    +

    Think of it as a centralized logging system for your markdown reports.

    +

    It handles the technical details like creating directories, managing the writing process (even when things get busy), and ensuring writes don't take too long. You can also easily filter these reports by things like the trading symbol, strategy, or exchange used.

    +

    The dump method is your primary way to add markdown content; it takes the markdown text and adds important metadata like timestamps and search tags to each line. Initialization is handled automatically and safely, so you don't need to worry about manual setup.

    +

    The MarkdownAdapter helps you manage how your markdown data is stored, offering flexibility and efficiency. It lets you easily switch between different storage methods without changing your core code.

    +

    You can choose to store your markdown as individual files, each in its own .md file, or append everything to a single .jsonl file.

    +

    There’s even a “dummy” adapter for testing purposes, which prevents any actual data from being saved. The system only creates one storage instance for each type of markdown, preventing unnecessary overhead. It also delays creating storage until the first time you need to write data, optimizing performance.

    +

    The LookupUtils class acts like a central record keeper, tracking all currently running backtests and live trading sessions. It maintains a list of these activities, noting when they start and when they finish.

    +

    This tracking helps manage resources and optimize performance, particularly concerning how data is handled during backtesting.

    +

    You don't need to create an instance of LookupUtils; it’s available as a singleton.

    +

    Here's a breakdown of what it does:

      -
    • It's initialized with the symbol, strategy name, and exchange name it manages.
    • -
    • waitForInit prepares the underlying storage – a one-time setup step.
    • -
    • readBreakevenData fetches existing breakeven data for a specific signal.
    • -
    • writeBreakevenData saves new or updated breakeven data for a given signal.
    • +
    • Adding Activities: When a backtest or live run begins, information about it is added to the registry. If you try to add the same activity again, it simply updates the existing entry.
    • +
    • Removing Activities: When a backtest or live run concludes (successfully or with an error), the registry is updated to remove the activity. It’s important to always remove activities to avoid leaving outdated information.
    • +
    • Listing Activities: The system can request a snapshot of all the active backtests and live runs at any given time.
    -

    This class provides a foundation for storing and retrieving data to files, ensuring a safe and reliable process. It handles the technical details of managing files, including ensuring they aren't corrupted and making sure updates happen completely.

    -

    The entityName and baseDir define where and what you're storing. The waitForInit method sets up the storage area initially and checks that the existing files are in good shape.

    -

    You can use readValue to get data back, hasValue to check if data exists, and writeValue to save data – all while it takes care of writing the data in a safe, atomic way. To get a list of all the data being stored, use the keys method to iterate through entity IDs, presented in sorted order.

    -

    This service helps you understand where your trading strategy is spending its time. It acts as a listener, quietly recording the duration of different parts of your strategy's execution. This information is then stored in a database, allowing you to pinpoint bottlenecks and optimize your strategy’s performance.

    -

    You can tell it to start listening for these timing events, and it will automatically stop listening when you tell it to.

    -

    Here's a breakdown of how it works:

    +

    Essentially, it provides a way to monitor and control the status of ongoing trading activities.

    +

    The LoggerService helps ensure consistent and informative logging throughout your trading strategies and backtests. It acts as a central point for logging, automatically adding important details to each message, like which strategy, exchange, or frame is being used, and relevant execution context such as the symbol being traded and the time of the trade.

    +

    You can configure a custom logger to use, or it will fall back to a basic "no-op" logger if you don't set one. The service provides methods for different logging levels like general messages, debug information, warnings, and more. The setLogger method is your way to plug in your preferred logging mechanism.

    +

    The LogAdapter provides a flexible way to manage log messages within your backtesting environment. Think of it as a central hub for all logging activities, allowing you to easily swap out different logging methods without changing your code. It defaults to storing logs in memory, but you can switch to persistent storage on disk, a dummy adapter that essentially ignores logs, or a JSONL file adapter for detailed record keeping.

    +

    The adapter uses a factory system, and to keep things efficient, it remembers the current logging method for reuse. The clear method is handy when your working directory changes, ensuring a fresh logging setup. You can use log, debug, info, and warn to record different types of information, and getList to retrieve all stored logs. It also allows setting a custom logging implementation through useLogger if you have unique requirements.

    +

    The LiveUtils class simplifies live trading operations and provides tools for managing live strategies. It offers features like crash recovery, real-time status updates, and convenient methods for interacting with live trading instances.

    +

    You can easily start live trading for a specific symbol and strategy using the run method, which acts like an infinite generator that automatically handles potential crashes and data recovery. There's also a background method for running live trades silently without directly receiving their results, useful for things like persistence or callbacks.

    +

    Need to know the current signal or position details? getPendingSignal, getTotalPercentClosed, getPositionEffectivePrice, and related methods provide access to essential data. You can also check if signals are active with hasNoPendingSignal and hasNoScheduledSignal.

    +

    Managing positions is straightforward with functions like commitPartialProfit, commitTrailingStop, and commitAverageBuy, allowing you to adjust stop-loss levels, take-profit targets, and add DCA entries. The class also offers utilities for generating reports (getReport, dump) and listing active trading instances (list). Finally, commitClosePending allows you to shut down a live trade immediately, while commitCancelScheduled can cancel a signal without halting the process.

    +

    The LiveReportService helps you keep a detailed record of what your trading strategy is doing in real-time. It's designed to capture every stage of a trade – from when it’s just waiting for an opportunity to when it’s finally closed – and save that information to a database.

    +

    Think of it as a live logbook for your strategy, providing valuable insights into its performance.

    +

    It connects to your trading system and listens for signals, then automatically records each event like when a trade is initiated, is active, or is closed.

    +

    You can easily subscribe to start receiving these live events and unsubscribe when you're done. Importantly, it prevents you from accidentally subscribing multiple times.

    +

    This service helps you automatically create reports documenting your live trading activity. It keeps track of everything that happens during your trades – from when a strategy is idle to when positions are opened, active, and eventually closed.

    +

    The service generates easy-to-read markdown tables summarizing these events and provides useful trading statistics like win rate and average profit/loss. These reports are saved as files, making it simple to review your strategy's performance over time.

    +

    You tell the service to start watching your strategy's ticks, and it takes care of the rest. It uses a system to isolate data for each trading combination you set up, so your reports stay organized. There's also a way to stop the service from tracking data when you no longer need it.

    +

    You can request data, generate reports, save them to disk, or even completely clear the accumulated data if needed. You can customize what information is included in the report.

    +

    LiveLogicPublicService helps manage live trading operations, handling things like automatically passing along information about the trading strategy and exchange being used.

    +

    It's designed to continuously run – think of it as a never-ending stream of trading updates – and is built to recover from crashes, ensuring your trading doesn't lose progress.

    +

    The run method is its core function. It takes a symbol (the asset being traded) and some context information.

    +

    It then streams data back to you, delivering signals related to opening, closing, or canceling trades.

    +

    Essentially, it simplifies the process of running and monitoring live trades by taking care of context management and recovery.

    +

    This service manages the ongoing process of live trading, continuously monitoring and reacting to market conditions. It operates as an infinite loop, constantly checking for new signals and processing trades.

    +

    The system builds its timeline using the current date and time to ensure accuracy. It delivers results – specifically, when trades are opened or closed – in a memory-efficient, streaming format.

    +

    If the process encounters an issue and needs to restart, it automatically recovers the trading state, so you don’t lose progress. The run method is the key entry point, taking a symbol as input and returning an async generator that streams those trading results.

    +

    This service lets you interact with live trading features within the backtest-kit framework. It's a central point for accessing live trading functionality and is designed to be easily used when you're setting up your application's dependencies.

    +

    Essentially, it acts as a bridge, wrapping another service to make things cleaner and easier to manage.

    +

    Here's a breakdown of what it provides:

      -
    • It uses a loggerService to provide helpful debugging information.
    • -
    • The track function handles the actual process of recording performance data.
    • -
    • The subscribe function is how you tell it to start listening to the strategy’s performance events – and it makes sure you don’t accidentally subscribe more than once.
    • -
    • The unsubscribe function is used to stop it from listening and cleaning up.
    • +
    • run() method: This is the key to running live trading. You tell it which symbol (like a stock ticker) you want to trade and provide some context like the strategy and exchange names. It continuously generates results – a stream of data about how the trading is progressing, including when a trade opens, closes, or is canceled. If things go wrong, it attempts to recover and keep the trading going, making it quite resilient.
    • +
    • Various validation services: It includes services for validating strategies, exchanges, risk factors, and actions – these help ensure everything is set up correctly before trading begins.
    • +
    • Logging: It has a built-in logger service to track events and help with debugging.
    -

    This service helps you understand how your trading strategies are performing by gathering and analyzing key metrics. It listens for performance events happening during your backtests or live trading, keeps track of these events for each strategy, and then summarizes them into useful statistics.

    -

    You can use it to get overall performance figures, like average returns and maximum drawdowns, but it also identifies potential bottlenecks in your strategies. It can generate reports in a readable markdown format, which makes it easy to share your results or identify areas for improvement.

    -

    The service also provides ways to clear out old performance data, and to manage how it subscribes and unsubscribes to the flow of performance events. Essentially, it gives you the tools to monitor, analyze, and refine your trading strategies.

    -

    The Performance class helps you understand how well your trading strategies are performing. It offers tools to analyze and report on your strategies' performance metrics.

    -

    You can retrieve aggregated performance statistics for a specific symbol and strategy, revealing detailed information like execution times, averages, and volatility.

    -

    To make understanding even easier, the class can generate comprehensive markdown reports, presenting a breakdown of where your strategy spends its time and highlighting potential bottlenecks through percentile analysis.

    -

    Finally, you can save these reports directly to your disk, making it simple to track and share your performance insights. The reports are typically stored in a directory named dump/performance, but you can customize the location.

    -

    The PartialUtils class helps you analyze and understand partial profit and loss data from your trading strategies. Think of it as a tool to inspect how your strategies are performing incrementally, rather than just at the very end.

    -

    It gathers information about partial profit and loss events, storing up to 250 of these events for each symbol and strategy combination. This data includes details like the time, type of event (profit or loss), symbol traded, strategy name, signal ID, position size, level, price, and whether it's a backtest or live trade.

    -

    You can use PartialUtils to get summarized statistics about your partial profits and losses. It can also create nicely formatted markdown reports that display all the individual events in a table, including details like the event type, symbol, strategy name, signal ID, position, level, price, and timestamp. These reports help you visually examine the sequence of events.

    -

    Finally, PartialUtils can save these markdown reports to files, making it easy to share your analysis or keep a record of your strategy’s performance. The files are named using the symbol and strategy name, so you can easily identify them.

    -

    The PartialReportService helps you keep track of when your trades partially close, whether it's for profit or loss. It listens for those specific events and records details like the price and level at which the partial closure happened.

    -

    Think of it as a logbook for those in-between moments of a trade.

    -

    You can tell it to start listening for partial profit and loss events, and it will send that information to be saved. To stop it from listening, there's an unsubscribe function that you can use. It's designed to prevent accidental multiple subscriptions, keeping things tidy. If you're already subscribed, this method does nothing.

    -

    This service helps you track and report on the partial profits and losses in your trading backtests. It listens for events indicating profit or loss and keeps a running total for each symbol and strategy you're using.

    -

    It automatically generates readable markdown reports summarizing these events, including detailed information about each profit or loss. You can also request overall statistics, like the total number of profits and losses.

    -

    The reports are saved to disk, making it easy to review your trading performance over time. You have control over where these reports are saved, and can even clear the stored data when you need to start fresh. The system ensures that each combination of symbol, strategy, exchange, frame, and backtest has its own separate storage. You can subscribe to receive profit/loss updates and unsubscribe when you no longer need them.

    -

    This service acts as a central hub for tracking and managing partial profits and losses within your trading strategy. It's designed to be injected into your strategy code, offering a single point of access for these operations.

    -

    Think of it as a log and forwarding system; whenever a profit, loss, or clearing of a partial position occurs, this service first records the event for monitoring purposes and then passes the request on to a lower-level service that actually handles the changes. Several validation services are also available to ensure the strategy and related configurations like risk, exchange, and frame are valid before proceeding with partial operations.

    -

    It simplifies how your strategy interacts with the partial profit/loss tracking system, promotes consistent logging, and helps keep your strategy code cleaner and more organized. The validate property uses caching to avoid unnecessary re-checks of strategy configurations.

    -

    The PartialConnectionService is designed to manage and track partial profit and loss information for trading signals. It's like a central hub that creates and maintains records for each signal, ensuring that these records are properly initialized and cleaned up when needed.

    -

    Think of it as a smart factory – whenever you need to track profit or loss for a signal, it provides a specialized component (a ClientPartial) that handles that specific task. These components are cached to avoid unnecessary creation, and they’re automatically removed when the signal is no longer active.

    -

    The service receives helpful tools like logging and event handling to keep everything organized and informed. When a signal experiences a profit, loss, or closure, this service coordinates the actions and notifies other parts of the system. It's a crucial part of the overall trading strategy, ensuring accurate and efficient tracking of partial results.

    -

    This component handles sending notifications about your trading strategy's progress, like signal events, profits, losses, and errors. It's designed to be flexible so you can easily switch between different ways of receiving those notifications – whether that's storing them in memory, saving them to a file, or simply ignoring them altogether for testing.

    -

    You can choose how notifications are handled by switching between adapters: a default in-memory adapter, a persistent adapter for saving notifications to disk, or a dummy adapter that does nothing.

    -

    The handleSignal, handlePartialProfit, handlePartialLoss, handleBreakeven, handleStrategyCommit, handleSync, handleRisk, handleError, handleCriticalError and handleValidationError methods are all pass-throughs to the currently selected notification adapter, ensuring consistent notification delivery. The getData method allows you to retrieve all the notifications that have been generated. The dispose method clears any stored notifications.

    -

    If your environment changes (like when the working directory changes during strategy runs), it's important to call clear() to force a new instance of the notification adapter to be created. This ensures it's using the correct configuration for the current environment.

    -

    This service helps manage and send out notifications related to signals, making sure everything is validated before it's sent. It’s primarily used internally by the backtest-kit framework, so you won’t directly use it unless you're deep in customization.

    -

    Think of it as a gatekeeper for signal information. Before a signal is broadcast, it checks several aspects, like the strategy, exchange, frame, and action schemas, to ensure everything is correct. This check is performed only once for each unique combination of strategy, exchange, and frame name to improve efficiency.

    -

    You'll interact with this indirectly through onActivePing callbacks, specifically using the commitSignalNotify() function. This function is responsible for taking the signal information, validating it, and then sending it out to the rest of the system. The notification itself is then handled by other components responsible for displaying and persisting the information.

    -

    This component lets you manage notifications during backtesting, offering flexibility in how those notifications are handled. It uses a design that allows you to easily swap out different notification methods without changing your core backtesting logic.

    -

    You can choose to store notifications in memory (the default), persist them to disk, or even use a dummy adapter that effectively ignores notifications entirely.

    -

    The handleSignal, handlePartialProfit, handleRisk, and other methods are ways to send different types of notifications. These methods simply pass the data to the currently active notification backend.

    -

    The useDummy, useMemory, and usePersist methods provide quick ways to switch between notification storage methods. The useNotificationAdapter function gives you the most control by allowing you to specify exactly which notification class to use. clear resets the cached notification utilities, which is important if your working directory changes.

    -

    The NotificationAdapter is the central hub for handling notifications during both backtesting and live trading. It automatically receives and organizes notifications triggered by various events like signals, profits, losses, and errors.

    -

    You can enable the adapter to start receiving notifications, which is done only once to prevent unnecessary subscriptions. Conversely, you can disable the adapter to stop receiving notifications; calling disable multiple times is perfectly safe.

    -

    To retrieve the accumulated notifications, there's a getData method that lets you specify whether you want the backtest or live notifications. When you’re finished, dispose of the adapter to clear all stored notifications and release resources.

    -

    This component provides a flexible way to manage data during live trading, acting as a central storage hub. Think of it as a smart memory system that can be easily swapped out with different storage methods.

    -

    By default, it saves data to files on your computer's file system, ensuring that your data persists even if the program restarts. However, it also offers alternatives: a temporary in-memory storage for quick testing, or even a "dummy" option that simply discards any data written to it.

    -

    You can easily change which storage method is used, and the system automatically manages how data is stored and retrieved.

    -

    It allows you to search, list, add, remove, and read entries. If you want to clean up or customize the storage, there are methods to dispose signals and clear caches. It’s designed to make handling trading memory a clean and adaptable process.

    -

    This adapter provides a flexible way to manage memory storage for backtesting, allowing you to choose different storage methods depending on your needs. By default, it uses an in-memory storage system based on BM25 for searching, meaning all data resides in the process's memory and isn't saved permanently.

    -

    You can easily switch between different storage implementations. For instance, you can choose to persist data to files, use a dummy adapter that simply discards data for testing purposes, or use a custom storage adapter you've built yourself.

    -

    The disposeSignal method helps keep memory usage in check; it clears out stored data associated with a specific signal when that signal is no longer needed. You can write, search, list, remove, and read data from memory using the provided methods. If your working directory changes during backtest iterations, you'll want to call clear to ensure fresh instances are created with the correct base path.

    -

    The MemoryAdapter is the central hub for managing how your backtests and live trading environments store and retrieve data. It intelligently directs memory-related operations, like writing, searching, listing, removing, and reading entries, to either the backtest or live memory systems based on your configuration.

    -

    To keep things tidy and prevent memory leaks, the MemoryAdapter automatically handles subscriptions to signal lifecycle events, ensuring that when a signal is closed, any related memory is cleaned up. It also uses a "single-shot" approach to subscriptions, guaranteeing that you don't accidentally subscribe multiple times.

    -

    You can control its activity with enable and disable functions; enabling it subscribes to lifecycle events, while disabling simply unsubscribes. The enable function ensures that stale data doesn't linger in your systems. The writeMemory function lets you store data, while searchMemory allows you to find data using full-text search, listMemory retrieves all entries, removeMemory deletes entries, and readMemory fetches a specific entry. All these functions use the information you provide to determine if they are operating in a backtest or live environment.

    -

    This class offers tools to analyze and report on maximum drawdown events, which help understand potential risks in your trading strategies. It acts as a central place to gather and present data collected from max drawdown events.

    -

    You can use it to fetch detailed statistical information about drawdowns, specifying the symbol, strategy, and data context you’re interested in.

    -

    It also allows you to create markdown reports summarizing these drawdown events, either as a string or by saving them directly to a file. You can customize which columns appear in the reports.

    -

    The MaxDrawdownReportService is designed to keep track of maximum drawdown events during a trading simulation. It monitors for these drawdown occurrences and records them in a special JSONL database for later analysis.

    -

    Think of it as a dedicated reporter, always listening for new drawdown events. When it detects one, it carefully notes important details – things like the exact time, the asset involved, the trading strategy used, the price at which the trade was placed, and so on – and saves that information.

    -

    To get started, you need to tell the service to begin watching for drawdown events using the subscribe method. To stop the service and prevent further records from being created, use unsubscribe. It’s designed to avoid accidentally subscribing multiple times, so it’s safe to call subscribe even if it’s already active.

    -

    This service is designed to automatically create and store reports detailing maximum drawdown, a critical risk metric for trading strategies. It listens for drawdown data and organizes it based on the trading symbol, strategy, exchange, and timeframe.

    -

    You can think of it as a data collector and reporter for drawdown events.

    -

    To start receiving these events, you need to subscribe. To stop and clear all collected data, unsubscribe.

    -

    The service allows you to retrieve the accumulated data, generate a formatted markdown report, or directly save the report to a file.

    -

    You can also clear the stored data. If you specify a particular symbol, strategy, exchange, timeframe, and backtest flag, only the data associated with that combination will be cleared. Otherwise, it clears everything.

    -

    This component manages how your trading reports are saved, offering flexible ways to control where and how the information is stored. It uses a design that lets you easily swap out different storage methods without changing your core code.

    -

    You can choose to save reports as individual markdown files in a folder (the default), append them to a single JSONL file, or even suppress the output entirely. The system remembers which storage method you're using, so you don't have to keep reconfiguring it.

    -

    If your project's working directory changes, like when moving between strategy iterations, it's important to clear the cache to ensure that new storage is created with the correct path. You can also change the default markdown storage adapter if you have a custom implementation.

    -

    This class helps manage how markdown reports are generated for different parts of the backtest-kit framework, like backtests, live trading, or performance analysis.

    -

    You can selectively turn on markdown reporting for specific areas, and it gives you a way to cleanly turn them all off at once to avoid resource leaks - remember to use the cleanup function it provides!

    -

    Alternatively, you can disable markdown reporting for just certain areas while leaving others running, providing precise control over what's reported.

    -

    You also have the ability to clear out the accumulated data for specific markdown reports without stopping the reporting itself, allowing you to refresh the data while keeping the reporting system active.

    -

    This adapter provides a straightforward way to generate backtest reports, creating each report as a separate markdown file within a designated folder. Think of it as a convenient way to keep your reports neatly organized for easy human review.

    -

    The adapter writes directly to files, so no complex stream management is involved. The file name and location are determined by the options.path and options.file settings you provide.

    -

    It automatically creates the necessary directories, so you don't have to worry about that part.

    -

    The waitForInit method is essentially a placeholder – it doesn't do anything because this adapter doesn’t require any initial setup.

    -

    The key function is dump, which handles writing the markdown content to a file, constructing the full file path, and ensuring the directory structure exists.

    -

    This component helps manage and store your markdown reports, like those generated during backtesting, in a structured and easily processable way. It writes each type of report (e.g., trade summaries, order books) to its own JSONL file, ensuring a clean and organized log.

    -

    Think of it as a central hub for all your markdown-based reports. It's designed to handle a large volume of data efficiently, including automatically creating directories and managing potential writing delays. The system also includes built-in protections to prevent write operations from taking too long, and it allows you to filter reports based on various criteria such as the trading symbol and strategy used.

    -

    You can initialize the system once, and it's safe to re-initialize it if needed. When you want to create a report, you simply provide the markdown content along with some identifying information (symbol, strategy, etc.), and the component takes care of writing it to the appropriate file. The resulting JSONL files can then be easily processed and analyzed by external tools.

    -

    The MarkdownAdapter helps manage how your markdown files are stored, offering flexibility and efficiency. It lets you easily switch between different storage methods, like having each markdown dump create its own file or appending them all to a single JSONL file.

    -

    You can change the way markdown is stored by providing a custom constructor for the adapter, allowing for tailored storage solutions.

    -

    For convenience, there are shortcuts to use the default folder-based storage (useMd) or the JSONL-based storage (useJsonl). If you just want to test or temporarily disable markdown writing, you can use the useDummy adapter, which simply ignores any attempts to write markdown. The system remembers your storage choices, so you don’t have to set them repeatedly.

    -

    The LookupUtils framework acts as a central record of what's currently happening in your backtests or live trading sessions. Think of it as a constantly updated list of ongoing activities, like individual backtests, live trades, or even steps within a trading strategy.

    -

    Each time a backtest starts, a live session begins, or a step in your strategy is executed, an entry is added to this list. Conversely, when something finishes, its entry is removed.

    -

    It uses an internal map (_lookupMap) to keep track of these entries, allowing quick access to the current state.

    -

    You can use the addActivity function to register a new activity, and removeActivity to clean up when it’s done. It's important to use removeActivity even if errors occur, to prevent stale entries from lingering.

    -

    Finally, listActivity provides a quick way to see a snapshot of all the activities that are currently in progress. This is primarily used internally, but useful for debugging or understanding what's going on.

    -

    The LoggerService is a central tool for logging information within the backtest-kit framework, ensuring all logs are formatted consistently and include important details. It provides a convenient way to record events during backtesting and live trading.

    -

    You can customize the logging behavior by providing your own logger implementation through the setLogger function, otherwise it defaults to a do-nothing logger.

    -

    The service automatically adds context to your log messages, such as the strategy name, exchange, and the specific part of the code being executed. This context helps pinpoint exactly where events occur.

    -

    It offers several logging levels – log, debug, info, and warn – each appending the context to the message you provide, making it easy to track different types of activity.

    -

    The LogAdapter acts as a central point for managing how your backtesting framework records information, like trades and performance metrics. It's designed to be flexible, allowing you to easily switch between different logging methods without changing a lot of code. By default, it keeps logs in memory, but you can quickly change it to store logs persistently to disk, use a dummy logger that does nothing, or even use a JSONL file.

    -

    The useLogger method gives you fine-grained control by letting you specify exactly how logs are handled. Methods like log, debug, info, and warn are shortcuts to send messages at different levels of importance, all through this adapter. If the working directory changes during testing, remember to call clear to refresh the logging setup.

    -

    LiveUtils provides tools for running live trading sessions, handling crashes, and getting real-time data. It acts as a central hub for managing live trading operations.

    -

    You can start live trading for a specific symbol and strategy using the run method, which continuously generates trading updates and recovers from potential crashes. Alternatively, the background method can run trading in the background without interrupting the main process.

    -

    The framework offers ways to retrieve important information about the current trade, like the pending signal, total position percentage, cost basis, and estimated minutes remaining. It also includes methods to adjust the trade, such as setting a new breakeven price, moving stop-loss and take-profit levels, and adding new DCA entries.

    -

    The LiveUtils framework also has functions for specific actions like canceling scheduled signals or closing the position directly. Finally, you can collect stats and reports about trading activity and list active trading instances. This whole system is designed to keep trading operations running smoothly and provide a wealth of information about the position's status.

    -

    The LiveReportService is designed to record every step of your live trading strategy as it happens. It monitors your signals, noting when they're idle, when a trade is opened, when it’s active, and when it's closed.

    -

    Essentially, it’s a logging system that saves these details to a SQLite database, allowing you to observe and analyze your trades in real-time.

    -

    It works by listening to live signal events and meticulously recording all the relevant information, then storing that data persistently. To prevent accidental duplicates, it uses a mechanism to ensure only one subscription is active at a time.

    -

    You can start receiving these live events by using the subscribe method, which returns a function you can call to stop the subscription. The unsubscribe method provides a clean way to stop the service from logging events if needed. Finally, the tick property handles the actual processing and logging of these events.

    -

    This service helps you automatically create markdown reports of your live trading activity. It listens for events happening during your trades, such as when a trade is opened, active, or closed, and carefully tracks all the details.

    -

    It organizes this information into easy-to-read markdown tables, giving you a clear overview of how each strategy is performing. You’ll also get key statistics like your win rate and average profit.

    -

    The service saves these reports as markdown files in a logs folder, organized by strategy name, making it simple to review your performance over time.

    -

    You can subscribe to receive these real-time updates, and the service is designed to prevent accidental duplicate subscriptions. There's also a function to stop receiving these updates when you no longer need them.

    -

    You have options to get raw data, generate reports for specific trades, or completely clear the accumulated data. You can even specify where the reports should be saved.

    -

    This service helps manage and run live trading operations. It simplifies things by automatically handling context information like the strategy and exchange being used, so you don't need to pass it around explicitly in your code.

    -

    Think of it as a central hub for live trading that seamlessly integrates with other parts of the backtest-kit framework.

    -

    It provides a continuous, never-ending stream of trading results, either signals to open or close positions, or cancellations.

    -

    The system is designed to be resilient, automatically recovering from crashes and preserving your trading progress. It uses the current time to keep everything synchronized.

    -

    You can specify the symbol you want to trade and a context object containing the strategy and exchange names to get started.

    -

    This service manages the ongoing process of live trading, working behind the scenes to keep everything running smoothly. It uses a continuous loop to constantly monitor the market and check for new trading signals.

    -

    The service streams results—specifically, when trades are opened or closed—efficiently, avoiding unnecessary data. It's designed to be memory-friendly and will run indefinitely, allowing for continuous trading.

    -

    If the system experiences a crash, it's built to automatically recover and resume trading from where it left off. The process leverages several core services for logging, strategy execution, and method context. The run method is the main entry point, taking a symbol as input and returning an async generator that provides a live stream of trading events.

    -

    This service helps your application interact with live trading features. It acts as a convenient bridge, making it easier to inject dependencies and use the underlying live trading logic.

    -

    Think of it as a central hub for live trading operations.

    -

    Here’s a breakdown of what it offers:

    +

    IntervalUtils helps you control how often functions are executed, particularly in trading strategies where you want to avoid overwhelming the system. Think of it as a way to ensure a task runs only once within a defined time period, like once per minute or once per hour.

    +

    There are two main ways to use it: in-memory, where the information is stored in the program’s memory, or file-based, where it persists even if the program restarts. The file-based version is particularly handy for strategies that need to remember whether a function has already run, even after a system reboot.

    +

    It's accessed through a single, easy-to-use instance named Interval.

    +

    You can manage these function executions using methods to clear out old data or reset counters, which is useful when your environment changes. Essentially, it provides a clean way to manage tasks and ensure they don't run unnecessarily.

    +

    This class helps you understand and analyze the highest profit moments achieved during your trading simulations or live trading. Think of it as a tool to review and gain insights from when your strategies performed exceptionally well.

    +

    It provides a few key functions:

      -
    • It handles running live trading sessions for a specific symbol.
    • -
    • It incorporates important context like the strategy and exchange being used.
    • -
    • The run method is the key – it provides an ongoing stream of results (open, closed, or cancelled strategy ticks) and automatically recovers from crashes, ensuring continuous operation. It works using an infinite generator.
    • -
    • It uses several other validation services internally to ensure things are set up correctly, including checks for strategies, exchanges, risks, and actions.
    • +
    • getData: This function lets you pull out specific statistical information related to the highest profit events for a particular trading strategy and symbol. It returns a detailed data model containing various statistics.
    • +
    • getReport: This is your go-to for creating a readable markdown report that summarizes all the highest profit events for a specific strategy and symbol. You can also customize which pieces of information are included in the report.
    • +
    • dump: If you want to permanently save that markdown report, this function will do it for you, writing the report to a file. You can specify the file path where you want the report saved.
    -

    IntervalUtils provides a way to control how often your functions run, especially when dealing with time-series data like trading signals. Think of it as a gatekeeper for your functions, ensuring they don't fire too frequently.

    -

    It has two main modes: in-memory, where the state is temporary, and file-based, where the state is saved to disk, meaning it survives restarts. The fn method is used for functions that don't need to persist data, while the file method is perfect for actions that need to be remembered between sessions.

    -

    To make things even easier, IntervalUtils uses a single, readily available instance called Interval, so you don't have to create one yourself. You can clear or dispose of these controlled functions when you need to, such as when your working directory changes, ensuring a clean start each time. It helps avoid conflicts between strategy iterations.

    -

    This class helps you analyze and report on the highest profit-generating events your trading strategies achieve.

    -

    Think of it as a tool to understand which strategies are performing best under different conditions.

    -

    It gathers data from events that track highest profits and lets you pull out key statistics or generate complete reports. You can request this data for a specific trading symbol, strategy, exchange, and timeframe.

    -

    The getData method lets you grab detailed statistics related to highest profit. The getReport method creates a formatted markdown report showcasing these highest profit events. Finally, dump allows you to take that markdown report and save it directly to a file for later review or sharing. It's all about providing easy access to insights about your most successful trading moments.

    -

    The HighestProfitReportService is designed to keep track of your most profitable trading moments and record them for later analysis. It essentially listens for notifications of new highest profit records and saves those details to a database.

    -

    When you want to start recording these events, you use the subscribe function, which kicks off the process of saving data. It's designed to only subscribe once, preventing duplicate data entries.

    -

    To stop recording, use the unsubscribe function. It disconnects the service from the data stream, preventing further records from being saved.

    -

    The service meticulously captures a snapshot of the trading conditions at the time of each highest profit record, including details like timestamps, symbols, strategy names, exchanges, signal IDs, position sizes, and order prices. This allows you to later understand exactly what led to those successful trades. Importantly, it retrieves signal-specific information directly from the signal data to ensure accuracy.

    -

    This service helps generate and store reports detailing the highest profit achieved for different trading scenarios. It listens for incoming data about profit events and organizes them based on symbol, strategy, exchange, and timeframe.

    -

    You can subscribe to receive these events, but it's designed to prevent multiple subscriptions. Unsubscribing completely stops the process and clears all accumulated data.

    -

    The tick method handles individual profit events, routing them to the appropriate storage area.

    -

    You can retrieve specific data using getData, which shows the accumulated statistics for a particular combination of symbol, strategy, exchange, and timeframe. getReport creates a nicely formatted markdown report with a table of events and a total count. Finally, dump creates this report and saves it as a markdown file to disk, with a filename indicating the symbol, strategy, exchange, and whether it’s a backtest.

    -

    To completely reset all the data, use clear. You can clear all storage or just a specific bucket identified by a combination of symbol, strategy, exchange, timeframe, and backtest status.

    -

    HeatUtils helps you easily visualize and analyze your trading portfolio's performance using heatmaps. Think of it as a tool to quickly understand how different assets are contributing to your overall strategy results.

    -

    It automatically gathers statistics from all your closed trades, giving you a clear picture of each symbol's performance and the portfolio's overall metrics.

    -

    You can request the raw data, or have HeatUtils generate a nicely formatted markdown report that summarizes the key information, such as total profit/loss, Sharpe ratio, and maximum drawdown, sorted by profitability.

    -

    The report can be saved directly to a file on your computer for later review or sharing. This whole system is designed to be straightforward – there’s just one readily available instance to use.

    -

    The HeatReportService helps you track and analyze your trading performance by recording when your signals close. It focuses on capturing the profit and loss (PNL) data associated with these closed signals across all the assets you're trading.

    -

    Think of it as a data collector for understanding how your trading strategies are performing over time, allowing you to spot patterns and make informed adjustments.

    -

    It connects to a central signal system and specifically records closed signals (those that have ended). It then saves this information in a database for later analysis and generating helpful visualizations – the heatmap.

    -

    You subscribe to this service to start receiving signal event updates, and importantly, it prevents you from accidentally subscribing multiple times. When you’re done, you can unsubscribe to stop receiving these updates.

    -

    This service creates a portfolio-wide heatmap to visualize trading performance. It listens for signals from your trading strategies and aggregates key metrics like profit/loss, Sharpe Ratio, and maximum drawdown for each symbol and across your entire portfolio.

    -

    It’s designed to be flexible, with each trading environment (exchange, timeframe, backtest vs. live) having its own dedicated storage area. This prevents data from different contexts getting mixed up.

    -

    You subscribe to receive tick events, and the service automatically builds up the heatmap data. It provides functions to retrieve the aggregated statistics, generate a nicely formatted markdown report, or write the report directly to a file. You can also clear the accumulated data to start fresh, either for a specific trading setup or globally. It handles potential errors like NaN or Infinity gracefully to ensure the report is always clean and understandable.

    -

    This service helps you keep track of and make sure your trading timeframes (like 1-minute, 5-minute, daily) are properly set up. It acts like a central manager for all your defined timeframes.

    -

    You can use it to register new timeframes with specific configurations.

    -

    Before you start using a timeframe in your trading logic, you can ask this service to double-check that it actually exists – preventing errors. The service remembers its checks, making the validation process faster each time. Finally, you can get a complete list of all the timeframes you've registered.

    -

    The FrameSchemaService helps keep track of all your different frame schemas, ensuring they are consistent and well-defined.

    -

    It's like a central library for these schemas, allowing you to easily register new ones and retrieve existing ones by their names.

    -

    Before a schema is officially added, a quick check ensures it has the essential properties in the right format.

    -

    You can add a new schema using register, update an existing one with override, and get a schema back using get. The service uses a sophisticated system for storing these schemas safely and in a type-safe manner.

    -

    This service acts as a central point for handling all things related to timeframes within the backtesting framework. It works closely with a connection service to fetch the necessary data and a validation service to ensure accuracy. Think of it as the engine that provides the sequence of dates your trading strategy will be tested against.

    -

    The getTimeframe function is its key feature—it's what you'll use to get the array of dates needed for a specific trading symbol and timeframe (like daily, weekly, or hourly).

    -

    Essentially, it simplifies the process of obtaining and managing the time data your backtest relies on.

    -

    The FrameConnectionService helps manage and access different trading frames, like minute, hour, or daily data, within your backtesting process. It acts as a central hub, automatically directing requests to the correct frame implementation based on the current context.

    -

    Think of it as a smart router for frame-related operations.

    -

    To improve performance, it keeps a record (memoizes) of the frame instances it creates, so it doesn't have to recreate them every time.

    -

    It also lets you define the timeframe for your backtest, specifying the start and end dates, allowing you to focus on specific periods of time. When running in live mode, there are no frame constraints.

    -

    The service relies on other services like the logger, schema, and method context services to function.

    -

    You can use getFrame to fetch a frame by name – the first time, it creates it, and subsequent calls return the stored version. getTimeframe helps determine the boundaries for backtesting a particular symbol.

    -

    The ExchangeValidationService helps you keep track of your trading exchanges and make sure they're properly set up before you start trading. Think of it as a central place to register all your exchanges and then quickly check if they’re ready to go.

    -

    It allows you to register new exchanges using addExchange, which essentially adds them to its record. Before any trading actions, you can use validate to confirm that an exchange exists and is correctly configured. The service also remembers the results of these validations, so things run faster the second time around. Finally, the list function lets you see all the exchanges currently registered in the system.

    -

    Essentially, it's a handy tool for organization and error prevention in your trading setup.

    -

    This class, ExchangeUtils, provides helpful tools for working with different cryptocurrency exchanges. It acts as a central point for common exchange-related tasks, ensuring consistency and validation.

    -

    Think of it as a helper that simplifies interacting with exchanges and retrieving data like candles, order books, and trades.

    -

    It's designed to be easily accessible throughout your backtesting framework.

    -

    Here's a bit more detail on what it does:

    +

    Essentially, this utility class gives you the tools to examine and document your most profitable trading moments.

    +

    This service is designed to keep track of and record the highest profit events achieved during a trading backtest. It actively monitors a data stream, specifically highestProfitSubject, and whenever a new highest profit record is detected, it creates a detailed log entry.

    +

    These log entries, formatted as JSONL, contain a wealth of information about the profitable trade, including timestamps, the traded symbol, the strategy used, the exchange, the timeframe, and details of the signal that triggered the trade – like its ID, position, current price, and original order parameters (take profit and stop loss).

    +

    To begin tracking these events, you need to subscribe to the highestProfitSubject. Importantly, subscribing only happens once; subsequent attempts simply return the same unsubscribe function. To stop the service from logging further profit records, you must call the unsubscribe function that was returned when you initially subscribed.

    +

    This service helps generate and store reports about the highest profit achieved in your trading strategies. It listens for data about those profits and organizes them based on the symbol, strategy, exchange, and timeframe you're using.

    +

    You can subscribe to receive profit data, and the system ensures you don't accidentally subscribe multiple times. Unsubscribing completely stops data collection and clears everything.

    +

    The tick method handles each incoming profit event, carefully categorizing it for storage.

    +

    You can request specific data—like the highest profit statistics for a particular symbol and strategy—or generate a full report in Markdown format. The report includes a table of recent events and a total count.

    +

    It can also write these reports directly to files, naming them according to the symbol, strategy, exchange, timeframe, and whether it's a backtest or live trade.

    +

    Finally, you can completely clear all accumulated data or selectively clear data for a single symbol/strategy/exchange/timeframe combination, effectively resetting the system for that specific scenario.

    +

    HeatUtils offers a simple way to create and manage portfolio heatmaps for your trading strategies. Think of it as a tool that gathers performance data – like profit, risk metrics, and trade counts – for each symbol your strategy has traded. It then organizes this data into a clear, visual report, typically in Markdown format.

    +

    You can easily retrieve this aggregated data using getData, which combines statistics from all closed trades for a specific strategy.

    +

    The getReport function builds a readable markdown table summarizing this portfolio performance, allowing you to quickly identify your top and bottom performers. You can also specify which columns to include in the report.

    +

    Finally, dump lets you save these reports directly to your hard drive, creating organized records of your strategy’s past performance. The report is saved as a Markdown file, named after your strategy, for easy sharing or archiving.

    +

    The HeatReportService helps you track and analyze your trading performance by recording when signals close and generate profit or loss. It listens for these "closed signal" events across all your symbols and saves the details to a database.

    +

    This service focuses specifically on closed signals – those that have resulted in a profit or loss.

    +

    To use it, you'll subscribe to receive these signal events, and when you're done, you can unsubscribe to stop the service. The subscription process prevents accidental multiple registrations. The stored data is then used to create heatmaps, giving you a portfolio-wide view of your trading activity. A logger helps with debugging, and a tick object handles processing and logging the closed signals.

    +

    This service creates a visual heatmap of your trading activity, aggregating data across all symbols and strategies. It’s designed to give you a quick, at-a-glance understanding of how your portfolio is performing.

    +

    The service listens for updates about closed trades. It then calculates key metrics for each individual symbol like total profit/loss, Sharpe Ratio, and maximum drawdown, as well as portfolio-level aggregates.

    +

    You can request these statistics using the getData method, which provides a snapshot of the aggregated data, or generate a nicely formatted markdown report with getReport or save it to a file with dump.

    +

    To reset the data, use clear— you can clear all data or target specific exchanges, frames, or backtest modes. The service also handles potential errors gracefully, especially mathematical ones, preventing issues like NaN or Infinity from breaking the calculations. Finally, subscribing to receive updates is managed through the subscribe and unsubscribe methods, ensuring you only receive the data you need and can stop when you choose.

    +

    This service helps you keep track of and confirm your trading timeframe configurations. Think of it as a central place to register and check if your timeframes are set up correctly.

    +

    It allows you to add new timeframes, ensuring they’re known to the system.

    +

    Before you try to use a timeframe in your backtest, you can use this service to verify it actually exists and is properly defined, which prevents errors. The service is designed to be efficient by remembering previous validation results.

    +

    Finally, you can easily get a complete list of all the timeframes you’ve registered.

    +

    The FrameSchemaService helps you keep track of your frame schemas, which are essentially blueprints for your trading strategies. It's designed to be type-safe, ensuring your schemas are consistent.

    +

    You can think of it as a central place to register and manage these schemas.

    +

    To add a new schema, use the register method. If a schema already exists, you can update it using the override method to change specific parts of it.

    +

    If you need to access a schema, simply use the get method, providing the schema's name.

    +

    Before a schema is added, it’s checked using validateShallow to make sure it has all the necessary properties and they are of the expected type. This helps catch errors early.

    +

    FrameCoreService is a central tool for managing timeframes within the backtesting process. It handles the creation of these timeframes, essentially providing the sequence of dates that your trading strategy will be tested against. Think of it as the engine that delivers the historical data for your backtest. It relies on other services to manage the connections and validation of this data. The getTimeframe function is its key feature – you use it to request a specific set of dates for a particular asset, which are then used as the basis for your backtest runs.

    +

    The FrameConnectionService acts as a central hub for managing and accessing different trading frames. It intelligently routes your requests to the correct frame implementation based on the active context.

    +

    To improve performance, it remembers previously created frames, so you don't have to recreate them every time. This service also handles the timeframe associated with a frame, defining the start and end dates for backtesting.

    +

    When operating in live mode, there are no frame constraints, and the frameName will be an empty string.

    +

    The getFrame function is the primary way to obtain a frame; it creates one if it doesn't already exist and caches it for later use. The getTimeframe function allows you to retrieve the specific dates used for backtesting a given symbol and frame.

    +

    It relies on several services: a logger for tracking activity, a schema service for defining frame structures, and a method context service to determine the active frame.

    +

    The ExchangeValidationService helps you keep track of your trading exchanges and make sure they’re set up correctly before you start trading. It acts like a central directory, letting you register new exchanges and quickly confirm that an exchange exists when you need it.

    +

    To help things run smoothly, it caches validation results so you don’t have to repeatedly check if an exchange is valid. You can add exchanges using addExchange, verify their existence with validate, and get a complete list of registered exchanges using list. Essentially, it's a tool for organizing and verifying your exchange configurations, preventing potential issues down the line.

    +

    ExchangeUtils helps you interact with different exchanges in a consistent way. It acts as a central hub, ensuring that requests to exchanges are handled correctly and validated.

    +

    Think of it as a helper that simplifies retrieving data like candles, average prices, and order books from exchanges. It’s designed to be easily used throughout your trading strategies.

    +

    Here's what it can do:

      -
    • Fetching Data: It can grab historical candles (price data over time), calculate average prices, get the latest closing price, and retrieve order books and aggregated trades.
    • -
    • Formatting: It automatically handles formatting trade quantities and prices to match the specific rules of each exchange, which is crucial for accurate backtesting.
    • -
    • Date Handling: When retrieving historical data, it intelligently calculates the appropriate date range to avoid look-ahead bias, ensuring accurate results.
    • -
    • Isolated Instances: It maintains separate instances for each exchange to prevent data conflicts and ensure stability.
    • -
    • Raw Data Access: You can get raw, unfiltered candle data with precise control over date ranges and limits.
    • +
    • It can fetch historical candle data for a specific trading pair, automatically calculating the right timeframe.
    • +
    • It calculates the VWAP (volume-weighted average price) based on recent trades.
    • +
    • It can retrieve the closing price of the most recent candle.
    • +
    • It formats trade quantities and prices to match the specific rules of each exchange, preventing errors.
    • +
    • It fetches order books and aggregated trades.
    • +
    • It retrieves raw candle data with more control over the date range and number of candles.
    -

    The ExchangeSchemaService helps keep track of information about different cryptocurrency exchanges, ensuring everything is structured correctly.

    -

    It uses a special system for storing these exchange details in a way that avoids errors caused by incorrect data types.

    -

    You can add new exchanges using addExchange(), and retrieve existing ones by their name using get().

    -

    Before adding a new exchange, validateShallow() checks that the essential properties are present and of the right type.

    -

    If you need to update an existing exchange's details, override() lets you make changes to specific parts of the schema.

    -

    The service relies on internal components for logging and managing its storage.

    -

    This service acts as a central hub for interacting with exchanges within the backtesting framework. It seamlessly combines exchange connection details with information about the current backtest, like the specific date and time being simulated.

    -

    Essentially, it provides a unified way to request data like historical candles, order books, and trade information from an exchange, ensuring that these requests are properly contextualized for the backtest environment.

    -

    The service offers several methods for retrieving exchange data, including functions for fetching candles (both historical and simulated future data for backtesting), calculating average prices, and formatting prices and quantities. Validation of the exchange configuration is handled efficiently to prevent repeated checks. The getRawCandles method is particularly powerful as it provides fine-grained control over the date range and amount of data retrieved.

    -

    The ExchangeConnectionService acts as a central hub for interacting with different cryptocurrency exchanges. It intelligently directs requests to the correct exchange based on the current trading context. To improve performance, it remembers previously used exchanges, avoiding redundant connections.

    -

    This service provides a range of functions for retrieving market data, including historical and real-time candles, average prices, order books, and aggregated trade data. It also handles the formatting of prices and quantities to ensure they comply with the specific rules of each exchange.

    -

    When fetching data, the service determines the exchange to use based on the method context. For historical data, it can retrieve candles within a specific date range. It also distinguishes between live and backtesting modes when calculating average prices – using real-time data live and VWAP calculations during backtesting. The service manages the complexities of different exchanges, allowing you to focus on your trading strategy.

    -

    The DumpAdapter provides a flexible way to store information generated during a backtest, allowing you to choose where that data is saved. It acts as a central point for dumping different types of data – messages, records, tables, text, errors, and JSON – and manages the underlying storage mechanism.

    -

    Initially, it defaults to saving data as markdown files, one per dump, in a structured directory. You can easily switch between different storage options, including in-memory storage, a no-op (dummy) mode that discards everything, or even plug in your own custom storage implementation.

    -

    To use the adapter, you must first activate it using enable(), which subscribes to signal lifecycle events to ensure data isn't stale. You deactivate it with disable(). The clear() method is useful when the working directory changes during testing to prevent issues with cached instances. There are also specific methods for dumping various data types like full message histories (dumpAgentAnswer), simple records (dumpRecord), tabular data (dumpTable), raw text (dumpText), errors (dumpError), and nested JSON objects (dumpJson).

    -

    The ConstantUtils class provides a set of pre-defined percentages designed to help manage take-profit and stop-loss levels in your trading strategies. These levels are calculated using a Kelly Criterion approach with an exponential risk decay, aiming for a balanced approach to risk and reward. Think of them as tiers for locking in profits or minimizing losses as a trade progresses.

    -

    For instance, when aiming for a final 10% profit, TP_LEVEL1 at 30% triggers when the price reaches 3% profit, TP_LEVEL2 at 60% triggers at 6% profit, and TP_LEVEL3 at 90% triggers at 9% profit. Similarly, SL_LEVEL1 at 40% and SL_LEVEL2 at 80% help manage potential losses by triggering stop-loss levels at those percentages of the overall risk exposure. These constants offer a quick way to incorporate these optimized levels into your backtesting and trading logic.

    -

    The ConfigValidationService acts as a safeguard for your trading configurations, making sure they're mathematically sound and capable of generating profits. It checks various parameters within the global configuration settings to catch potential errors before they impact your backtesting results.

    -

    This service pays close attention to percentages like slippage and fees, ensuring they aren't negative. It also verifies that your take-profit settings are realistic – specifically, that they account for all costs involved in a trade.

    -

    Beyond that, it enforces sensible relationships between settings, such as minimum and maximum values, and confirms that time-related parameters, like timeouts and retry counts, are positive whole numbers. Finally, it examines parameters related to how candles (price data) are handled.

    -

    Essentially, it's a built-in quality control system for your trading setup.

    -

    The ColumnValidationService helps keep your column configurations in good shape. It ensures that each column definition has all the necessary information, like a unique identifier, a display name, a formatting method, and visibility settings.

    -

    It verifies that these essential pieces are present and correctly formatted – making sure keys and labels are strings, and formatting and visibility are handled by functions.

    -

    Crucially, it makes sure that the unique identifiers you assign to each column don't clash within their group, preventing unexpected behavior. The service acts as a safeguard, helping to prevent errors and inconsistencies in your column data setup.

    -

    ClientSizing helps you figure out how much to trade based on a variety of approaches. It's a core component used when running strategies to determine the right position size. You can use different sizing methods like a simple percentage, the Kelly Criterion, or ATR-based sizing.

    -

    The system also allows you to set limits, ensuring your positions stay within specified boundaries—both minimum and maximum sizes, and a percentage limit of your overall capital. There’s even a way to add callbacks so you can validate the sizing decisions or record what's happening.

    -

    The calculate method is the key – it takes input parameters and returns the calculated position size.

    -

    ClientRisk helps manage risk across your trading strategies to prevent exceeding limits. It acts as a central authority, checking signals before they're executed to ensure your portfolio stays within defined boundaries.

    -

    It monitors things like the maximum number of concurrent positions you hold, and allows you to add custom checks tailored to your specific risk preferences, taking into account all currently active positions.

    -

    Several strategies can share the same ClientRisk instance, enabling a broader view of risk across your entire portfolio.

    -

    The checkSignal method determines if a signal should be allowed, considering factors like current price and timestamps. checkSignalAndReserve provides a safer, concurrent way to validate signals and temporarily reserve a place in the active position map, preventing other strategies from bypassing limits.

    -

    Finally, addSignal records when a new position is opened, and removeSignal cleans up when a position is closed, ensuring the system accurately reflects the current state of your portfolio. It’s important to always pair a successful checkSignalAndReserve with either addSignal or removeSignal to keep the risk map accurate and avoid accumulating stale reservations.

    -

    The ClientFrame is responsible for creating the timeline of data points your backtest will use. Think of it as the engine that builds the sequence of moments in time for your trading strategy to analyze. It avoids repeating work by remembering previously generated timelines, making the process more efficient.

    -

    You can customize how far apart these timeline points are, choosing intervals from one minute to one day.

    -

    The ClientFrame works closely with the core backtesting logic, providing the data needed to run simulations. Its primary function is to give you the ordered list of dates and times for your backtest. You can get a timeframe array for a specific trading symbol using the getTimeframe method, which handles caching to optimize performance.

    -

    This ClientExchange component acts as a bridge, providing access to exchange data for your backtesting and trading systems. It handles fetching historical and future market data – like candle data – and calculates important metrics like the Volume Weighted Average Price (VWAP). You can retrieve past candles, get data needed for signal generation in backtests, and format prices and quantities according to the specific rules of each exchange.

    -

    Here's a breakdown of its key functions:

    +

    Importantly, this utility operates as a single, shared instance, making it very convenient to use within your backtesting framework.

    +

    This service helps you keep track of and manage the information about different cryptocurrency exchanges. It's designed to be reliable and type-safe, ensuring the data you're using is consistent.

    +

    You can add new exchange details using addExchange(), and find them later by their name using get().

    +

    Before adding a new exchange, validateShallow() checks that it has all the necessary information and the correct format.

    +

    If an exchange already exists in the system, you can update specific parts of its details using override().

    +

    The service uses a registry to store these exchange schemas, and relies on other supporting services to log activity.

    +

    The ExchangeCoreService acts as a central hub for interacting with exchanges within the trading framework. It combines the connection to the exchange with the ability to inject important contextual information like the symbol being traded, the precise time of the trade, and whether it’s a backtest or live environment.

    +

    It handles tasks like retrieving historical price data (candles), obtaining future price data specifically for backtesting, calculating average prices, and fetching order book information.

    +

    This service also provides methods for formatting prices and quantities, ensuring consistency and accuracy based on the trading context. It's designed to simplify common exchange operations and ensure the correct parameters are passed to the exchange for both historical analysis and real-time trading. The validation process for the exchange is optimized to avoid unnecessary repetition.

    +

    The ExchangeConnectionService acts as a central hub for interacting with different cryptocurrency exchanges within the backtest-kit framework. It intelligently directs requests to the correct exchange implementation based on the current context. To optimize performance, it remembers (caches) frequently used exchange connections, so you don't have to repeatedly create them.

    +

    This service provides a comprehensive set of methods for retrieving market data, including historical and future candles, average prices, order books, and aggregated trades. It handles formatting prices and quantities to match the specific rules of each exchange, ensuring compatibility and accuracy.

    +

    Key functionalities include fetching candles, retrieving average prices (differing between backtesting and live modes), and accessing order book and trade data. It intelligently routes requests using the currently configured exchange based on the execution context, providing a unified and consistent interface for all exchange operations. You can also request raw candle data with specific date ranges.

    +

    The DumpAdapter helps you save important data generated during your backtesting process. Think of it as a flexible system for capturing information like messages, records, tables, text, errors, and JSON objects. By default, it saves this data as individual Markdown files, organized by signal ID, bucket name, and a unique identifier.

    +

    You have options for where this data is stored: you can choose to keep it in memory, discard it entirely (useful for testing), or even plug in your own custom storage solutions. Before using it, you need to activate the adapter; afterwards, you can deactivate it.

    +

    The adapter keeps track of its instances to avoid memory issues and clears these when a signal is cancelled. It’s also designed to handle changes in your working directory, ensuring that it uses the correct file paths for saving data. You can clear all the cached instances by calling the clear method.

    +

    The CronUtils class provides a way to schedule tasks that run at specific intervals, especially useful when running multiple backtests in parallel. It ensures that these tasks fire only once, even if multiple backtests attempt to execute them simultaneously.

    +

    Think of it as a traffic controller for scheduled events, making sure each task runs exactly once, even if several tests are trying to run it at the same time.

    +

    Here's a breakdown of how it works:

      -
    • Candle Data Retrieval: It efficiently fetches historical and future candles, ensuring data accuracy and preventing "look-ahead bias" (using future data to influence past decisions). You can specify limits and date ranges.
    • -
    • VWAP Calculation: It quickly calculates the VWAP, a key indicator reflecting the average price a security has traded at throughout the day, using the last few 1-minute candles.
    • -
    • Price & Quantity Formatting: This component formats prices and quantities correctly for each specific exchange, ensuring you're submitting orders and interpreting data in the right format.
    • -
    • Order Book and Aggregated Trades: You can retrieve order book snapshots and aggregated trade data, also taking into account the current time to avoid look-ahead bias.
    • -
    • Efficiency: The code is optimized for performance, using prototype functions to minimize memory usage.
    • +
    • +

      Registration: You register tasks with names and intervals. If you register the same name again, the previous entry is replaced, but any handlers currently running for that name will complete first.

      +
    • +
    • +

      Single-Shot Coordination: This is key. When multiple backtests try to trigger the same task at the same time, CronUtils makes sure only one handler actually runs. The others wait.

      +
    • +
    • +

      Watermark Feature: It tracks the last boundary reached, preventing tasks from being triggered multiple times on the same interval, even if virtual time jumps around.

      +
    • +
    • +

      Memory Management: It includes utilities to clean up old entries to free up memory, though this doesn't impact correctness – it’s more about performance.

      +
    • +
    • +

      Lifecycle Integration: It can be enabled to automatically integrate with backtesting lifecycle events like start, idle time, and scheduled tasks, so you don't need to manually wire everything.

      +
    • +
    • +

      Complete Reset: There's a dispose function that completely wipes all registered tasks and lifecycle hooks, useful for completely clearing the system.

      +
    -

    Essentially, this component makes it easier and more reliable to interact with different exchanges and gather the data you need for robust backtesting and trading strategies.

    -

    The ClientAction component is the central hub for managing and running your custom action handlers within the backtest-kit framework. Think of it as a conductor orchestrating your strategy's logic. It takes care of setting up your handlers, ensuring they only initialize and clean up once, and routing different types of events – like signals from live trading or backtesting – to the appropriate handler methods.

    -

    It's designed to be flexible, letting you plug in handlers that manage things like your application's state, track what's happening, send notifications (via Telegram, Discord, or email), or gather analytics. The signal methods handle the core event routing, while specific methods like breakevenAvailable or partialProfitAvailable respond to particular trading milestones. Finally, signalSync provides a critical gate for position management using limit orders.

    -

    Essentially, ClientAction simplifies the process of integrating custom logic into your trading strategies.

    -

    This class provides a straightforward way to cache the results of your functions, particularly those used within a trading strategy. It’s designed to avoid redundant calculations by storing and reusing results based on time intervals or persisting them to disk.

    -

    The main feature is the fn method, which allows you to wrap a regular function to automatically cache its results, invalidating the cache when the timeframe changes.

    -

    There's also a file method for caching asynchronous functions to disk – this is handy for expensive computations that you want to reuse across multiple runs, like complex data analysis. This method stores the files within a specific directory structure, making management a bit easier.

    -

    To ensure clean operation, you can dispose of specific function caches using dispose, completely clear all caches with clear, or reset file cache counters with resetCounter. This is especially useful if your project’s working directory changes frequently, preventing cache conflicts.

    -

    Essentially, CacheUtils streamlines the process of caching, optimizing your trading framework's performance and ensuring consistent results across different strategy iterations.

    -

    This class, BrokerBase, provides a foundation for building connections to different trading platforms like exchanges. Think of it as a customizable middleman between your trading strategy and the actual exchange. It handles tasks like placing orders (both initial and adjustments like stop-loss orders), recording trades, and sending notifications.

    -

    You don’t have to re-implement every aspect of interacting with an exchange – this base class provides default behaviors for logging important events, which you can override to tailor it for your specific exchange.

    -

    Here's how it works:

    -
      -
    1. Initialization: You’ll initialize the broker using waitForInit(). This is where you’d connect to the exchange and authenticate.
    2. -
    3. Event Handling: As your trading strategy runs, different events occur – like opening a position, hitting a stop-loss, or making a partial profit. The BrokerBase provides "commit" methods for these events (onSignalOpenCommit, onSignalCloseCommit, etc.). These are triggered automatically based on the actions your strategy takes.
    4. -
    5. Customization: You extend the BrokerBase class and override these "commit" methods to add the actual exchange interaction logic – placing the orders and managing your positions.
    6. -
    7. Logging: All events are automatically logged, helping you track what's happening and debug any issues.
    8. -
    -

    The BrokerBase simplifies the process of integrating your trading strategy with different exchanges, providing a structured way to handle trading operations and keep a record of all actions.

    -

    The BrokerAdapter acts as a middleman between your trading strategy and the actual broker, providing a layer of control and safety. It’s designed to ensure that trade-related actions are handled consistently, whether you're backtesting or live trading.

    -

    Think of it as a transaction manager for your trades. Before any changes are made to the core data (like your account balance), the BrokerAdapter steps in. If any of the commit functions (like opening a signal, setting a stop-loss, or averaging into a position) fail, it prevents the changes from happening, ensuring your data remains consistent.

    -

    During backtesting, these commit functions are essentially ignored, allowing for quick simulations. When live trading, they forward the actions to your registered broker.

    -

    You configure the BrokerAdapter by registering a broker adapter - this can be an existing broker object or a class that creates one. You then 'enable' the adapter to start listening for specific events, like trade openings and closings. When you’re done, you can ‘disable’ it, which stops the listening. A clear function allows you to refresh the broker connection if your environment changes.

    -

    This class offers helpful tools for examining breakeven events, providing insights into your trading strategy's performance. It acts as a central point for accessing and presenting breakeven data collected by the system.

    -

    You can easily retrieve aggregated statistics like the total number of breakeven events for a specific symbol and strategy.

    -

    It can also generate detailed markdown reports outlining each breakeven event, including vital information like the symbol, strategy used, entry price, breakeven price, and timestamp.

    -

    Finally, it provides a convenient way to save these reports directly to files, organized by symbol and strategy name, for later review or sharing. Think of it as your automated breakeven report generator and data analyst.

    -

    The BreakevenReportService is designed to keep track of when your trading signals reach their breakeven point. It acts as a listener, capturing these significant events – moments when a trade has recovered its initial investment.

    -

    All the details about these breakeven achievements, like the specifics of the signal, are logged and stored in a database.

    -

    To use it, you'll subscribe to receive these breakeven events. This subscription is managed to prevent issues with overlapping registrations. When you’re finished, you can unsubscribe to stop receiving the events. The service also utilizes a logger for debugging purposes, and ensures the data is reliably saved to your database through the ReportWriter.

    -

    The BreakevenMarkdownService helps you automatically create and store reports detailing breakeven events for your trading strategies. It listens for these events and organizes them, then transforms the information into readable markdown tables that summarize the data.

    -

    You can subscribe to the service to receive these events, and then use the tickBreakeven method to process them. The service keeps track of events for each symbol and strategy combination, ensuring everything is neatly separated.

    -

    It provides a way to access key statistics about the breakeven events and can generate full reports for a specific trading symbol and strategy. The reports are saved to disk in a standardized format, making it easy to review and analyze your trading performance. You can even clear out the stored data when it's no longer needed, either selectively or completely.

    -

    This service acts as a central point for managing breakeven calculations within the trading system. Think of it as a middleman; it receives requests related to breakeven, logs them for monitoring purposes, and then passes them on to another service responsible for the actual calculations.

    -

    It's designed to be easily integrated into the core trading strategy – specifically, it's injected along with other necessary settings. This keeps things organized and makes it simple to track how breakeven is being handled across the entire system.

    -

    Several validation services are also integrated to ensure the strategy, associated risks, exchanges, and other elements exist before processing requests.

    -

    The validate method is a quick check to confirm that a strategy and its related risk configurations are valid, and it remembers previous checks to avoid repeating them unnecessarily.

    -

    The check method determines if a breakeven trigger should occur, and if so, it signals that action. Finally, the clear method resets the breakeven state when a trading signal ends.

    -

    This service helps keep track of breakeven points for trading signals. It’s designed to efficiently manage and reuse breakeven calculations, creating a dedicated instance for each signal ID.

    -

    Think of it as a factory that produces and manages "ClientBreakeven" objects, making sure each signal has its own record. These objects are cached, so you don't have to recreate them every time you need to check or clear the breakeven status.

    -

    When a signal is checked, this service either finds an existing breakeven record or creates one, then performs the actual calculation. Similarly, when a signal closes, the service clears the breakeven record and removes it from the cache. It relies on other services for logging, actions, and managing time, and it sends notifications about breakeven events.

    -

    This class provides tools for running and analyzing backtests. It's designed to be used as a central place to interact with the backtest system.

    -

    You can use it to run a backtest, execute it in the background without immediate results, or retrieve information about a specific backtest, such as the current pending signal or the position's profitability. The class handles things like DCA entries, partial profit/loss takes, and trailing stop/take adjustments.

    -

    Here's a breakdown of what you can do:

    +

    The ConstantUtils class provides a set of predefined percentages designed to help manage your trading strategies using a Kelly Criterion-inspired approach with risk decay. It’s focused on setting Take Profit (TP) and Stop Loss (SL) levels that adapt based on how far the price has moved towards its ultimate goal.

    +

    Think of it as having multiple checkpoints along the way.

    +

    For example, TP_LEVEL1 triggers when the price reaches 30% of the total distance to your final profit target, allowing you to lock in a smaller profit quickly. TP_LEVEL3 triggers closer to the end, at 90% of the distance, ensuring nearly all profits are secured.

    +

    Similarly, SL_LEVEL1 is an early warning at 40% of the way to your potential loss, helping to minimize risk, while SL_LEVEL2 at 80% ensures you exit completely before a major downturn.

    +

    These percentages are fixed values within the class and designed to be used as reference points for determining when to adjust your position.

    +

    The ConfigValidationService is like a safety net for your trading setup. It meticulously checks your global configuration parameters to make sure everything is mathematically sound and designed to actually make money.

    +

    It verifies that percentages like slippage and fees are non-negative, ensuring you’re not unintentionally losing money. It also makes sure your take-profit distance is large enough to cover those costs, guaranteeing a profit when your target is reached.

    +

    Beyond the basics, it ensures relationships between parameters make sense – like stop-loss distances being properly ordered – and that time-related settings and candle data requests are reasonable. Essentially, it's designed to catch potential errors before they impact your backtesting results.

    +

    This service, ColumnValidationService, helps keep your column configurations clean and reliable. It ensures that each column definition follows a specific set of rules, preventing common errors and making your data more consistent.

    +

    Essentially, it checks if all your column definitions have the necessary information – a key, a label, a format, and visibility settings – and verifies that these values are of the correct type and unique where they need to be. Think of it as a safeguard against typos or incorrect configurations that could cause problems later on.

    +

    The service performs this validation on your column configurations and flags any issues it finds. It uses a logger service to record any validation problems encountered.

    +

    The ClientSizing class helps determine how much of an asset to trade in each situation. It provides several ways to calculate position sizes, including fixed percentages, Kelly criterion, and using Average True Range (ATR). You can also set limits on the minimum or maximum position size and a percentage of your capital that can be used for any single trade.

    +

    It’s designed to work alongside your trading strategy, and it even allows for custom callbacks so you can validate the sizing or log the results.

    +

    The calculate method is the core function – it takes input parameters and returns the calculated position size.

    +

    ClientRisk helps manage risk across your trading strategies, ensuring they don't exceed pre-defined limits. It acts as a central control point for portfolio-level risk, preventing signals that could lead to unwanted exposure.

    +

    Think of it as a gatekeeper that validates trading signals before they're executed. It can restrict the total number of simultaneous positions and allows for custom risk checks, giving you fine-grained control. Multiple strategies can share the same ClientRisk instance, which enables cross-strategy risk analysis and coordinated risk management.

    +

    The ClientRisk system tracks active positions using a map that dynamically updates. This map helps determine if a new signal should be allowed. There’s an initialization process, and it attempts to persist the active positions (though this is skipped during backtesting).

    +

    The checkSignal method is the core validation process, examining signals against configured rules and providing callbacks for both allowed and rejected signals. checkSignalAndReserve is a specialized, thread-safe version that secures a place in the position map before validation, preventing race conditions when strategies run concurrently. It's important to follow up on a successful checkSignalAndReserve with either adding the signal (addSignal) or removing the placeholder (removeSignal).

    +

    Finally, addSignal is used to register a newly opened position, while removeSignal cleans up when a position is closed, ensuring the risk map remains accurate.

    +

    The ClientFrame helps generate the timeline of data your backtest will use. Think of it as creating a schedule of when your trading decisions will be made.

    +

    It's designed to efficiently create these timelines, avoiding unnecessary repetition by remembering previously generated timelines.

    +

    You can customize how far apart these timeline points are, from short intervals like one minute to longer ones like a day.

    +

    It also allows you to add custom checks or record important events during this timeline creation. Essentially, it's a core component that ensures your backtest runs smoothly through the historical data. The getTimeframe property is the main function you'll use to actually generate this timeline for a specific asset.

    +

    The ClientExchange class acts as a bridge, providing a way to access and format exchange data for your backtesting framework. It handles fetching historical and future candle data, calculates VWAP prices, and formats prices and quantities according to exchange-specific rules. Think of it as a standardized interface for interacting with different exchanges.

    +

    You can use it to retrieve candles from the past (getCandles) or into the future (getNextCandles), which is particularly useful for simulating trades in a backtest. It also offers a method to calculate the Volume Weighted Average Price (getAveragePrice) based on recent trading activity.

    +

    Beyond just data retrieval, the ClientExchange also helps with presentation. formatPrice and formatQuantity ensure that data is displayed in the correct format for the specific exchange you are working with.

    +

    The getRawCandles method is powerful, allowing for flexible candle fetching with custom start and end dates and limits, all while carefully preventing look-ahead bias. Finally, it provides functionalities to retrieve order book data (getOrderBook) and aggregated trades (getAggregatedTrades), ensuring the framework gets the information it needs to simulate realistic trading conditions. The entire class is designed to be efficient and prevent common issues like look-ahead bias.

    +

    The ClientAction class is designed to manage and execute custom action handlers within the backtest-kit framework. Think of it as a central hub that brings together your custom logic with the core trading engine. It sets up and manages the lifecycle of these handlers, ensuring they're initialized only once and properly cleaned up when they're no longer needed.

    +

    It routes different types of events – signals from live or backtesting, breakeven updates, profit/loss milestones, and ping activity – to the appropriate methods within your action handler. This allows you to easily incorporate things like logging, notifications (via Telegram, Discord, or email), and analytics into your trading strategy.

    +

    The waitForInit and dispose methods use a special pattern to guarantee that initialization and cleanup only happen once. The signalSync method provides a crucial gate for managing positions using limit orders, ensuring any errors are handled appropriately. Essentially, ClientAction provides a structured way to plug in your custom functions to respond to various trading events.

    +

    CacheUtils helps you automatically store and reuse the results of your functions, making your trading strategies run faster and more efficiently. It acts as a central helper, making sure each function gets its own dedicated caching space.

    +

    The fn method is the main tool: it lets you wrap any function so it remembers its previous results based on time intervals. This is perfect for calculations that depend on historical data.

    +

    If your functions work asynchronously, the file method provides persistent caching – results are read from and written to disk, acting like a memory that lasts beyond the program's run. This is especially helpful for long-running tasks.

    +

    Sometimes you need a fresh start for your caching. dispose lets you completely remove the cached data for a specific function, forcing it to recalculate. clear resets all caching, which can be useful when your working directory changes. Lastly, resetCounter ensures file indices are reset if your working directory shifts.

    +

    This BrokerBase class is your starting point for connecting your trading strategy to a real exchange. Think of it as a template you customize to interact with platforms like Binance, Coinbase, or your own proprietary system. It handles the low-level details of sending orders, managing stop-loss and take-profit levels, and tracking your positions.

    +

    It comes with pre-built "no-op" functions that simply log what’s happening, meaning you only need to override the functions that are specific to your exchange's API. You'll customize this class to place orders, track position changes, and send notifications—whether that’s via Telegram, Discord, email, or a database.

    +

    The initialization process happens within the waitForInit() method, where you'll connect to your exchange and authenticate. Then, as your trading strategy runs, various event methods will be triggered:

      -
    • Run a backtest: run() initiates a backtest for a specific symbol and configuration.
    • -
    • Background backtesting: background() runs tests without needing to immediately see the results – good for testing things that don't directly produce data.
    • -
    • Signal information: Retrieve details about pending signals, including the breakeven price, the effective entry price (accounting for DCA), and potential profit/loss percentages.
    • -
    • Position details: Get information about the current position, such as the number of units held, the total cost, and the percentage of the position that has been closed.
    • -
    • Control the backtest: You can activate scheduled signals, close pending signals, commit partial profit or loss orders, and adjust trailing stop/take levels.
    • -
    • Data and Reporting: Access statistics and generate reports with key performance metrics.
    • -
    • Listing active tests: See a list of currently running backtests and their status.
    • +
    • onSignalOpenCommit: Used when opening a new trade.
    • +
    • onSignalCloseCommit: Used when closing a trade completely.
    • +
    • onPartialProfitCommit, onPartialLossCommit: Used for taking partial profits or limiting losses.
    • +
    • onTrailingStopCommit, onTrailingTakeCommit: Used to adjust stop-loss and take-profit levels dynamically.
    • +
    • onBreakevenCommit: Used to move the stop-loss to the entry price.
    • +
    • onAverageBuyCommit: Used when adding a new buy order in a DCA strategy.
    -

    The class is designed as a singleton, so you don't need to create instances, it's a single central point of access for backtest utilities.

    -

    The BacktestReportService helps you keep a detailed record of what's happening during your backtests. It diligently captures every signal event – when a signal is idle, opened, active, or closed – and saves that information to a database.

    -

    Think of it as a logbook for your trading strategy’s performance during the backtest.

    -

    You subscribe the service to the backtest’s signal emitter to receive these events, ensuring you don’t accidentally duplicate your subscriptions. The subscribe method returns a function to unsubscribe, letting you gracefully stop the event flow when needed. If you're no longer subscribed, unsubscribe simply does nothing. The service also utilizes a logger to output debugging information.

    -

    The BacktestMarkdownService helps you create and save reports about your backtesting results. It works by listening for events as your strategy runs and keeps track of the signals that have closed.

    -

    It uses a clever storage system to keep data separate for each symbol, strategy, exchange, timeframe, and backtest run, preventing interference between different tests.

    -

    You can use it to generate reports in markdown format, which are easy to read and share. These reports detail the information about the closed signals.

    -

    The service can automatically save these reports to a specific directory on your disk.

    -

    To use it, you subscribe to the backtest signal emitter to receive tick events, ensuring the service is active during your backtest. When you're done, you can unsubscribe to stop receiving those events. It offers ways to clear all accumulated data or just data for a specific backtest configuration.

    -

    This service helps you run backtests, taking care of automatically managing the context needed for your strategy. It simplifies the process by handling things like the strategy name, exchange, and frame—you don't have to pass them around explicitly.

    -

    Essentially, it acts as a layer on top of the private backtest logic, making it easier to use.

    -

    The run function is the core of this service; it executes the backtest for a specific symbol and provides a stream of results, like signals to open, close, or cancel positions. The context, containing details about the strategy and environment, is automatically passed to all related functions during the backtest.

    -

    It uses two key components: a logger service and the private backtest logic itself.

    -

    The BacktestLogicPrivateService helps run backtests in a way that's efficient with memory. It works by first gathering the timeframes you'll be testing from a frame service.

    -

    Then, it steps through each timeframe, processing them one by one. When a trading signal appears (like a buy or sell opportunity), it fetches the necessary candle data and executes the backtest logic.

    -

    The service skips ahead to the timeframe where the signal is closed, then it reports the outcome of the test. This process continues, giving you a continuous stream of results without storing everything in memory at once. You can even stop the backtest early if needed.

    -

    To make it work, it needs dependencies like services that handle strategy logic, exchange data, frame management, and more. The run method is where you start the backtest process for a specific symbol, and it produces a stream of results.

    -

    The BacktestCommandService is like a central hub for running backtests within the system. It provides a straightforward way to access and utilize backtesting capabilities.

    -

    It's essentially a helper, built on top of the more detailed BacktestLogicPublicService, making it easy to inject and use for backtest related tasks.

    -

    Several internal services, such as those handling validation and logging, are also managed and accessed through this service.

    -

    The core function is run, which lets you execute a backtest for a specific trading symbol. You also need to supply details like the strategy, exchange, and frame names for the backtest to work correctly. It returns a sequence of results representing what would have happened on each tick during the backtest.

    -

    This service helps you keep track of and double-check your action handlers, which are essential components for your trading strategies. It acts like a central manager for all your action handlers, making sure they are properly registered before anything runs.

    -

    It lets you register new action handlers using addAction, and then easily verify their existence with validate. This prevents errors later on.

    -

    To speed things up, it remembers the results of those validations, so it doesn't have to repeat the checks every time. Finally, list provides a way to see all the action handlers currently registered.

    -

    Essentially, it's your safety net and organizational tool for managing action handlers within the backtest-kit framework.

    -

    The ActionSchemaService acts as a central hub for managing and organizing action schemas within your trading framework. It ensures that action schemas are registered correctly, validated for consistency, and easily accessible when needed.

    -

    It uses a type-safe system to store these schemas, helping to prevent errors. The service also checks that action handlers only use the methods they're supposed to, promoting cleaner and more reliable code.

    -

    Here's a breakdown of its capabilities:

    +

    You don't need to handle event handling in backtest mode, as it's automatically skipped. There's no explicit cleanup process - any necessary teardown should happen within waitForInit() or handled externally.

    +

    The BrokerAdapter acts as a gatekeeper for interactions with your broker, ensuring that all trading actions are handled safely and consistently. It sits between your trading logic and the actual broker connection. Think of it as a transaction manager – if anything goes wrong during a trade, it prevents changes to your core data.

    +

    During backtesting, these broker interactions are skipped entirely to speed things up. When you're live trading, the BrokerAdapter forwards the information to your actual broker connection.

    +

    Here's what it does:

      -
    • Registration: You can register new action schemas, and the service will verify they're properly structured and that the methods used are valid. It won't allow duplicate action names.
    • -
    • Validation: Before a schema is registered, a quick check confirms that all the required properties are present and of the correct type.
    • -
    • Updates: You can modify existing action schemas – just provide the changes you want, and the service will merge them with the original. This avoids the need to re-register everything from scratch.
    • -
    • Retrieval: When needed, you can easily fetch a specific action schema by its name, allowing other parts of the system to use the configuration details.
    • +
    • Connects to your broker: You register your broker adapter using useBrokerAdapter.
    • +
    • Handles key trading actions: It intercepts and controls common actions like opening/closing signals, setting profit/loss targets, trailing stops, take profits, breakeven points, and average buy entries, before applying them. If an error occurs during any of these actions, the trade doesn’t actually happen.
    • +
    • Manages Events: Automatically passes opening and closing signal events to your broker.
    • +
    • Enables/Disables Connection: enable() activates the connection, while disable() disconnects. clear() resets the broker connection, useful if you’re switching between different environments (like different test folders).
    • +
    • Lazy Initialization: The connection to your broker isn't created until it's actually needed, and it's cached to avoid unnecessary work.
    -

    The service keeps track of which actions are available and how they should be handled, ultimately contributing to a more organized and robust trading environment.

    -

    The ActionProxy is a safety net for your custom trading logic within the backtest-kit framework. Think of it as a wrapper around your code that ensures things don't break unexpectedly. It's designed to prevent errors in your action handlers—the functions you write to define how your trading strategy reacts to market events—from crashing the entire backtesting or live trading system.

    -

    Whenever one of your action handlers encounters a problem, the ActionProxy catches the error, logs it, and keeps the process moving. It’s like having a built-in error handler. This is achieved through try...catch blocks surrounding all the action methods.

    -

    You don't directly create ActionProxy instances; instead, you use fromInstance() to wrap an existing handler.

    -

    The ActionProxy handles a range of events, including:

    +

    The BreakevenUtils class helps you analyze and report on breakeven events in your trading system. Think of it as a central place to gather and present information about when your trades reached their breakeven points.

    +

    It gathers data from breakeven events and provides tools to view that data in different ways.

    +

    You can retrieve statistical summaries of breakeven events to understand trends and patterns. +It can create detailed markdown reports that show individual breakeven events in a table, including key details like symbol, strategy, entry price, and when they occurred. +Finally, you can easily save these reports to files for later review or sharing. This is especially useful for documenting backtest results or tracking performance.

    +

    The BreakevenReportService helps you keep track of when your trading signals reach their breakeven point. It's designed to listen for these "breakeven" moments and record them, including all the relevant details about the signal that achieved it.

    +

    Think of it as a dedicated reporter for your profitable trades – it makes sure you don't miss any significant milestones.

    +

    To get it working, you'll use the subscribe method to connect it to your signal source. This also prevents accidental duplicate subscriptions. When you’re done monitoring, use the unsubscribe method to stop the service. This ensures your resources aren't unnecessarily used. The tickBreakeven property handles the actual processing and logging of these breakeven events to a database. A logger service is also integrated to help you debug if needed.

    +

    The BreakevenMarkdownService helps you automatically create and save reports detailing breakeven events for your trading strategies. It listens for breakeven signals and organizes the information received for each symbol and strategy you're tracking.

    +

    The service generates clear, readable markdown tables that summarize these events, including statistics like the total number of breakeven occurrences. These reports are then saved as files, making it easy to review and analyze your strategy's performance.

    +

    You can subscribe to receive these signals and unsubscribe when you no longer need them. The service manages the data storage effectively, ensuring each combination of symbol, strategy, exchange, frame, and backtest has its own isolated space.

    +

    Functions are provided to retrieve data and reports, and to clear the accumulated data—either for a specific combination or everything at once. Finally, the service automatically saves the generated reports to disk, organizing them in a dedicated directory.

    +

    This service, the BreakevenGlobalService, acts as a central point for managing and tracking breakeven calculations within the system. It's designed to be a single place where strategies can access these calculations, making the overall architecture cleaner and more organized.

    +

    Essentially, it sits between the strategies and the actual connection layer that handles the breakeven logic. Every time a breakeven calculation happens, it's logged here first, offering a clear audit trail of what's going on.

    +

    The service relies on several other services (like validation and schema services) to ensure everything is set up correctly, and it gets these dependencies from the system's dependency injection container. It delegates the heavy lifting – creating and managing the ClientBreakeven – to a separate connection service.

    +

    You’ll find it injected into the ClientStrategy with specific parameters. The check function decides if a breakeven should trigger, and the clear function resets the breakeven state when a signal ends. These actions are always logged through this global service before being passed on to the connection service.

    +

    The BreakevenConnectionService helps track and manage breakeven points for your trading signals. It keeps track of these calculations, creating a special object for each signal to avoid redundant work.

    +

    Think of it as a smart factory: it builds and manages these signal-specific breakeven objects, ensuring they’re properly set up with logging and notification capabilities.

    +

    It’s designed to work alongside other parts of the system, automatically creating and cleaning up these breakeven objects as signals are used and closed. The service is key for keeping track of your trading strategy's performance and risk.

    +

    Here's a quick rundown of what it does:

      -
    • init: Initial setup.
    • -
    • signal: General signal processing.
    • -
    • signalLive: Signal processing in live trading.
    • -
    • signalBacktest: Signal processing during backtesting.
    • -
    • breakevenAvailable: Handling breakeven events.
    • -
    • partialProfitAvailable: Managing partial profit targets.
    • -
    • partialLossAvailable: Managing partial loss limits.
    • -
    • pingScheduled: Dealing with scheduled signals.
    • -
    • pingActive: Managing active positions.
    • -
    • pingIdle: Handling periods of inactivity.
    • -
    • riskRejection: Responding to risk management rejections.
    • -
    • dispose: Clean up when the strategy finishes.
    • +
    • It creates and caches a breakeven tracking object for each signal.
    • +
    • It handles the actual calculations and checks for breakeven conditions.
    • +
    • It cleans up when signals are no longer needed, preventing memory issues.
    • +
    • It integrates with logging and event systems to keep you informed.
    -

    Notably, the signalSync method is an exception to this error-handling rule, as errors here need to propagate for proper limit order handling. Essentially, ActionProxy helps keep your trading strategy stable and prevents errors from bringing down the whole system.

    -

    The ActionCoreService acts as a central coordinator for handling actions within your trading strategies. It’s responsible for automatically managing and executing these actions based on the defined strategy schema.

    -

    Think of it as a traffic controller for events; it receives information (like market ticks, breakeven notifications, or scheduled pings) and distributes them to the appropriate actions within a strategy.

    -

    Here's a breakdown of its key functionalities:

    +

    This class provides helpful tools for running and analyzing backtests within the framework. It acts as a central point for common backtesting operations, simplifying tasks like starting tests and retrieving data.

    +

    You can easily run backtests for specific symbols and strategies, or execute them in the background for tasks like logging without immediate feedback. It also allows you to check for the existence of pending or scheduled signals, and calculate important metrics like position cost, potential profit, and time remaining.

    +

    The framework provides several methods to manipulate an active position – partially closing it, adjusting stop-loss or take-profit levels, or moving the stop to breakeven. This makes it easy to experiment with different risk management strategies during backtesting.

    +

    Finally, this class can generate comprehensive reports, export data, and list currently running backtest instances for monitoring and analysis. It's designed to be a convenient resource for anyone working with backtests.

    +

    The BacktestReportService is designed to keep a detailed record of what's happening during your backtests. It listens for signals generated by your trading strategies and saves information about them—when a signal is idle, when it’s opened, active, or closed—into a database.

    +

    Think of it as a way to create a logbook for your backtests.

    +

    You can use this log to analyze how your strategies performed and to find any bugs or unexpected behavior.

    +

    To use it, you'll subscribe to receive these signals, and then you can unsubscribe when you’re finished. The system prevents accidentally subscribing multiple times, ensuring efficient operation.

    +

    The BacktestMarkdownService helps you create and save reports detailing the performance of your trading strategies during backtesting. It listens for updates as your strategies trade, carefully recording how each trade closes.

    +

    It organizes this information, building tables that show detailed signal information. These reports are then saved as markdown files, making them easy to read and share, located in the logs/backtest directory.

    +

    The service uses a clever storage system that keeps data separate for each symbol, strategy, exchange, timeframe, and backtest run, ensuring that your reports are accurate and organized.

    +

    You can request data, generate reports, or clear out old data as needed. It also provides ways to subscribe to and unsubscribe from real-time updates during backtesting.

    +

    This service helps you run backtests, handling the behind-the-scenes details of managing context. It simplifies the backtesting process by automatically providing information about your strategy, exchange, and data frame to the various functions used during the test.

    +

    The BacktestLogicPublicService relies on a private service to perform the actual backtesting logic.

    +

    It also includes services for handling time, frame schemas, and exchange connections.

    +

    The run method is the main way to start a backtest. You tell it which symbol to test and the name of the strategy, exchange and data frame you are using, and it will stream back the results, taking care of passing along all necessary context.

    +

    The BacktestLogicPrivateService handles the complex process of running a backtest, particularly when dealing with asynchronous operations. It works by first retrieving the timeframes from a frame service, then processing each timeframe one at a time.

    +

    When a trading signal appears (e.g., a buy or sell opportunity), the service fetches the necessary historical price data (candles) and executes the backtest logic. It then pauses the process until that signal is resolved (closed).

    +

    Importantly, the service delivers results in a stream, meaning it doesn't store everything in memory at once – this is efficient for backtests involving large datasets. You can also stop the backtest early if needed.

    +

    The run method is the main entry point; you provide a symbol (like "BTCUSDT"), and it returns an async generator that yields results representing the tick results - opened, closed, cancelled or scheduled. The service relies on other core services for managing things like logging, strategy execution, exchange interactions, frame management, action execution and context.

    +

    The BacktestCommandService acts as a central point for running backtests within the system. It provides a straightforward way to access and execute backtesting operations, essentially simplifying how you trigger and manage backtest processes.

    +

    It relies on several other services for its work, including logging, schema handling, validation of risk, actions, strategies, exchanges, and frames. These services ensure that the backtest is properly configured and adheres to the defined rules.

    +

    The core functionality lies in the run method, which allows you to initiate a backtest for a specific trading symbol. When you run a backtest, you also provide information about the strategy, exchange, and frame being used, which helps contextualize the simulation. The method returns a series of results, detailing the outcomes of each tick, including scheduled, opened, closed, and cancelled orders.

    +

    The ActionValidationService helps keep track of your action handlers—those pieces of code that respond to different events or actions in your system. Think of it as a central place to register and confirm that your handlers are properly set up.

    +

    You can use it to add new action handlers using addAction, essentially telling the service about a new handler and its configuration. Before you actually use a handler, validate makes sure it's there, preventing errors later on.

    +

    To speed things up, the service remembers the results of previous validations – this is called memoization – so it doesn’t have to repeatedly check the same handlers. Finally, list gives you a complete overview of all the action handlers currently registered, which is useful for debugging or understanding your system’s setup. It is important to note that it has properties like loggerService and _actionMap to manage its internal workings.

    +

    The ActionSchemaService acts as a central place to manage and keep track of the different actions your application can perform. It makes sure your action definitions are consistent and follow the rules you've set.

    +

    It uses a type-safe system to store these action definitions, ensuring they’re structured correctly. When you define an action, this service checks that it only uses the allowed public methods, helping to prevent errors.

    +

    You can register new actions, making sure they're valid before they're added to the system. If you need to make small changes to an existing action, you can override specific parts of it without having to redefine the entire action. Finally, it provides a way to easily retrieve the full configuration for an action when needed.

    +

    Here's a quick breakdown of what it does:

      -
    • Action Management: It reads the list of actions defined in a strategy’s schema and orchestrates their execution.
    • -
    • Validation: It ensures the strategy setup and related components (exchange, frame, risks, and actions) are valid and consistent.
    • -
    • Event Routing: It dispatches specific events – like market updates, breakeven notifications, or scheduled tasks – to the corresponding actions in a predefined order. There are distinct routing methods for backtesting, live trading, and signal synchronization.
    • -
    • Initialization & Cleanup: It handles the initialization of actions before a strategy runs, including loading any necessary persisted data. It also cleans up actions when a strategy finishes.
    • -
    • Synchronization: signalSync provides a way to ensure all actions agree on position-related events.
    • +
    • Registration: Adds new action definitions and validates them.
    • +
    • Validation: Checks that action handlers are structured correctly and using approved methods.
    • +
    • Overrides: Allows you to update parts of existing actions.
    • +
    • Retrieval: Provides a way to get the full action definition.
    -

    The service relies on various other services for its operations, like validation and schema retrieval, making it a vital piece of the framework's infrastructure. You generally won't interact with this service directly; it operates behind the scenes to manage action execution.

    -

    This component acts as a central hub for directing different actions within your trading strategies. It intelligently routes specific events – like signals, breakeven updates, or scheduled pings – to the correct action handler, based on details like the action's name, the strategy and frame it belongs to, and whether it's a backtest. To improve performance, it remembers previously created action handlers, so it doesn't need to recreate them every time.

    -

    Think of it as a traffic controller, ensuring each signal gets to the right place without unnecessary work.

    -

    Here's a breakdown of what it does:

    +

    The loggerService property lets you hook into the service’s logging. _registry is an internal storage for the action schemas.

    +

    The ActionProxy acts as a safety net when using custom trading logic within the backtest framework. It's designed to prevent errors in your custom code from bringing down the entire backtesting process. Think of it as a protective layer around your code.

    +

    It handles important events like signal generation, profit/loss adjustments, scheduled tasks, and more. Whenever these events are triggered, ActionProxy steps in and wraps your code in a “try-catch” block.

    +

    If any errors occur within your custom code during these events, they are logged, reported, and the system keeps running without crashing. The errors don’t halt the backtest, allowing you to identify and fix issues later.

    +

    Crucially, it uses a factory pattern for creating instances, ensuring all your action handlers are properly wrapped for safety. Some actions like signalSync bypass this error capture to allow more direct error propagation. The dispose method also cleans up resources safely, just like the other methods.

    +

    The ActionCoreService is like a central dispatcher for your trading strategies. It's responsible for orchestrating how actions (like buying, selling, or adjusting positions) are handled by your strategies.

    +

    It gathers action lists from strategy definitions and then systematically invokes the appropriate handlers for each action. This ensures actions are processed in the intended order and in response to different events.

    +

    Here's a breakdown of its key functions:

      -
    • Action Routing: It takes an action name and related context information (strategy, exchange, frame, and backtest mode) and figures out which action handler should receive the event.
    • -
    • Caching: It keeps a record of the action handlers it's already created, so it can quickly reuse them, making things faster. The cached instances are specific to a combination of strategy, exchange, and frame, meaning different strategies and frames have their own isolated sets of action handlers.
    • -
    • Event Handling: It provides various methods (signal, signalLive, breakevenAvailable, etc.) for sending different types of events to the appropriate action handlers. Each of these methods takes a relevant event and context information.
    • -
    • Initialization & Cleanup: It has functions to initialize and dispose of these action handlers, ensuring they're properly set up and cleaned up when needed. The clear function specifically helps to clear the cached action handlers.
    • +
    • Validation: Before anything happens, it carefully checks that your strategy setup (name, exchange, frame) and all related actions and risks are valid. It avoids repeated checks by caching these validations.
    • +
    • Initialization: When a strategy starts, the service prepares all the individual action components by loading any persisted data they may have.
    • +
    • Signal Routing: It routes various signals (market data, timer events, risk events) to the correct actions, differentiating between backtesting, live trading, and scheduled activities. Different signal types have distinct handling functions (signal, signalLive, signalBacktest).
    • +
    • Event Handling: It also manages specific events like breakeven confirmations, partial profit/loss adjustments, and ping notifications, passing them to appropriate actions.
    • +
    • Synchronization: The signalSync function acts as a gatekeeper, making sure all actions agree before a key step (like opening or closing a position).
    • +
    • Cleanup: When a strategy finishes, the dispose function cleans up all action components and releases resources.
    • +
    • Data Clearing: The clear function allows you to clean out action data, either for a specific action or for all actions across all strategies.
    -

    This component is designed to be efficient and reliable, ensuring the correct actions are executed at the right time.

    -

    The ActionBase class is your foundation for extending the backtest-kit framework. It’s designed to help you add custom logic and integrations to your trading strategies, like handling notifications, logging events, or connecting to external services. Think of it as a starting point where you can plug in your own code to extend the core functionality.

    -

    When you create a custom action handler, you inherit from ActionBase, which provides default behavior for many common tasks, such as logging events automatically. You only need to implement the methods relevant to your specific needs, avoiding repetitive boilerplate code. The framework calls these methods at specific points during the strategy execution – like when a signal is generated, a breakeven point is hit, or a position reaches a profit/loss milestone.

    -

    The lifecycle of an action handler starts with its creation and continues through initialization (init), where you can set up any resources it needs. Events like signals (signal, signalLive, signalBacktest) are then triggered as the strategy runs, allowing your code to react to those events. Finally, dispose gets called at the end to clean up everything.

    -

    Each event method (like signal, breakevenAvailable, partialProfitAvailable) has a version for live trading and backtesting, so you can tailor your actions differently based on the environment. The riskRejection method informs you when a signal is blocked by risk management. The ping methods track the state of the strategy (scheduled, active, or idle) allowing for monitoring of these states.

    -
    +

    Essentially, the ActionCoreService handles the complex logistics of managing and executing actions within your trading strategies, keeping everything organized and consistent.

    +

    The ActionConnectionService acts as a central dispatcher, directing different types of events to the correct action handlers within your trading strategy. It intelligently routes signals—like new ticks, breakeven updates, partial profit/loss adjustments, and scheduled pings—to the corresponding ClientAction based on the action's name, the strategy and frame it belongs to, and whether it's a backtest or live run.

    +

    To optimize performance, it utilizes caching; once an action is created, it’s stored and reused for subsequent requests with the same action name, strategy, exchange, and frame. This ensures that action instances aren't repeatedly initialized, saving valuable resources.

    +

    The service relies on several other services like loggerService, actionSchemaService, and strategyCoreService to function correctly, and provides methods for initializing, disposing, and clearing these cached actions when needed. Specifically, the getAction method is key—it’s responsible for retrieving or creating these action handlers, and its caching mechanism is crucial for efficiency. Each event type—signal, signalLive, signalBacktest, breakevenAvailable, and so on—has its dedicated routing method.

    +

    This class, ActionBase, is designed to help you easily extend the trading framework with custom actions. Think of it as a starting point for adding extra functionality without having to write a lot of boilerplate code. It handles things like logging events automatically, so you don't need to implement those parts yourself.

    +

    You can use it to build custom logic for managing things like state, sending notifications (via email, Discord, etc.), tracking performance, or responding to specific trading conditions.

    +

    The class follows a specific lifecycle: it initializes when created, receives various event notifications as the strategy runs (like signals, breakeven points, profit milestones, etc.), and then cleans up when the strategy is finished. Each of these events is triggered based on what's happening in the trading process.

    +

    Specifically, there are distinct events for live vs. backtest modes. You'll get signalLive for actions that should only run in live trading, and signalBacktest for actions specific to backtesting. You also have methods for handling events related to risk management and monitoring the state of the strategy. The dispose method is vital for cleaning up any resources you might use in your custom actions.

    +

    Function beginContext

    Wraps a function so it always runs outside any active method or execution context.

    +

    When the wrapped function is called, beginContext checks whether +MethodContextService or ExecutionContextService currently have an active +scope and, if so, escapes each one with runOutOfContext before invoking run. +This prevents accidental context leakage from a caller into a logically independent +operation (e.g. an internal runner that must establish its own fresh context).

    +

    The returned wrapper preserves the original function's parameter and return types, +so it is a transparent drop-in replacement.

    +
    const runInContextInternal = beginContext(
    async (run: () => Promise<void>, context: IRunContext) => {
    return await MethodContextService.runInContext(
    () => ExecutionContextService.runInContext(run, context),
    context,
    );
    },
    ); +
    + +
    • Type Parameters

      • T extends (...args: any[]) => any

        Type of the wrapped function.

        +

      Parameters

      • run: T

        Function to wrap.

        +

      Returns (...args: Parameters<T>) => ReturnType<T>

      A new function with the same signature as run that escapes any +active context before executing.

      +
    + + + + + + + + + diff --git a/functions/types.beginTime.html b/functions/types.beginTime.html new file mode 100644 index 0000000000000000000000000000000000000000..1f8e503a032600ffaae89f0e89bdd1342bd7133d --- /dev/null +++ b/functions/types.beginTime.html @@ -0,0 +1,39 @@ +beginTime | backtest-kit

    Function beginTime

    Wraps a function to execute it outside of the current execution context if one exists.

    +

    This utility ensures that the wrapped function runs in isolation from any existing +ExecutionContext, preventing context leakage and unintended context sharing between +async operations.

    +
    const myFunction = async (param: string) => {
    // This code will run outside of any ExecutionContext
    return param.toUpperCase();
    };

    const wrappedFunction = beginTime(myFunction);
    const result = wrappedFunction('hello'); // Returns 'HELLO' +
    + +
    // Usage with trycatch wrapper
    const safeFunction = trycatch(
    beginTime(async (id: number) => {
    // Function body runs isolated from parent context
    return await fetchData(id);
    })
    ); +
    + +
    • Type Parameters

      • T extends (...args: any[]) => any

        Function type with any parameters and return type

        +

      Parameters

      • run: T

        The function to be wrapped and executed outside of context

        +

      Returns (...args: Parameters<T>) => ReturnType<T>

      A curried function that accepts the original function's parameters +and executes it outside of the current context if one exists

      +
    + + + + + + + + + diff --git a/functions/types.cacheCandles.html b/functions/types.cacheCandles.html index d89b0c3d35a316f7f65b1e7cb0a438ac33be60b6..f655f5ede7e8172fa55dc38c21a3f1746a1f0d79 100644 --- a/functions/types.cacheCandles.html +++ b/functions/types.cacheCandles.html @@ -2,7 +2,7 @@ Runs a check-then-warm pipeline with one retry: validates the cache first and, on a miss, downloads the missing data and re-validates.

    Parameters

    • params: ICacheCandlesParams

      Combined cache parameters with optional lifecycle callbacks

      -

    Returns Promise<void>

    +

    Returns Promise<void>

    Function listenAfterEnd

    • Subscribes to after end events with queued async processing. +Emits when the engine has completed processing a strategy execution for a symbol. +Events are processed sequentially in order received, even if callback is async. +Uses queued wrapper to prevent concurrent execution of the callback.

      +

      Parameters

      • fn: (event: AfterEndContract) => void

        Callback function to handle after end events

        +

      Returns () => void

      Unsubscribe function to stop listening to events

      +
    + + + + + + + + + diff --git a/functions/types.listenAfterEndOnce.html b/functions/types.listenAfterEndOnce.html new file mode 100644 index 0000000000000000000000000000000000000000..ac305536f99d7d001e7c5cef8d3774372425e52b --- /dev/null +++ b/functions/types.listenAfterEndOnce.html @@ -0,0 +1,31 @@ +listenAfterEndOnce | backtest-kit

    Function listenAfterEndOnce

    • Subscribes to filtered after end events with one-time execution. +Listens for events matching the filter predicate, then executes callback once +and automatically unsubscribes.

      +

      Parameters

      • filterFn: (event: AfterEndContract) => boolean

        Predicate to filter which events trigger the callback

        +
      • fn: (event: AfterEndContract) => void

        Callback function to handle the filtered event (called only once)

        +

      Returns () => void

      Unsubscribe function to cancel the listener before it fires

      +
    + + + + + + + + + diff --git a/functions/types.listenBacktestProgress.html b/functions/types.listenBacktestProgress.html index 419aefe067b04999ad213e48179b259797be780b..7d00c9deddf7b177f5d74a2bcba0e1c0602588e8 100644 --- a/functions/types.listenBacktestProgress.html +++ b/functions/types.listenBacktestProgress.html @@ -7,7 +7,7 @@ Uses queued wrapper to prevent concurrent execution of the callback.

    import { listenBacktestProgress, Backtest } from "backtest-kit";

    const unsubscribe = listenBacktestProgress((event) => {
    console.log(`Progress: ${(event.progress * 100).toFixed(2)}%`);
    console.log(`${event.processedFrames} / ${event.totalFrames} frames`);
    console.log(`Strategy: ${event.strategyName}, Symbol: ${event.symbol}`);
    });

    Backtest.background("BTCUSDT", {
    strategyName: "my-strategy",
    exchangeName: "binance",
    frameName: "1d-backtest"
    });

    // Later: stop listening
    unsubscribe();
    -
    +

    Function listenBeforeStart

    • Subscribes to before start events with queued async processing. +Emits when the engine is about to start a new strategy execution for a symbol. +Events are processed sequentially in order received, even if callback is async. +Uses queued wrapper to prevent concurrent execution of the callback.

      +

      Parameters

      Returns () => void

      Unsubscribe function to stop listening to events

      +
    + + + + + + + + + diff --git a/functions/types.listenBeforeStartOnce.html b/functions/types.listenBeforeStartOnce.html new file mode 100644 index 0000000000000000000000000000000000000000..91372a974aa17ed980788455260c31c42a9385b0 --- /dev/null +++ b/functions/types.listenBeforeStartOnce.html @@ -0,0 +1,31 @@ +listenBeforeStartOnce | backtest-kit

    Function listenBeforeStartOnce

    • Subscribes to filtered before start events with one-time execution. +Listens for events matching the filter predicate, then executes callback once +and automatically unsubscribes.

      +

      Parameters

      • filterFn: (event: BeforeStartContract) => boolean

        Predicate to filter which events trigger the callback

        +
      • fn: (event: BeforeStartContract) => void

        Callback function to handle the filtered event (called only once)

        +

      Returns () => void

      Unsubscribe function to cancel the listener before it fires

      +
    + + + + + + + + + diff --git a/functions/types.listenBreakevenAvailable.html b/functions/types.listenBreakevenAvailable.html index b5dce38fcdbc79a916e8069c0d23b595cb03e763..6c6c237c967791464f7f73494249f9061229fe0b 100644 --- a/functions/types.listenBreakevenAvailable.html +++ b/functions/types.listenBreakevenAvailable.html @@ -8,7 +8,7 @@ Uses queued wrapper to prevent concurrent execution of the callback.

    import { listenBreakeven } from "./function/event";

    const unsubscribe = listenBreakeven((event) => {
    console.log(`Signal ${event.data.id} reached breakeven`);
    console.log(`Symbol: ${event.symbol}, Position: ${event.data.position}`);
    console.log(`Entry: ${event.data.priceOpen}, Current: ${event.currentPrice}`);
    console.log(`Mode: ${event.backtest ? "Backtest" : "Live"}`);
    });

    // Later: stop listening
    unsubscribe();
    -
    +

    Function shutdown

    • Gracefully shuts down the backtest execution by emitting a shutdown event. This allows all components that subscribe to the shutdownEmitter to perform necessary cleanup before the process exits. The shutdown method is typically called in response to a termination signal (e.g., SIGINT) to ensure a clean exit.

      -

      Returns void

    +

    Returns void

    Function toPlainString

    Converts markdown content to plain text with minimal formatting

    +
    • Parameters

      • content: string

        Markdown string to convert

        +

      Returns string

      Plain text representation

      +
    + + + + + + + + + diff --git a/functions/types.toProfitLossDto.html b/functions/types.toProfitLossDto.html index 810564a86a4de8ca05cd25a3dfd99e519efe97e6..4df61caa1173eb87eb805e2a1ccfffa27764e14b 100644 --- a/functions/types.toProfitLossDto.html +++ b/functions/types.toProfitLossDto.html @@ -14,7 +14,7 @@ effectivePrice = costBasisAtClose / Σ(entry.cost/entry.price for entries[0..ent
    • Parameters

      • signal: Signal$2

        Closed signal with position details and optional partial history

      • priceClose: number

        Actual close price at final exit

      Returns IStrategyPnL

      PNL data with percentage, prices, and USD amounts

      -
    +

    Function waitForCandle

    Waits for the next candle interval to start and returns the timestamp of the new candle.

    • Parameters

      • interval: CandleInterval

        The candle interval (e.g., "1m", "1h") to wait for.

      Returns Promise<number>

      A promise that resolves with the timestamp (in milliseconds) of the next candle start.

      -
    +

    Function warmCandles

    • Pre-caches candles for a date range into persist storage. Downloads all candles matching the interval from from to to.

      Parameters

      • params: IWarmCandlesParams

        Cache parameters

        -

      Returns Promise<void>

    +

    Returns Promise<void>

    +backtest-kit

    Interface ActivateScheduledCommit

    Activate scheduled signal event.

    -
    interface ActivateScheduledCommit {
        action: "activate-scheduled";
        activateId?: string;
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • ActivateScheduledCommit

    Properties

    interface ActivateScheduledCommit {
        action: "activate-scheduled";
        activateId?: string;
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • ActivateScheduledCommit

    Properties

    action: "activate-scheduled"

    Discriminator for activate-scheduled action

    -
    activateId?: string

    Optional identifier for the activation reason (user-provided)

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price at time of activation

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (set during this activation)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price

    -
    priceTakeProfit: number

    Effective take profit price

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    activateId?: string

    Optional identifier for the activation reason (user-provided)

    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price at time of activation

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (set during this activation)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price

    +
    priceTakeProfit: number

    Effective take profit price

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface ActivateScheduledCommitNotification

    Activate scheduled commit notification. Emitted when a scheduled signal is activated by user (without waiting for priceOpen).

    -
    interface ActivateScheduledCommitNotification {
        activateId?: string;
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "activate_scheduled.commit";
    }

    Properties

    interface ActivateScheduledCommitNotification {
        activateId?: string;
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "activate_scheduled.commit";
    }

    Properties

    activateId? backtest createdAt currentPrice @@ -42,47 +42,47 @@ Emitted when a scheduled signal is activated by user (without waiting for priceO totalPartials type

    Properties

    activateId?: string

    Optional activation identifier (provided when user calls activateScheduled())

    -
    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when activation was executed

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price

    -
    priceTakeProfit: number

    Effective take profit price

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when activation was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "activate_scheduled.commit"

    Discriminator for type-safe union

    -
    +
    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when activation was executed

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price

    +
    priceTakeProfit: number

    Effective take profit price

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when activation was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "activate_scheduled.commit"

    Discriminator for type-safe union

    +

    Interface AfterEndContract

    Contract for the afterEnd lifecycle event of strategy execution.

    +

    Emitted by the engine after the strategy iterator has finished — whether +by reaching the end of the frame, being stopped via stopStrategy, +throwing an error, or being cancelled by the consumer (e.g., breaking out +of for await). Used by subscribers to perform teardown that should +happen exactly once per run: flushing buffers, closing files, computing +final aggregates, sending a "run completed" notification, etc.

    +

    Guarantees:

    +
      +
    • Fires exactly once per run() invocation, paired with the matching +BeforeStartContract event. The pairing holds for every termination +path including exceptions and external cancellation (delivered via the +generator's try/finally block).
    • +
    • Listener errors are caught and routed to the global errorEmitter; they +never propagate to the original caller.
    • +
    +

    Mode differences:

    +
      +
    • In backtest mode, when is the cursor position from TimeMetaService +at the moment of completion — i.e., the historical time of the last +processed candle. If the run was interrupted before any candle was +processed (e.g., empty frame, immediate cancellation), when falls +back to the frame's planned start date so it equals +BeforeStartContract.when for the same run. This means +afterEnd.when - beforeStart.when is always the real processed +duration, never an inflated planned one.
    • +
    • In live mode, when is the current wall-clock time aligned to the +1-minute boundary at the moment of emission.
    • +
    +

    BeforeStartContract — the paired initialization event.

    +
    interface AfterEndContract {
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        when: Date;
    }

    Properties

    backtest: boolean

    true if this event was emitted from a backtest run, false if from a +live trading run. Use this to branch listener logic without inspecting +other fields.

    +
    currentPrice: number

    Average symbol price observed at the moment the event was emitted, +fetched from ExchangeConnectionService.getAveragePrice(symbol). +Provided as a convenience so subscribers don't need to query the +exchange themselves.

    +
    exchangeName: string

    Name of the exchange that provided market data for this run.

    +
    frameName: string

    Name of the frame (timeframe / date range) the run used. Empty string +in live mode, where frames are not used.

    +
    strategyName: string

    Name of the strategy that was executed. Use this to demultiplex events +when subscribing globally to runs across multiple strategies on the +same symbol.

    +
    symbol: string

    Trading symbol the run was for (e.g., "BTCUSDT", "ETHUSDT"). +Matches the symbol from the paired BeforeStartContract.

    +
    timestamp: number

    Same value as when, expressed as milliseconds since the Unix epoch. +Provided so subscribers can avoid calling .getTime() and to keep the +payload trivially serialisable (e.g., for forwarding over IPC or +writing to a log).

    +
    when: Date

    Event time as a Date instance.

    +

    In backtest: cursor position from TimeMetaService at completion (the +time of the last processed candle), with fallback to the frame's +planned start date if no candle was processed.

    +

    In live: wall-clock now, aligned to 1-minute boundary.

    +

    Always equal to new Date(timestamp).

    +
    + + + + + + + + + diff --git a/interfaces/types.AverageBuyCommit.html b/interfaces/types.AverageBuyCommit.html index 2897fea0340ccba5bbe9279b18d5db5941dfb0b4..967b5212df83397f527b0e4bb817f42b12b90c0d 100644 --- a/interfaces/types.AverageBuyCommit.html +++ b/interfaces/types.AverageBuyCommit.html @@ -1,6 +1,6 @@ AverageBuyCommit | backtest-kit

    Interface AverageBuyCommit

    Average-buy (DCA) event. Emitted when a new averaging entry is added to an open position.

    -
    interface AverageBuyCommit {
        action: "average-buy";
        backtest: boolean;
        cost: number;
        currentPrice: number;
        effectivePriceOpen: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • AverageBuyCommit

    Properties

    interface AverageBuyCommit {
        action: "average-buy";
        backtest: boolean;
        cost: number;
        currentPrice: number;
        effectivePriceOpen: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • AverageBuyCommit

    Properties

    action backtest cost currentPrice @@ -28,35 +28,35 @@ Emitted when a new averaging entry is added to an open position.

    totalEntries totalPartials

    Properties

    action: "average-buy"

    Discriminator for average-buy action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    cost: number

    Cost of this averaging entry in USD

    -
    currentPrice: number

    Price at which the new averaging entry was executed

    -
    effectivePriceOpen: number

    Effective (averaged) entry price after this addition

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    -

    Unrealized PNL at the moment of average-buy (calculated after new entry added)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Original entry price (signal.priceOpen, unchanged by averaging)

    -
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    -
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    cost: number

    Cost of this averaging entry in USD

    +
    currentPrice: number

    Price at which the new averaging entry was executed

    +
    effectivePriceOpen: number

    Effective (averaged) entry price after this addition

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    +

    Unrealized PNL at the moment of average-buy (calculated after new entry added)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Original entry price (signal.priceOpen, unchanged by averaging)

    +
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    +
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface AverageBuyCommitNotification

    Average-buy (DCA) commit notification. Emitted when a new averaging entry is added to an open position.

    -
    interface AverageBuyCommitNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        currentPrice: number;
        effectivePriceOpen: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "average_buy.commit";
    }

    Properties

    interface AverageBuyCommitNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        currentPrice: number;
        effectivePriceOpen: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "average_buy.commit";
    }

    Properties

    backtest cost createdAt currentPrice @@ -43,48 +43,48 @@ Emitted when a new averaging entry is added to an open position.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    cost: number

    Cost of this averaging entry in USD

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Price at which the new averaging entry was executed

    -
    effectivePriceOpen: number

    Averaged (effective) entry price after this addition

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Original entry price (unchanged by averaging)

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when the averaging entry was executed

    -
    totalEntries: number

    Total number of DCA entries after this addition

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "average_buy.commit"

    Discriminator for type-safe union

    -
    +
    cost: number

    Cost of this averaging entry in USD

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Price at which the new averaging entry was executed

    +
    effectivePriceOpen: number

    Averaged (effective) entry price after this addition

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Original entry price (unchanged by averaging)

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when the averaging entry was executed

    +
    totalEntries: number

    Total number of DCA entries after this addition

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "average_buy.commit"

    Discriminator for type-safe union

    +

    Interface BeforeStartContract

    Contract for the beforeStart lifecycle event of strategy execution.

    +

    Emitted by the engine immediately before it begins iterating the strategy +for a given symbol — after validation and context setup, but before the +first candle/tick is processed. Used by subscribers to perform +initialization that should happen exactly once per run: opening log files, +resetting per-run accumulators, sending a "run started" notification, +snapshotting initial state, etc.

    +

    Guarantees:

    +
      +
    • Fires exactly once per run() invocation, before any signal is yielded.
    • +
    • Always paired with an AfterEndContract event for the same run, even if +the iterator is interrupted, throws, or is cancelled externally. If +beforeStart fires, afterEnd is guaranteed to fire afterwards.
    • +
    • Listener errors are caught and routed to the global errorEmitter; they +never abort the run.
    • +
    +

    Mode differences:

    +
      +
    • In backtest mode, when is the planned start of the frame (from +FrameSchemaService.startDate, aligned to 1-minute boundary). It is the +intended beginning of the historical replay, not wall-clock time.
    • +
    • In live mode, when is the current wall-clock time aligned to the +1-minute boundary.
    • +
    +

    AfterEndContract — the paired completion event.

    +
    interface BeforeStartContract {
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        when: Date;
    }

    Properties

    backtest: boolean

    true if this event was emitted from a backtest run, false if from a +live trading run. Use this to branch listener logic without inspecting +other fields.

    +
    currentPrice: number

    Average symbol price observed at the moment the event was emitted, +fetched from ExchangeConnectionService.getAveragePrice(symbol). +Provided as a convenience so subscribers don't need to query the +exchange themselves.

    +
    exchangeName: string

    Name of the exchange providing market data for this run.

    +
    frameName: string

    Name of the frame (timeframe / date range) for the run. Empty string in +live mode, where frames are not used.

    +
    strategyName: string

    Name of the strategy being executed. Use this to demultiplex events when +subscribing globally to runs across multiple strategies on the same +symbol.

    +
    symbol: string

    Trading symbol the run is for (e.g., "BTCUSDT", "ETHUSDT"). +Same value that was passed to Backtest.run / Live.run.

    +
    timestamp: number

    Same value as when, expressed as milliseconds since the Unix epoch. +Provided so subscribers can avoid calling .getTime() and to keep the +payload trivially serialisable (e.g., for forwarding over IPC or +writing to a log).

    +
    when: Date

    Event time as a Date instance.

    +

    In backtest: the planned start of the frame (aligned to 1-minute +boundary). Represents intended start time, not the moment of emission.

    +

    In live: wall-clock now, aligned to 1-minute boundary.

    +

    Always equal to new Date(timestamp).

    +
    + + + + + + + + + diff --git a/interfaces/types.BreakevenAvailableNotification.html b/interfaces/types.BreakevenAvailableNotification.html index 761ba210582c10ca34c27c07af9760cd2fe8f64b..e6e12272903a79f31569b5ae0974156642c32c3a 100644 --- a/interfaces/types.BreakevenAvailableNotification.html +++ b/interfaces/types.BreakevenAvailableNotification.html @@ -1,6 +1,6 @@ BreakevenAvailableNotification | backtest-kit

    Interface BreakevenAvailableNotification

    Breakeven available notification. Emitted when signal's stop-loss can be moved to breakeven (entry price).

    -
    interface BreakevenAvailableNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "breakeven.available";
    }

    Properties

    interface BreakevenAvailableNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "breakeven.available";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -41,46 +41,46 @@ Emitted when signal's stop-loss can be moved to breakeven (entry price).

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when breakeven became available

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position (breakeven level)

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when breakeven became available

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "breakeven.available"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when breakeven became available

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position (breakeven level)

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when breakeven became available

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "breakeven.available"

    Discriminator for type-safe union

    +

    Interface BreakevenCommit

    Breakeven event.

    -
    interface BreakevenCommit {
        action: "breakeven";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • BreakevenCommit

    Properties

    interface BreakevenCommit {
        action: "breakeven";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • BreakevenCommit

    Properties

    action: "breakeven"

    Discriminator for breakeven action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price at time of breakeven adjustment

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (set to priceOpen by breakeven action)

    -
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price at time of breakeven adjustment

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (set to priceOpen by breakeven action)

    +
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface BreakevenCommitNotification

    Breakeven commit notification. Emitted when breakeven action is executed.

    -
    interface BreakevenCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "breakeven.commit";
    }

    Properties

    interface BreakevenCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "breakeven.commit";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -41,46 +41,46 @@ Emitted when breakeven action is executed.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when breakeven was executed

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set, after breakeven this equals priceOpen)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when breakeven was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "breakeven.commit"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when breakeven was executed

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set, after breakeven this equals priceOpen)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when breakeven was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "breakeven.commit"

    Discriminator for type-safe union

    +

    Interface BreakevenEvent

    Unified breakeven event data for report generation. Contains all information about when signals reached breakeven.

    -
    interface BreakevenEvent {
        backtest: boolean;
        currentPrice: number;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        pendingAt?: number;
        pnl?: IStrategyPnL;
        position: string;
        priceOpen: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    interface BreakevenEvent {
        backtest: boolean;
        currentPrice: number;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        pendingAt?: number;
        pnl?: IStrategyPnL;
        position: string;
        priceOpen: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    backtest currentPrice note? originalPriceOpen? @@ -21,26 +21,26 @@ Contains all information about when signals reached breakeven.

    totalEntries? totalPartials?

    Properties

    backtest: boolean

    True if backtest mode, false if live mode

    -
    currentPrice: number

    Current market price when breakeven was reached

    -
    note?: string

    Human-readable description of signal reason

    -
    originalPriceOpen?: number

    Original entry price before DCA averaging (present when averageBuy was applied)

    -
    originalPriceStopLoss?: number

    Original stop loss price set at signal creation

    -
    originalPriceTakeProfit?: number

    Original take profit price set at signal creation

    -
    partialExecuted?: number

    Total executed percentage from partial closes

    -
    pendingAt?: number

    Timestamp when position became active (ms)

    -

    Unrealized PNL at the moment breakeven was reached

    -
    position: string

    Position type

    -
    priceOpen: number

    Entry price (breakeven level)

    -
    priceStopLoss?: number

    Stop loss exit price

    -
    priceTakeProfit?: number

    Take profit target price

    -
    scheduledAt?: number

    Timestamp when signal was created/scheduled (ms)

    -
    signalId: string

    Signal ID

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Event timestamp in milliseconds

    -
    totalEntries?: number

    Total number of DCA entries (present when averageBuy was applied)

    -
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    -
    +
    currentPrice: number

    Current market price when breakeven was reached

    +
    note?: string

    Human-readable description of signal reason

    +
    originalPriceOpen?: number

    Original entry price before DCA averaging (present when averageBuy was applied)

    +
    originalPriceStopLoss?: number

    Original stop loss price set at signal creation

    +
    originalPriceTakeProfit?: number

    Original take profit price set at signal creation

    +
    partialExecuted?: number

    Total executed percentage from partial closes

    +
    pendingAt?: number

    Timestamp when position became active (ms)

    +

    Unrealized PNL at the moment breakeven was reached

    +
    position: string

    Position type

    +
    priceOpen: number

    Entry price (breakeven level)

    +
    priceStopLoss?: number

    Stop loss exit price

    +
    priceTakeProfit?: number

    Take profit target price

    +
    scheduledAt?: number

    Timestamp when signal was created/scheduled (ms)

    +
    signalId: string

    Signal ID

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Event timestamp in milliseconds

    +
    totalEntries?: number

    Total number of DCA entries (present when averageBuy was applied)

    +
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    +

    Interface CancelScheduledCommit

    Cancel scheduled signal event.

    -
    interface CancelScheduledCommit {
        action: "cancel-scheduled";
        backtest: boolean;
        cancelId?: string;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • CancelScheduledCommit

    Properties

    interface CancelScheduledCommit {
        action: "cancel-scheduled";
        backtest: boolean;
        cancelId?: string;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • CancelScheduledCommit

    Properties

    action: "cancel-scheduled"

    Discriminator for cancel-scheduled action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    cancelId?: string

    Optional identifier for the cancellation reason (user-provided)

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -

    Total PNL of the closed position (including all entries and partials)

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    cancelId?: string

    Optional identifier for the cancellation reason (user-provided)

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +

    Total PNL of the closed position (including all entries and partials)

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface CancelScheduledCommitNotification

    Cancel scheduled commit notification. Emitted when a scheduled signal is cancelled before activation.

    -
    interface CancelScheduledCommitNotification {
        backtest: boolean;
        cancelId?: string;
        createdAt: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "cancel_scheduled.commit";
    }

    Properties

    interface CancelScheduledCommitNotification {
        backtest: boolean;
        cancelId?: string;
        createdAt: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "cancel_scheduled.commit";
    }

    Properties

    backtest cancelId? createdAt exchangeName @@ -33,38 +33,38 @@ Emitted when a scheduled signal is cancelled before activation.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    cancelId?: string

    Optional identifier for the cancellation reason (user-provided)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when cancellation was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "cancel_scheduled.commit"

    Discriminator for type-safe union

    -
    +
    cancelId?: string

    Optional identifier for the cancellation reason (user-provided)

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when cancellation was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "cancel_scheduled.commit"

    Discriminator for type-safe union

    +

    Interface ClosePendingCommit

    Close pending signal event.

    -
    interface ClosePendingCommit {
        action: "close-pending";
        backtest: boolean;
        closeId?: string;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • ClosePendingCommit

    Properties

    interface ClosePendingCommit {
        action: "close-pending";
        backtest: boolean;
        closeId?: string;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • ClosePendingCommit

    Properties

    action: "close-pending"

    Discriminator for close-pending action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    closeId?: string

    Optional identifier for the close reason (user-provided)

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -

    Total PNL of the closed position (including all entries and partials)

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    closeId?: string

    Optional identifier for the close reason (user-provided)

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +

    Total PNL of the closed position (including all entries and partials)

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface ClosePendingCommitNotification

    Close pending commit notification. Emitted when a pending signal is closed before position activation.

    -
    interface ClosePendingCommitNotification {
        backtest: boolean;
        closeId?: string;
        createdAt: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "close_pending.commit";
    }

    Properties

    interface ClosePendingCommitNotification {
        backtest: boolean;
        closeId?: string;
        createdAt: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "close_pending.commit";
    }

    Properties

    backtest closeId? createdAt exchangeName @@ -33,38 +33,38 @@ Emitted when a pending signal is closed before position activation.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    closeId?: string

    Optional identifier for the close reason (user-provided)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when close was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "close_pending.commit"

    Discriminator for type-safe union

    -
    +
    closeId?: string

    Optional identifier for the close reason (user-provided)

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when close was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "close_pending.commit"

    Discriminator for type-safe union

    +

    Interface CriticalErrorNotification

    Critical error notification. Emitted for fatal errors requiring process termination.

    -
    interface CriticalErrorNotification {
        backtest: boolean;
        error: object;
        id: string;
        message: string;
        type: "error.critical";
    }

    Properties

    interface CriticalErrorNotification {
        backtest: boolean;
        error: object;
        id: string;
        message: string;
        type: "error.critical";
    }

    Properties

    backtest: boolean

    Always false for error notifications (errors are from live context)

    -
    error: object

    Serialized error object with stack trace and metadata

    -
    id: string

    Unique notification identifier

    -
    message: string

    Human-readable error message

    -
    type: "error.critical"

    Discriminator for type-safe union

    -
    +
    error: object

    Serialized error object with stack trace and metadata

    +
    id: string

    Unique notification identifier

    +
    message: string

    Human-readable error message

    +
    type: "error.critical"

    Discriminator for type-safe union

    +

    Interface CronEntry

    Configuration for a registered cron entry.

    +
    interface CronEntry {
        handler: CronCallback;
        interval?: CandleInterval;
        name: string;
        symbols?: string[];
    }

    Properties

    handler: CronCallback

    Handler invoked on the first parallel tick to reach a new boundary.

    +
    interval?: CandleInterval

    Candle interval at whose boundaries the handler fires. +Same scale as CandleInterval used by Interval and Cache: +"1m" | "5m" | "1h" | "1d" etc.

    +

    If omitted, the entry switches to fire-once mode: the handler is +invoked on the very first matching tick (no boundary check) and never +again. If the handler throws, the entry is not marked as fired and +will retry on the next tick.

    +
    name: string

    Unique name of the entry. Used as the dedup key on register (re-registering +the same name replaces the previous entry) and as part of the singleshot +coordination key.

    +

    Must be non-empty and must not contain :: is reserved as the slot-key +segment separator and would otherwise create ambiguity between global and +fan-out fire-once keys.

    +
    symbols?: string[]

    Symbol whitelist that doubles as the fan-out switch.

    +
      +
    • Empty/undefined → global singleshot: across all parallel backtests +the handler runs once per boundary. The first symbol to reach the +boundary opens the slot; others await the same promise.
    • +
    • Non-empty → per-symbol fan-out: ticks whose symbol is not in the +list are skipped, and ticks whose symbol is in the list each open +their own slot. The handler runs once per whitelisted symbol per +boundary.
    • +
    +

    The same rule applies in fire-once mode: global → handler runs once +total; fan-out → once per whitelisted symbol.

    +

    Each symbol must not contain : (same reason as CronEntry.name).

    +
    + + + + + + + + + diff --git a/interfaces/types.CronHandle.html b/interfaces/types.CronHandle.html new file mode 100644 index 0000000000000000000000000000000000000000..7892db001a367a561f3d0650591013df69a79411 --- /dev/null +++ b/interfaces/types.CronHandle.html @@ -0,0 +1,30 @@ +CronHandle | backtest-kit

    Interface CronHandle

    Handle returned from register. Call it to unregister the entry — +equivalent to Cron.unregister(name).

    +
    const dispose = Cron.register({
    name: "x",
    interval: "1h",
    handler: async (symbol, when, backtest) => { ... },
    });
    dispose(); // unregisters +
    + +
    + + + + + + + + + diff --git a/interfaces/types.DoneContract.html b/interfaces/types.DoneContract.html index f23a9098f6569e76098abc81b6b2cad34aa264fa..2e06c74f48a1f5f2c06c39cd0d9021923822e33e 100644 --- a/interfaces/types.DoneContract.html +++ b/interfaces/types.DoneContract.html @@ -4,17 +4,17 @@ Contains metadata about the completed execution context.

    import { listenDone } from "backtest-kit";

    listenDone((event) => {
    if (event.backtest) {
    console.log("Backtest completed:", event.symbol);
    } else {
    console.log("Live trading completed:", event.symbol);
    }
    });
    -
    interface DoneContract {
        backtest: boolean;
        exchangeName: string;
        frameName: string;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface DoneContract {
        backtest: boolean;
        exchangeName: string;
        frameName: string;
        strategyName: string;
        symbol: string;
    }

    Properties

    backtest: boolean

    backtest - True if backtest mode, false if live mode

    -
    exchangeName: string

    exchangeName - Name of the exchange used in execution

    -
    frameName: string

    frameName - Name of the frame (empty string for live mode)

    -
    strategyName: string

    strategyName - Name of the strategy that completed

    -
    symbol: string

    symbol - Trading symbol (e.g., "BTCUSDT")

    -
    +
    exchangeName: string

    exchangeName - Name of the exchange used in execution

    +
    frameName: string

    frameName - Name of the frame (empty string for live mode)

    +
    strategyName: string

    strategyName - Name of the strategy that completed

    +
    symbol: string

    symbol - Trading symbol (e.g., "BTCUSDT")

    +

    Interface HeatmapStatisticsModel

    Portfolio heatmap statistics structure. Contains aggregated data for all symbols in the portfolio.

    -
    interface HeatmapStatisticsModel {
        portfolioAvgFallPnl: number;
        portfolioAvgPeakPnl: number;
        portfolioSharpeRatio: number;
        portfolioTotalPnl: number;
        portfolioTotalTrades: number;
        symbols: IHeatmapRow[];
        totalSymbols: number;
    }

    Properties

    interface HeatmapStatisticsModel {
        portfolioAvgFallPnl: number;
        portfolioAvgPeakPnl: number;
        portfolioSharpeRatio: number;
        portfolioTotalPnl: number;
        portfolioTotalTrades: number;
        symbols: IHeatmapRow[];
        totalSymbols: number;
    }

    Properties

    portfolioAvgFallPnl portfolioAvgPeakPnl portfolioSharpeRatio portfolioTotalPnl @@ -8,13 +8,13 @@ Contains aggregated data for all symbols in the portfolio.

    symbols totalSymbols

    Properties

    portfolioAvgFallPnl: number

    Trade-count-weighted average fall PNL across all symbols. Closer to 0 is better.

    -
    portfolioAvgPeakPnl: number

    Trade-count-weighted average peak PNL across all symbols. Higher is better.

    -
    portfolioSharpeRatio: number

    Portfolio-wide Sharpe Ratio

    -
    portfolioTotalPnl: number

    Portfolio-wide total PNL

    -
    portfolioTotalTrades: number

    Portfolio-wide total trades

    -
    symbols: IHeatmapRow[]

    Array of symbol statistics

    -
    totalSymbols: number

    Total number of symbols tracked

    -
    +
    portfolioAvgPeakPnl: number

    Trade-count-weighted average peak PNL across all symbols. Higher is better.

    +
    portfolioSharpeRatio: number

    Portfolio-wide Sharpe Ratio

    +
    portfolioTotalPnl: number

    Portfolio-wide total PNL

    +
    portfolioTotalTrades: number

    Portfolio-wide total trades

    +
    symbols: IHeatmapRow[]

    Array of symbol statistics

    +
    totalSymbols: number

    Total number of symbols tracked

    +

    Interface HighestProfitEvent

    Single highest profit event recorded for a position.

    -
    interface HighestProfitEvent {
        backtest: boolean;
        currentPrice: number;
        maxDrawdown: IStrategyPnL;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Properties

    interface HighestProfitEvent {
        backtest: boolean;
        currentPrice: number;
        maxDrawdown: IStrategyPnL;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Properties

    backtest: boolean

    Whether the event occurred in backtest mode

    -
    currentPrice: number

    Record price reached in the profit direction

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Position direction

    -
    priceOpen: number

    Effective entry price at the time of the update

    -
    priceStopLoss: number

    Stop loss price

    -
    priceTakeProfit: number

    Take profit price

    -
    signalId: string

    Signal unique identifier

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Unix timestamp in milliseconds when the record was set

    -
    +
    currentPrice: number

    Record price reached in the profit direction

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Position direction

    +
    priceOpen: number

    Effective entry price at the time of the update

    +
    priceStopLoss: number

    Stop loss price

    +
    priceTakeProfit: number

    Take profit price

    +
    signalId: string

    Signal unique identifier

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Unix timestamp in milliseconds when the record was set

    +

    Interface HighestProfitStatisticsModel

    Aggregated statistics model for highest profit events.

    -
    interface HighestProfitStatisticsModel {
        eventList: HighestProfitEvent[];
        totalEvents: number;
    }

    Properties

    interface HighestProfitStatisticsModel {
        eventList: HighestProfitEvent[];
        totalEvents: number;
    }

    Properties

    eventList: HighestProfitEvent[]

    Full list of recorded events (newest first)

    -
    totalEvents: number

    Total number of recorded events

    -
    +
    totalEvents: number

    Total number of recorded events

    +

    Interface IActivateScheduledCommitRow

    Queued activate scheduled commit.

    -
    interface IActivateScheduledCommitRow {
        action: "activate-scheduled";
        activateId?: string;
        backtest: boolean;
        signalId: string;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IActivateScheduledCommitRow

    Properties

    interface IActivateScheduledCommitRow {
        action: "activate-scheduled";
        activateId?: string;
        backtest: boolean;
        signalId: string;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IActivateScheduledCommitRow

    Properties

    action: "activate-scheduled"

    Discriminator

    -
    activateId?: string

    Activation ID (optional, for user-initiated activations)

    -
    backtest: boolean

    Whether running in backtest mode

    -
    signalId: string

    Signal ID being activated

    -
    symbol: string

    Trading pair symbol

    -
    +
    activateId?: string

    Activation ID (optional, for user-initiated activations)

    +
    backtest: boolean

    Whether running in backtest mode

    +
    signalId: string

    Signal ID being activated

    +
    symbol: string

    Trading pair symbol

    +

    Interface IAggregatedTradeData

    Aggregated trade data point. Represents a single trade that has occurred, used for detailed analysis and backtesting. Includes price, quantity, timestamp, and whether the buyer is the market maker (which can indicate trade direction).

    -
    interface IAggregatedTradeData {
        id: string;
        isBuyerMaker: boolean;
        price: number;
        qty: number;
        timestamp: number;
    }

    Properties

    id +
    interface IAggregatedTradeData {
        id: string;
        isBuyerMaker: boolean;
        price: number;
        qty: number;
        timestamp: number;
    }

    Properties

    id: string

    Unique identifier for the aggregated trade

    -
    isBuyerMaker: boolean

    Whether the buyer is the market maker (true if buyer is maker, false if seller is maker)

    -
    price: number

    Price at which the trade occurred

    -
    qty: number

    Quantity traded

    -
    timestamp: number

    Unix timestamp in milliseconds when the trade occurred

    -
    +
    isBuyerMaker: boolean

    Whether the buyer is the market maker (true if buyer is maker, false if seller is maker)

    +
    price: number

    Price at which the trade occurred

    +
    qty: number

    Quantity traded

    +
    timestamp: number

    Unix timestamp in milliseconds when the trade occurred

    +

    Interface IBidData

    Single bid or ask in order book.

    -
    interface IBidData {
        price: string;
        quantity: string;
    }

    Properties

    interface IBidData {
        price: string;
        quantity: string;
    }

    Properties

    Properties

    price: string

    Price level as string

    -
    quantity: string

    Quantity at this price level as string

    -
    +
    quantity: string

    Quantity at this price level as string

    +

    Interface IBreakevenCommitRow

    Queued breakeven commit.

    -
    interface IBreakevenCommitRow {
        action: "breakeven";
        backtest: boolean;
        currentPrice: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IBreakevenCommitRow

    Properties

    interface IBreakevenCommitRow {
        action: "breakeven";
        backtest: boolean;
        currentPrice: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IBreakevenCommitRow

    Properties

    action: "breakeven"

    Discriminator

    -
    backtest: boolean

    Whether running in backtest mode

    -
    currentPrice: number

    Price at which breakeven was set

    -
    symbol: string

    Trading pair symbol

    -
    +
    backtest: boolean

    Whether running in backtest mode

    +
    currentPrice: number

    Price at which breakeven was set

    +
    symbol: string

    Trading pair symbol

    +

    Interface ICandleData

    Single OHLCV candle data point. Used for VWAP calculation and backtesting.

    -
    interface ICandleData {
        close: number;
        high: number;
        low: number;
        open: number;
        timestamp: number;
        volume: number;
    }

    Properties

    interface ICandleData {
        close: number;
        high: number;
        low: number;
        open: number;
        timestamp: number;
        volume: number;
    }

    Properties

    close: number

    Closing price at candle end

    -
    high: number

    Highest price during candle period

    -
    low: number

    Lowest price during candle period

    -
    open: number

    Opening price at candle start

    -
    timestamp: number

    Unix timestamp in milliseconds when candle opened

    -
    volume: number

    Trading volume during candle period

    -
    +
    high: number

    Highest price during candle period

    +
    low: number

    Lowest price during candle period

    +
    open: number

    Opening price at candle start

    +
    timestamp: number

    Unix timestamp in milliseconds when candle opened

    +
    volume: number

    Trading volume during candle period

    +

    Interface IDumpContext

    Context required to identify a dump entry. Passed only through DumpAdapter - instances receive signalId, bucketName, and backtest via constructor.

    -
    interface IDumpContext {
        backtest: boolean;
        bucketName: string;
        description: string;
        dumpId: string;
        signalId: string;
    }

    Properties

    interface IDumpContext {
        backtest: boolean;
        bucketName: string;
        description: string;
        dumpId: string;
        signalId: string;
    }

    Properties

    backtest: boolean

    Flag indicating if the context is backtest or live; routed to Memory.writeMemory

    -
    bucketName: string

    Bucket name - groups dumps by strategy or agent name

    -
    description: string

    Human-readable label describing the dump contents; included in the BM25 index for Memory search and rendered in Markdown output

    -
    dumpId: string

    Unique identifier for this dump entry

    -
    signalId: string

    Signal identifier - scopes the dump to a specific trade

    -
    +
    bucketName: string

    Bucket name - groups dumps by strategy or agent name

    +
    description: string

    Human-readable label describing the dump contents; included in the BM25 index for Memory search and rendered in Markdown output

    +
    dumpId: string

    Unique identifier for this dump entry

    +
    signalId: string

    Signal identifier - scopes the dump to a specific trade

    +

    Interface IDumpInstance

    Interface for dump instance implementations. Instances are scoped to (signalId, bucketName) via constructor. Methods receive only the payload and dumpId.

    -
    interface IDumpInstance {
        dispose(): void;
        dumpAgentAnswer(
            messages: MessageModel<MessageRole>[],
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpError(
            content: string,
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpJson(json: object, dumpId: string, description: string): Promise<void>;
        dumpRecord(
            record: Record<string, unknown>,
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpTable(
            rows: Record<string, unknown>[],
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpText(
            content: string,
            dumpId: string,
            description: string,
        ): Promise<void>;
    }

    Methods

    interface IDumpInstance {
        dispose(): void;
        dumpAgentAnswer(
            messages: MessageModel<MessageRole>[],
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpError(
            content: string,
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpJson(json: object, dumpId: string, description: string): Promise<void>;
        dumpRecord(
            record: Record<string, unknown>,
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpTable(
            rows: Record<string, unknown>[],
            dumpId: string,
            description: string,
        ): Promise<void>;
        dumpText(
            content: string,
            dumpId: string,
            description: string,
        ): Promise<void>;
    }

    Methods

    dispose dumpAgentAnswer dumpError dumpJson @@ -9,33 +9,33 @@ Methods receive only the payload and dumpId.

    dumpTable dumpText

    Methods

    • Releases any resources held by this instance.

      -

      Returns void

    • Persist the full message history of one agent invocation.

      +

      Returns void

    • Persist the full message history of one agent invocation.

      Parameters

      • messages: MessageModel<MessageRole>[]

        Full chat history (system, user, assistant, tool)

      • dumpId: string

        Unique identifier for this dump entry

      • description: string

        Human-readable label describing the agent invocation context; included in the BM25 index for Memory search

        -

      Returns Promise<void>

    • Persist an error description.

      +

    Returns Promise<void>

    • Persist an error description.

      Parameters

      • content: string

        Error message or description to dump

      • dumpId: string

        Unique identifier for this dump entry

      • description: string

        Human-readable label describing the error context; included in the BM25 index for Memory search

        -

      Returns Promise<void>

    • Persist an arbitrary nested object as a fenced JSON block.

      +

    Returns Promise<void>

    • Persist an arbitrary nested object as a fenced JSON block.

      Parameters

      • json: object

        Arbitrary object to serialize with JSON.stringify

      • dumpId: string

        Unique identifier for this dump entry

      • description: string

        Human-readable label describing the object contents; included in the BM25 index for Memory search

      Returns Promise<void>

      Prefer dumpRecord - flat key-value structure maps naturally to markdown tables and SQL storage

      -
    • Persist a flat key-value record.

      +
    • Persist a flat key-value record.

      Parameters

      • record: Record<string, unknown>

        Arbitrary flat object to dump

      • dumpId: string

        Unique identifier for this dump entry

      • description: string

        Human-readable label describing the record contents; included in the BM25 index for Memory search

        -

      Returns Promise<void>

    • Persist an array of objects as a table. +

    Returns Promise<void>

    • Persist an array of objects as a table. Column headers are derived from the union of all keys across all rows.

      Parameters

      • rows: Record<string, unknown>[]

        Array of arbitrary objects to dump

      • dumpId: string

        Unique identifier for this dump entry

      • description: string

        Human-readable label describing the table contents; included in the BM25 index for Memory search

        -

      Returns Promise<void>

    • Persist a raw text or markdown string.

      +

    Returns Promise<void>

    • Persist a raw text or markdown string.

      Parameters

      • content: string

        Arbitrary text content to dump

      • dumpId: string

        Unique identifier for this dump entry

      • description: string

        Human-readable label describing the content; included in the BM25 index for Memory search

        -

      Returns Promise<void>

    +

    Returns Promise<void>

    Interface IExchangeSchema

    Exchange schema registered via addExchange(). Defines candle data source and formatting logic.

    -
    interface IExchangeSchema {
        callbacks?: Partial<IExchangeCallbacks>;
        exchangeName: string;
        formatPrice?: (
            symbol: string,
            price: number,
            backtest: boolean,
        ) => Promise<string>;
        formatQuantity?: (
            symbol: string,
            quantity: number,
            backtest: boolean,
        ) => Promise<string>;
        getAggregatedTrades?: (
            symbol: string,
            from: Date,
            to: Date,
            backtest: boolean,
        ) => Promise<IAggregatedTradeData[]>;
        getCandles: (
            symbol: string,
            interval: CandleInterval,
            since: Date,
            limit: number,
            backtest: boolean,
        ) => Promise<IPublicCandleData[]>;
        getOrderBook?: (
            symbol: string,
            depth: number,
            from: Date,
            to: Date,
            backtest: boolean,
        ) => Promise<IOrderBookData>;
        note?: string;
    }

    Properties

    interface IExchangeSchema {
        callbacks?: Partial<IExchangeCallbacks>;
        exchangeName: string;
        formatPrice?: (
            symbol: string,
            price: number,
            backtest: boolean,
        ) => Promise<string>;
        formatQuantity?: (
            symbol: string,
            quantity: number,
            backtest: boolean,
        ) => Promise<string>;
        getAggregatedTrades?: (
            symbol: string,
            from: Date,
            to: Date,
            backtest: boolean,
        ) => Promise<IAggregatedTradeData[]>;
        getCandles: (
            symbol: string,
            interval: CandleInterval,
            since: Date,
            limit: number,
            backtest: boolean,
        ) => Promise<IPublicCandleData[]>;
        getOrderBook?: (
            symbol: string,
            depth: number,
            from: Date,
            to: Date,
            backtest: boolean,
        ) => Promise<IOrderBookData>;
        note?: string;
    }

    Properties

    callbacks? exchangeName formatPrice? formatQuantity? @@ -9,20 +9,20 @@ Defines candle data source and formatting logic.

    getOrderBook? note?

    Properties

    callbacks?: Partial<IExchangeCallbacks>

    Optional lifecycle event callbacks (onCandleData)

    -
    exchangeName: string

    Unique exchange identifier for registration

    -
    formatPrice?: (
        symbol: string,
        price: number,
        backtest: boolean,
    ) => Promise<string>

    Format price according to exchange precision rules.

    +
    exchangeName: string

    Unique exchange identifier for registration

    +
    formatPrice?: (
        symbol: string,
        price: number,
        backtest: boolean,
    ) => Promise<string>

    Format price according to exchange precision rules.

    Optional. If not provided, defaults to Bitcoin precision on Binance (2 decimal places).

    Type declaration

      • (symbol: string, price: number, backtest: boolean): Promise<string>
      • Parameters

        • symbol: string

          Trading pair symbol

        • price: number

          Raw price value

        • backtest: boolean

          Whether running in backtest mode

        Returns Promise<string>

        Promise resolving to formatted price string

        -
    formatQuantity?: (
        symbol: string,
        quantity: number,
        backtest: boolean,
    ) => Promise<string>

    Format quantity according to exchange precision rules.

    +
    formatQuantity?: (
        symbol: string,
        quantity: number,
        backtest: boolean,
    ) => Promise<string>

    Format quantity according to exchange precision rules.

    Optional. If not provided, defaults to Bitcoin precision on Binance (8 decimal places).

    Type declaration

      • (symbol: string, quantity: number, backtest: boolean): Promise<string>
      • Parameters

        • symbol: string

          Trading pair symbol

        • quantity: number

          Raw quantity value

        • backtest: boolean

          Whether running in backtest mode

        Returns Promise<string>

        Promise resolving to formatted quantity string

        -
    getAggregatedTrades?: (
        symbol: string,
        from: Date,
        to: Date,
        backtest: boolean,
    ) => Promise<IAggregatedTradeData[]>

    Fetch aggregated trades for a trading pair. +

    getAggregatedTrades?: (
        symbol: string,
        from: Date,
        to: Date,
        backtest: boolean,
    ) => Promise<IAggregatedTradeData[]>

    Fetch aggregated trades for a trading pair. Optional. If not provided, throws an error when called.

    Type declaration

      • (
            symbol: string,
            from: Date,
            to: Date,
            backtest: boolean,
        ): Promise<IAggregatedTradeData[]>
      • Parameters

        • symbol: string

          Trading pair symbol (e.g., "BTCUSDT")

        • from: Date

          Start of time range (used in backtest for historical data, can be ignored in live)

          @@ -32,14 +32,14 @@ Optional. If not provided, throws an error when called.

    // Backtest implementation: returns historical aggregated trades for the time range
    const backtestAggregatedTrades = async (symbol: string, from: Date, to: Date, backtest: boolean) => {
    if (backtest) {
    return await database.getAggregatedTrades(symbol, from, to);
    }
    return await exchange.fetchAggregatedTrades(symbol);
    };

    // Live implementation: ignores from/to when not in backtest mode
    const liveAggregatedTrades = async (symbol: string, _from: Date, _to: Date, backtest: boolean) => {
    return await exchange.fetchAggregatedTrades(symbol);
    };
    -
    getCandles: (
        symbol: string,
        interval: CandleInterval,
        since: Date,
        limit: number,
        backtest: boolean,
    ) => Promise<IPublicCandleData[]>

    Fetch candles from data source (API or database).

    +
    getCandles: (
        symbol: string,
        interval: CandleInterval,
        since: Date,
        limit: number,
        backtest: boolean,
    ) => Promise<IPublicCandleData[]>

    Fetch candles from data source (API or database).

    Type declaration

      • (
            symbol: string,
            interval: CandleInterval,
            since: Date,
            limit: number,
            backtest: boolean,
        ): Promise<IPublicCandleData[]>
      • Parameters

        • symbol: string

          Trading pair symbol (e.g., "BTCUSDT")

        • interval: CandleInterval

          Candle time interval (e.g., "1m", "1h")

        • since: Date

          Start date for candle fetching

        • limit: number

          Maximum number of candles to fetch

        • backtest: boolean

          Whether running in backtest mode

        Returns Promise<IPublicCandleData[]>

        Promise resolving to array of OHLCV candle data

        -
    getOrderBook?: (
        symbol: string,
        depth: number,
        from: Date,
        to: Date,
        backtest: boolean,
    ) => Promise<IOrderBookData>

    Fetch order book for a trading pair.

    +
    getOrderBook?: (
        symbol: string,
        depth: number,
        from: Date,
        to: Date,
        backtest: boolean,
    ) => Promise<IOrderBookData>

    Fetch order book for a trading pair.

    Optional. If not provided, throws an error when called.

    Type declaration

      • (
            symbol: string,
            depth: number,
            from: Date,
            to: Date,
            backtest: boolean,
        ): Promise<IOrderBookData>
      • Parameters

        • symbol: string

          Trading pair symbol (e.g., "BTCUSDT")

        • depth: number

          Maximum depth levels for both bids and asks (default: CC_ORDER_BOOK_MAX_DEPTH_LEVELS)

          @@ -50,8 +50,8 @@ Optional. If not provided, throws an error when called.

    // Backtest implementation: returns historical order book for the time range
    const backtestOrderBook = async (symbol: string, depth: number, from: Date, to: Date, backtest: boolean) => {
    if (backtest) {
    return await database.getOrderBookSnapshot(symbol, depth, from, to);
    }
    return await exchange.fetchOrderBook(symbol, depth);
    };

    // Live implementation: ignores from/to when not in backtest mode
    const liveOrderBook = async (symbol: string, depth: number, _from: Date, _to: Date, backtest: boolean) => {
    return await exchange.fetchOrderBook(symbol, depth);
    };
    -
    note?: string

    Optional developer note for documentation

    -
    +
    note?: string

    Optional developer note for documentation

    +

    Interface IHeatmapRow

    Portfolio heatmap statistics for a single symbol. Aggregated metrics across all strategies for one trading pair.

    -
    interface IHeatmapRow {
        avgFallPnl: number;
        avgLoss: number;
        avgPeakPnl: number;
        avgPnl: number;
        avgWin: number;
        calmarRatio: number;
        expectancy: number;
        lossCount: number;
        maxDrawdown: number;
        maxLossStreak: number;
        maxWinStreak: number;
        profitFactor: number;
        recoveryFactor: number;
        sharpeRatio: number;
        sortinoRatio: number;
        stdDev: number;
        symbol: string;
        totalPnl: number;
        totalTrades: number;
        winCount: number;
        winRate: number;
    }

    Properties

    interface IHeatmapRow {
        avgFallPnl: number;
        avgLoss: number;
        avgPeakPnl: number;
        avgPnl: number;
        avgWin: number;
        calmarRatio: number;
        expectancy: number;
        lossCount: number;
        maxDrawdown: number;
        maxLossStreak: number;
        maxWinStreak: number;
        profitFactor: number;
        recoveryFactor: number;
        sharpeRatio: number;
        sortinoRatio: number;
        stdDev: number;
        symbol: string;
        totalPnl: number;
        totalTrades: number;
        winCount: number;
        winRate: number;
    }

    Properties

    avgFallPnl avgLoss avgPeakPnl avgPnl @@ -22,27 +22,27 @@ Aggregated metrics across all strategies for one trading pair.

    winCount winRate

    Properties

    avgFallPnl: number

    Average fall PNL percentage across all trades (_fall.pnlPercentage). Closer to 0 is better.

    -
    avgLoss: number

    Average loss percentage on losing trades

    -
    avgPeakPnl: number

    Average peak PNL percentage across all trades (_peak.pnlPercentage). Higher is better.

    -
    avgPnl: number

    Average PNL per trade

    -
    avgWin: number

    Average profit percentage on winning trades

    -
    calmarRatio: number

    Calmar Ratio (totalPnl / maxDrawdown). Higher is better.

    -
    expectancy: number

    Expectancy: (winRate * avgWin) - (lossRate * avgLoss)

    -
    lossCount: number

    Number of losing trades

    -
    maxDrawdown: number

    Maximum drawdown percentage (largest peak-to-trough decline)

    -
    maxLossStreak: number

    Maximum consecutive losing trades

    -
    maxWinStreak: number

    Maximum consecutive winning trades

    -
    profitFactor: number

    Profit factor: sum of wins / sum of losses

    -
    recoveryFactor: number

    Recovery Factor (totalPnl / maxDrawdown). Higher is better.

    -
    sharpeRatio: number

    Risk-adjusted return (Sharpe Ratio)

    -
    sortinoRatio: number

    Sortino Ratio (avgPnl / downside deviation — stdDev of losses only). Higher is better.

    -
    stdDev: number

    Standard deviation of PNL

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    totalPnl: number

    Total profit/loss percentage across all closed trades

    -
    totalTrades: number

    Total number of closed trades

    -
    winCount: number

    Number of winning trades

    -
    winRate: number

    Win rate percentage

    -
    +
    avgLoss: number

    Average loss percentage on losing trades

    +
    avgPeakPnl: number

    Average peak PNL percentage across all trades (_peak.pnlPercentage). Higher is better.

    +
    avgPnl: number

    Average PNL per trade

    +
    avgWin: number

    Average profit percentage on winning trades

    +
    calmarRatio: number

    Calmar Ratio (totalPnl / maxDrawdown). Higher is better.

    +
    expectancy: number

    Expectancy: (winRate * avgWin) - (lossRate * avgLoss)

    +
    lossCount: number

    Number of losing trades

    +
    maxDrawdown: number

    Maximum drawdown percentage (largest peak-to-trough decline)

    +
    maxLossStreak: number

    Maximum consecutive losing trades

    +
    maxWinStreak: number

    Maximum consecutive winning trades

    +
    profitFactor: number

    Profit factor: sum of wins / sum of losses

    +
    recoveryFactor: number

    Recovery Factor (totalPnl / maxDrawdown). Higher is better.

    +
    sharpeRatio: number

    Risk-adjusted return per trade (Sharpe Ratio = avgPnl / stdDev)

    +
    sortinoRatio: number

    Sortino Ratio (avgPnl / downside deviation — RMS of losing trades only). Higher is better.

    +
    stdDev: number

    Standard deviation of PNL

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    totalPnl: number

    Total profit/loss percentage across all closed trades

    +
    totalTrades: number

    Total number of closed trades

    +
    winCount: number

    Number of winning trades

    +
    winRate: number

    Win rate percentage

    +

    Interface ILog

    Extended logger interface with log history access.

    -
    interface ILog {
        debug(topic: string, ...args: any[]): void;
        getList(): Promise<ILogEntry[]>;
        info(topic: string, ...args: any[]): void;
        log(topic: string, ...args: any[]): void;
        warn(topic: string, ...args: any[]): void;
    }

    Hierarchy (View Summary)

    Methods

    interface ILog {
        debug(topic: string, ...args: any[]): void;
        getList(): Promise<ILogEntry[]>;
        info(topic: string, ...args: any[]): void;
        log(topic: string, ...args: any[]): void;
        warn(topic: string, ...args: any[]): void;
    }

    Hierarchy (View Summary)

    Methods

    • Logs a debug-level message. Employed for detailed diagnostic information, such as intermediate states during agent tool calls, swarm navigation changes, or embedding creation processes, typically enabled in development or troubleshooting scenarios.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs an info-level message. +

    • Logs an info-level message. Used to record informational updates, such as successful completions, policy validations, or history commits, providing a high-level overview of system activity without excessive detail.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a general-purpose message. +

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a general-purpose message. Used throughout the swarm system to record significant events or state changes, such as agent execution, session connections, or storage updates.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a warning-level message. +

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a warning-level message. Used to record potentially problematic situations that don't prevent execution but may require attention, such as missing data, unexpected conditions, or deprecated usage.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    +

    Parameters

    • topic: string
    • ...args: any[]

    Returns void

    Interface ILogEntry

    Single log entry stored in the log history.

    -
    interface ILogEntry {
        args: unknown[];
        createdAt: string;
        executionContext: IExecutionContext;
        id: string;
        methodContext: IMethodContext;
        priority: number;
        timestamp: number;
        topic: string;
        type: "log" | "debug" | "info" | "warn";
    }

    Properties

    interface ILogEntry {
        args: unknown[];
        createdAt: string;
        executionContext: IExecutionContext;
        id: string;
        methodContext: IMethodContext;
        priority: number;
        timestamp: number;
        topic: string;
        type: "log" | "debug" | "info" | "warn";
    }

    Properties

    Properties

    args: unknown[]

    Additional arguments passed to the log call

    -
    createdAt: string

    Date taken from backtest context to improve user experience

    -
    executionContext: IExecutionContext

    Optional execution context associated with the log entry, providing additional details about the execution environment or state when the log was recorded

    -
    id: string

    Unique entry identifier generated via randomString

    -
    methodContext: IMethodContext

    Optional method context associated with the log entry, providing additional details about the execution environment or state when the log was recorded

    -
    priority: number

    Current Unix timestamp in milliseconds for storage rotate

    -
    timestamp: number

    Unix timestamp in milliseconds taken from backtest context to improve user experience

    -
    topic: string

    Log topic / method name

    -
    type: "log" | "debug" | "info" | "warn"

    Log level

    -
    +
    createdAt: string

    Date taken from backtest context to improve user experience

    +
    executionContext: IExecutionContext

    Optional execution context associated with the log entry, providing additional details about the execution environment or state when the log was recorded

    +
    id: string

    Unique entry identifier generated via randomString

    +
    methodContext: IMethodContext

    Optional method context associated with the log entry, providing additional details about the execution environment or state when the log was recorded

    +
    priority: number

    Current Unix timestamp in milliseconds for storage rotate

    +
    timestamp: number

    Unix timestamp in milliseconds taken from backtest context to improve user experience

    +
    topic: string

    Log topic / method name

    +
    type: "log" | "debug" | "info" | "warn"

    Log level

    +

    Interface ILogger

    Interface representing a logging mechanism for the swarm system. Provides methods to record messages at different severity levels, used across components like agents, sessions, states, storage, swarms, history, embeddings, completions, and policies. Logs are utilized to track lifecycle events (e.g., initialization, disposal), operational details (e.g., tool calls, message emissions), validation outcomes (e.g., policy checks), and errors (e.g., persistence failures), aiding in debugging, monitoring, and auditing.

    -
    interface ILogger {
        debug(topic: string, ...args: any[]): void;
        info(topic: string, ...args: any[]): void;
        log(topic: string, ...args: any[]): void;
        warn(topic: string, ...args: any[]): void;
    }

    Hierarchy (View Summary)

    Methods

    interface ILogger {
        debug(topic: string, ...args: any[]): void;
        info(topic: string, ...args: any[]): void;
        log(topic: string, ...args: any[]): void;
        warn(topic: string, ...args: any[]): void;
    }

    Hierarchy (View Summary)

    Methods

    Methods

    • Logs a debug-level message. Employed for detailed diagnostic information, such as intermediate states during agent tool calls, swarm navigation changes, or embedding creation processes, typically enabled in development or troubleshooting scenarios.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs an info-level message. +

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs an info-level message. Used to record informational updates, such as successful completions, policy validations, or history commits, providing a high-level overview of system activity without excessive detail.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a general-purpose message. +

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a general-purpose message. Used throughout the swarm system to record significant events or state changes, such as agent execution, session connections, or storage updates.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a warning-level message. +

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    • Logs a warning-level message. Used to record potentially problematic situations that don't prevent execution but may require attention, such as missing data, unexpected conditions, or deprecated usage.

      -

      Parameters

      • topic: string
      • ...args: any[]

      Returns void

    +

    Parameters

    • topic: string
    • ...args: any[]

    Returns void

    Interface IMarkdownDumpOptions

    Options for markdown dump operations. Contains path information and metadata for filtering.

    -
    interface IMarkdownDumpOptions {
        exchangeName: string;
        file: string;
        frameName: string;
        path: string;
        signalId: string;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IMarkdownDumpOptions {
        exchangeName: string;
        file: string;
        frameName: string;
        path: string;
        signalId: string;
        strategyName: string;
        symbol: string;
    }

    Properties

    exchangeName file frameName path @@ -8,13 +8,13 @@ Contains path information and metadata for filtering.

    strategyName symbol

    Properties

    exchangeName: string

    Exchange name

    -
    file: string

    File name including extension

    -
    frameName: string

    Frame name (timeframe identifier)

    -
    path: string

    Directory path relative to process.cwd()

    -
    signalId: string

    Signal unique identifier

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    file: string

    File name including extension

    +
    frameName: string

    Frame name (timeframe identifier)

    +
    path: string

    Directory path relative to process.cwd()

    +
    signalId: string

    Signal unique identifier

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IMemoryInstance

    Interface for memory instance implementations. Defines the contract for local, persist, and dummy backends.

    -
    interface IMemoryInstance {
        dispose(): void;
        listMemory<T extends object = object>(
            when: Date,
        ): Promise<{ content: T; memoryId: string }[]>;
        readMemory<T extends object = object>(
            memoryId: string,
            when: Date,
        ): Promise<T>;
        removeMemory(memoryId: string, when: Date): Promise<void>;
        searchMemory<T extends object = object>(
            query: string,
            when: Date,
            settings?: SearchSettings,
        ): Promise<{ content: T; memoryId: string; score: number }[]>;
        waitForInit(initial: boolean): Promise<void>;
        writeMemory<T extends object = object>(
            memoryId: string,
            value: T,
            description: string,
            when: Date,
        ): Promise<void>;
    }

    Methods

    interface IMemoryInstance {
        dispose(): void;
        listMemory<T extends object = object>(
            when: Date,
        ): Promise<{ content: T; memoryId: string }[]>;
        readMemory<T extends object = object>(
            memoryId: string,
            when: Date,
        ): Promise<T>;
        removeMemory(memoryId: string, when: Date): Promise<void>;
        searchMemory<T extends object = object>(
            query: string,
            when: Date,
            settings?: SearchSettings,
        ): Promise<{ content: T; memoryId: string; score: number }[]>;
        waitForInit(initial: boolean): Promise<void>;
        writeMemory<T extends object = object>(
            memoryId: string,
            value: T,
            description: string,
            when: Date,
        ): Promise<void>;
    }

    Methods

    dispose listMemory readMemory removeMemory @@ -8,32 +8,32 @@ Defines the contract for local, persist, and dummy backends.

    waitForInit writeMemory

    Methods

    • Releases any resources held by this instance.

      -

      Returns void

    • List all entries in memory. +

      Returns void

    • List all entries in memory. Filters out entries whose when is greater than the requested when.

      Type Parameters

      • T extends object = object

      Parameters

      • when: Date

        Logical timestamp at which the read is happening (look-ahead guard)

      Returns Promise<{ content: T; memoryId: string }[]>

      Array of all stored entries

      -
    • Read a single entry from memory. +

    • Read a single entry from memory. Behaves as not-found if the stored when is greater than the requested when.

      Type Parameters

      • T extends object = object

      Parameters

      • memoryId: string

        Unique entry identifier

      • when: Date

        Logical timestamp at which the read is happening (look-ahead guard)

      Returns Promise<T>

      Entry value

      Error if entry not found (or shadowed by look-ahead)

      -
    • Remove an entry from memory.

      +
    • Remove an entry from memory.

      Parameters

      • memoryId: string

        Unique entry identifier

      • when: Date

        Logical timestamp (kept for API consistency; removal is by UUID)

        -

      Returns Promise<void>

    • Search memory using BM25 full-text scoring. +

    Returns Promise<void>

    • Search memory using BM25 full-text scoring. Filters out entries whose when is greater than the requested when.

      Type Parameters

      • T extends object = object

      Parameters

      • query: string

        Search query string

      • when: Date

        Logical timestamp at which the read is happening (look-ahead guard)

      • Optionalsettings: SearchSettings

      Returns Promise<{ content: T; memoryId: string; score: number }[]>

      Array of matching entries with scores

      -
    • Initialize the memory instance.

      +
    • Initialize the memory instance.

      Parameters

      • initial: boolean

        Whether this is the first initialization

        -

      Returns Promise<void>

    • Write a value to memory.

      +

    Returns Promise<void>

    • Write a value to memory.

      Type Parameters

      • T extends object = object

      Parameters

      • memoryId: string

        Unique entry identifier

      • value: T

        Value to store

      • description: string

        Optional BM25 index string; defaults to JSON.stringify(value)

      • when: Date

        Logical timestamp this entry belongs to (look-ahead guard)

        -

      Returns Promise<void>

    +

    Returns Promise<void>

    Interface INotificationUtils

    Base interface for notification adapters. All notification adapters must implement this interface.

    -
    interface INotificationUtils {
        dispose(): Promise<void>;
        getData(): Promise<NotificationModel[]>;
        handleBreakeven(data: BreakevenContract): Promise<void>;
        handleCriticalError(error: Error): Promise<void>;
        handleError(error: Error): Promise<void>;
        handlePartialLoss(data: PartialLossContract): Promise<void>;
        handlePartialProfit(data: PartialProfitContract): Promise<void>;
        handleRisk(data: RiskContract): Promise<void>;
        handleSignal(data: IStrategyTickResult): Promise<void>;
        handleSignalNotify(data: SignalInfoContract): Promise<void>;
        handleStrategyCommit(data: StrategyCommitContract): Promise<void>;
        handleSync(data: SignalSyncContract): Promise<void>;
        handleValidationError(error: Error): Promise<void>;
    }

    Methods

    interface INotificationUtils {
        dispose(): Promise<void>;
        getData(): Promise<NotificationModel[]>;
        handleBreakeven(data: BreakevenContract): Promise<void>;
        handleCriticalError(error: Error): Promise<void>;
        handleError(error: Error): Promise<void>;
        handlePartialLoss(data: PartialLossContract): Promise<void>;
        handlePartialProfit(data: PartialProfitContract): Promise<void>;
        handleRisk(data: RiskContract): Promise<void>;
        handleSignal(data: IStrategyTickResult): Promise<void>;
        handleSignalNotify(data: SignalInfoContract): Promise<void>;
        handleStrategyCommit(data: StrategyCommitContract): Promise<void>;
        handleSync(data: SignalSyncContract): Promise<void>;
        handleValidationError(error: Error): Promise<void>;
    }

    Methods

    dispose getData handleBreakeven handleCriticalError @@ -14,29 +14,29 @@ All notification adapters must implement this interface.

    handleSync handleValidationError

    Methods

    • Clears all stored notifications.

      -

      Returns Promise<void>

    • Handles critical error event.

      +

    Returns Promise<void>

    • Handles critical error event.

      Parameters

      • error: Error

        The error object

        -

      Returns Promise<void>

    • Handles error event.

      +

    Returns Promise<void>

    • Handles error event.

      Parameters

      • error: Error

        The error object

        -

      Returns Promise<void>

    • Handles partial loss availability event.

      +

    Returns Promise<void>

    • Handles partial profit availability event.

      +

    Returns Promise<void>

    • Handles risk rejection event.

      +

    Returns Promise<void>

    • Handles signal events (opened, closed, scheduled, cancelled).

      +

    Returns Promise<void>

    • Handles strategy commit events (partial-profit, breakeven, trailing, etc.).

      +

    Returns Promise<void>

    • Handles signal sync event (signal-open, signal-close).

      +

    Returns Promise<void>

    • Handles validation error event.

      +

    Returns Promise<void>

    • Handles validation error event.

      Parameters

      • error: Error

        The error object

        -

      Returns Promise<void>

    +

    Returns Promise<void>

    Interface IOrderBookData

    Order book data containing bids and asks.

    -
    interface IOrderBookData {
        asks: IBidData[];
        bids: IBidData[];
        symbol: string;
    }

    Properties

    interface IOrderBookData {
        asks: IBidData[];
        bids: IBidData[];
        symbol: string;
    }

    Properties

    Properties

    asks: IBidData[]

    Array of ask orders (sell orders)

    -
    bids: IBidData[]

    Array of bid orders (buy orders)

    -
    symbol: string

    Trading pair symbol

    -
    +
    bids: IBidData[]

    Array of bid orders (buy orders)

    +
    symbol: string

    Trading pair symbol

    +

    Interface IPartialLossCommitRow

    Queued partial loss commit.

    -
    interface IPartialLossCommitRow {
        action: "partial-loss";
        backtest: boolean;
        currentPrice: number;
        percentToClose: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IPartialLossCommitRow

    Properties

    interface IPartialLossCommitRow {
        action: "partial-loss";
        backtest: boolean;
        currentPrice: number;
        percentToClose: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IPartialLossCommitRow

    Properties

    action: "partial-loss"

    Discriminator

    -
    backtest: boolean

    Whether running in backtest mode

    -
    currentPrice: number

    Price at which partial was executed

    -
    percentToClose: number

    Percentage of position closed

    -
    symbol: string

    Trading pair symbol

    -
    +
    backtest: boolean

    Whether running in backtest mode

    +
    currentPrice: number

    Price at which partial was executed

    +
    percentToClose: number

    Percentage of position closed

    +
    symbol: string

    Trading pair symbol

    +

    Interface IPartialProfitCommitRow

    Queued partial profit commit.

    -
    interface IPartialProfitCommitRow {
        action: "partial-profit";
        backtest: boolean;
        currentPrice: number;
        percentToClose: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IPartialProfitCommitRow

    Properties

    interface IPartialProfitCommitRow {
        action: "partial-profit";
        backtest: boolean;
        currentPrice: number;
        percentToClose: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • IPartialProfitCommitRow

    Properties

    action: "partial-profit"

    Discriminator

    -
    backtest: boolean

    Whether running in backtest mode

    -
    currentPrice: number

    Price at which partial was executed

    -
    percentToClose: number

    Percentage of position closed

    -
    symbol: string

    Trading pair symbol

    -
    +
    backtest: boolean

    Whether running in backtest mode

    +
    currentPrice: number

    Price at which partial was executed

    +
    percentToClose: number

    Percentage of position closed

    +
    symbol: string

    Trading pair symbol

    +

    Interface IPositionSizeATRParams

    Public API parameters for ATR-based sizing (without method field).

    -
    interface IPositionSizeATRParams {
        accountBalance: number;
        atr: number;
        priceOpen: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • IPositionSizeATRParams

    Properties

    interface IPositionSizeATRParams {
        accountBalance: number;
        atr: number;
        priceOpen: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • IPositionSizeATRParams

    Properties

    accountBalance: number

    Current account balance

    -
    atr: number

    Current ATR value

    -
    priceOpen: number

    Planned entry price

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    atr: number

    Current ATR value

    +
    priceOpen: number

    Planned entry price

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IPositionSizeFixedPercentageParams

    Public API parameters for fixed percentage sizing (without method field).

    -
    interface IPositionSizeFixedPercentageParams {
        accountBalance: number;
        priceOpen: number;
        priceStopLoss: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • IPositionSizeFixedPercentageParams

    Properties

    interface IPositionSizeFixedPercentageParams {
        accountBalance: number;
        priceOpen: number;
        priceStopLoss: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • IPositionSizeFixedPercentageParams

    Properties

    accountBalance: number

    Current account balance

    -
    priceOpen: number

    Planned entry price

    -
    priceStopLoss: number

    Stop-loss price

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    priceOpen: number

    Planned entry price

    +
    priceStopLoss: number

    Stop-loss price

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IPositionSizeKellyParams

    Public API parameters for Kelly Criterion sizing (without method field).

    -
    interface IPositionSizeKellyParams {
        accountBalance: number;
        priceOpen: number;
        symbol: string;
        winLossRatio: number;
        winRate: number;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • IPositionSizeKellyParams

    Properties

    interface IPositionSizeKellyParams {
        accountBalance: number;
        priceOpen: number;
        symbol: string;
        winLossRatio: number;
        winRate: number;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • IPositionSizeKellyParams

    Properties

    accountBalance: number

    Current account balance

    -
    priceOpen: number

    Planned entry price

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    winLossRatio: number

    Average win/loss ratio

    -
    winRate: number

    Win rate (0-1)

    -
    +
    priceOpen: number

    Planned entry price

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    winLossRatio: number

    Average win/loss ratio

    +
    winRate: number

    Win rate (0-1)

    +

    Interface IPublicCandleData

    interface IPublicCandleData {
        close: number;
        high: number;
        low: number;
        open: number;
        timestamp: number;
        volume: number;
    }

    Properties

    close +IPublicCandleData | backtest-kit

    Interface IPublicCandleData

    interface IPublicCandleData {
        close: number;
        high: number;
        low: number;
        open: number;
        timestamp: number;
        volume: number;
    }

    Properties

    close: number

    Closing price at candle end

    -
    high: number

    Highest price during candle period

    -
    low: number

    Lowest price during candle period

    -
    open: number

    Opening price at candle start

    -
    timestamp: number

    Unix timestamp in milliseconds when candle opened

    -
    volume: number

    Trading volume during candle period

    -
    +
    high: number

    Highest price during candle period

    +
    low: number

    Lowest price during candle period

    +
    open: number

    Opening price at candle start

    +
    timestamp: number

    Unix timestamp in milliseconds when candle opened

    +
    volume: number

    Trading volume during candle period

    +

    Interface IRecentUtils

    Base interface for recent signal storage adapters.

    -
    interface IRecentUtils {
        getLatestSignal(
            symbol: string,
            strategyName: string,
            exchangeName: string,
            frameName: string,
            backtest: boolean,
            when: Date,
        ): Promise<IPublicSignalRow>;
        getMinutesSinceLatestSignalCreated(
            timestamp: number,
            symbol: string,
            strategyName: string,
            exchangeName: string,
            frameName: string,
            backtest: boolean,
        ): Promise<number>;
        handleActivePing(event: ActivePingContract): Promise<void>;
    }

    Methods

    interface IRecentUtils {
        getLatestSignal(
            symbol: string,
            strategyName: string,
            exchangeName: string,
            frameName: string,
            backtest: boolean,
            when: Date,
        ): Promise<IPublicSignalRow>;
        getMinutesSinceLatestSignalCreated(
            timestamp: number,
            symbol: string,
            strategyName: string,
            exchangeName: string,
            frameName: string,
            backtest: boolean,
        ): Promise<number>;
        handleActivePing(event: ActivePingContract): Promise<void>;
    }

    Methods

    • Retrieves the latest active signal for the given context. @@ -12,7 +12,7 @@ Returns null if the stored signal's timestamp is greater than the r

    • backtest: boolean

      Flag indicating if the context is backtest or live

    • when: Date

      Logical timestamp at which the read is happening (look-ahead guard)

    Returns Promise<IPublicSignalRow>

    The latest signal or null if not found / shadowed by look-ahead

    -
    • Returns the number of minutes elapsed since the latest signal's timestamp. +

    • Returns the number of minutes elapsed since the latest signal's timestamp. timestamp doubles as the look-ahead cutoff — a signal whose timestamp exceeds the requested one is treated as not yet visible.

      Parameters

      • timestamp: number

        Current timestamp in milliseconds (also serves as look-ahead cutoff)

        @@ -22,9 +22,9 @@ exceeds the requested one is treated as not yet visible.

      • frameName: string

        Frame identifier

      • backtest: boolean

        Flag indicating if the context is backtest or live

      Returns Promise<number>

      Minutes since the latest signal, or null if no signal found / shadowed by look-ahead

      -
    +

    Returns Promise<void>

    Interface IReportDumpOptions

    Options for report data writes. Contains metadata for event filtering and search.

    -
    interface IReportDumpOptions {
        exchangeName: string;
        frameName: string;
        signalId: string;
        strategyName: string;
        symbol: string;
        walkerName: string;
    }

    Properties

    interface IReportDumpOptions {
        exchangeName: string;
        frameName: string;
        signalId: string;
        strategyName: string;
        symbol: string;
        walkerName: string;
    }

    Properties

    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name (timeframe identifier)

    -
    signalId: string

    Signal unique identifier

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    walkerName: string

    Walker optimization name

    -
    +
    frameName: string

    Frame name (timeframe identifier)

    +
    signalId: string

    Signal unique identifier

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    walkerName: string

    Walker optimization name

    +

    Interface IRiskActivePosition

    Active position tracked by ClientRisk for cross-strategy analysis.

    -
    interface IRiskActivePosition {
        exchangeName: string;
        frameName: string;
        minuteEstimatedTime: number;
        openTimestamp: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IRiskActivePosition {
        exchangeName: string;
        frameName: string;
        minuteEstimatedTime: number;
        openTimestamp: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        strategyName: string;
        symbol: string;
    }

    Properties

    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name

    -
    minuteEstimatedTime: number

    Estimated time in minutes

    -
    openTimestamp: number

    Timestamp when the position was opened

    -
    position: "long" | "short"

    Position direction ("long" or "short")

    -
    priceOpen: number

    Entry price

    -
    priceStopLoss: number

    Stop loss price

    -
    priceTakeProfit: number

    Take profit price

    -
    strategyName: string

    Strategy name owning the position

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    frameName: string

    Frame name

    +
    minuteEstimatedTime: number

    Estimated time in minutes

    +
    openTimestamp: number

    Timestamp when the position was opened

    +
    position: "long" | "short"

    Position direction ("long" or "short")

    +
    priceOpen: number

    Entry price

    +
    priceStopLoss: number

    Stop loss price

    +
    priceTakeProfit: number

    Take profit price

    +
    strategyName: string

    Strategy name owning the position

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IRiskCheckArgs

    Risk check arguments for evaluating whether to allow opening a new position. Called BEFORE signal creation to validate if conditions allow new signals. Contains only passthrough arguments from ClientStrategy context.

    -
    interface IRiskCheckArgs {
        currentPrice: number;
        currentSignal: IPublicSignalRow;
        exchangeName: string;
        frameName: string;
        riskName: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    interface IRiskCheckArgs {
        currentPrice: number;
        currentSignal: IPublicSignalRow;
        exchangeName: string;
        frameName: string;
        riskName: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    currentPrice currentSignal exchangeName frameName @@ -10,14 +10,14 @@ Contains only passthrough arguments from ClientStrategy context.

    symbol timestamp

    Properties

    currentPrice: number

    Current VWAP price

    -
    currentSignal: IPublicSignalRow

    Pending signal to apply

    -
    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name

    -
    riskName: string

    Risk name

    -
    strategyName: string

    Strategy name requesting to open a position

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Current timestamp

    -
    +
    currentSignal: IPublicSignalRow

    Pending signal to apply

    +
    exchangeName: string

    Exchange name

    +
    frameName: string

    Frame name

    +
    riskName: string

    Risk name

    +
    strategyName: string

    Strategy name requesting to open a position

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Current timestamp

    +

    Interface IRiskSchema

    Risk schema registered via addRisk(). Defines portfolio-level risk controls via custom validations.

    -
    interface IRiskSchema {
        callbacks?: Partial<IRiskCallbacks>;
        note?: string;
        riskName: string;
        validations: (IRiskValidationFn | IRiskValidation)[];
    }

    Properties

    interface IRiskSchema {
        callbacks?: Partial<IRiskCallbacks>;
        note?: string;
        riskName: string;
        validations: (IRiskValidationFn | IRiskValidation)[];
    }

    Properties

    callbacks?: Partial<IRiskCallbacks>

    Optional lifecycle event callbacks (onRejected, onAllowed)

    -
    note?: string

    Optional developer note for documentation

    -
    riskName: string

    Unique risk profile identifier

    -

    Custom validations array for risk logic

    -
    +
    note?: string

    Optional developer note for documentation

    +
    riskName: string

    Unique risk profile identifier

    +

    Custom validations array for risk logic

    +

    Interface IRiskSignalRow

    Risk signal row for internal risk management. Extends ISignalDto to include priceOpen, originalPriceStopLoss and originalPriceTakeProfit. Used in risk validation to access entry price and original SL/TP.

    -
    interface IRiskSignalRow {
        _entry?: { cost: number; price: number; timestamp: number }[];
        _fall: { price: number; timestamp: number } & IStrategyPnL;
        _isScheduled: boolean;
        _partial?: {
            costBasisAtClose: number;
            currentPrice: number;
            entryCountAtClose: number;
            percent: number;
            timestamp: number;
            type: "profit" | "loss";
        }[];
        _peak: { price: number; timestamp: number } & IStrategyPnL;
        _trailingPriceStopLoss?: number;
        _trailingPriceTakeProfit?: number;
        cost: number;
        exchangeName: string;
        frameName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        minuteEstimatedTime: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        partialExecuted: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy (View Summary)

    Properties

    interface IRiskSignalRow {
        _entry?: { cost: number; price: number; timestamp: number }[];
        _fall: { price: number; timestamp: number } & IStrategyPnL;
        _isScheduled: boolean;
        _partial?: {
            costBasisAtClose: number;
            currentPrice: number;
            entryCountAtClose: number;
            percent: number;
            timestamp: number;
            type: "profit" | "loss";
        }[];
        _peak: { price: number; timestamp: number } & IStrategyPnL;
        _trailingPriceStopLoss?: number;
        _trailingPriceTakeProfit?: number;
        cost: number;
        exchangeName: string;
        frameName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        minuteEstimatedTime: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        partialExecuted: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy (View Summary)

    Properties

    _entry? _fall _isScheduled _partial? @@ -40,15 +40,15 @@ Original priceOpen is preserved unchanged for identity/audit purposes.

    Type declaration

    • cost: number

      Cost of this entry in USD (e.g. 100 for $100 position)

    • price: number

      Price at which this entry was executed

    • timestamp: number

      Unix timestamp in milliseconds when this entry was executed

      -
    _fall: { price: number; timestamp: number } & IStrategyPnL

    Worst price seen in loss direction during the life of this position. +

    _fall: { price: number; timestamp: number } & IStrategyPnL

    Worst price seen in loss direction during the life of this position. Initialized at position open with priceOpen/pendingAt (pnl = 0). Updated on every tick/candle when price moves toward SL (currentDistance < 0).

    • For LONG: minimum VWAP price seen below effective entry
    • For SHORT: maximum VWAP price seen above effective entry
    -
    _isScheduled: boolean

    Internal runtime marker for scheduled signals

    -
    _partial?: {
        costBasisAtClose: number;
        currentPrice: number;
        entryCountAtClose: number;
        percent: number;
        timestamp: number;
        type: "profit" | "loss";
    }[]

    History of partial closes for PNL calculation. +

    _isScheduled: boolean

    Internal runtime marker for scheduled signals

    +
    _partial?: {
        costBasisAtClose: number;
        currentPrice: number;
        entryCountAtClose: number;
        percent: number;
        timestamp: number;
        type: "profit" | "loss";
    }[]

    History of partial closes for PNL calculation. Each entry contains type (profit/loss), percent closed, and price. Used to calculate weighted PNL: Σ(percent_i × pnl_i) for each partial + (remaining% × final_pnl)

    Computed values (derived from this array):

    @@ -67,14 +67,14 @@ Used to slice _entry to only entries that existed at this partial.

  • percent: number

    Percentage of position closed (0-100)

  • timestamp: number

    Unix timestamp in milliseconds when this partial close was executed

  • type: "profit" | "loss"

    Type of partial close: profit (moving toward TP) or loss (moving toward SL)

    -
  • _peak: { price: number; timestamp: number } & IStrategyPnL

    Best price seen in profit direction during the life of this position. +

    _peak: { price: number; timestamp: number } & IStrategyPnL

    Best price seen in profit direction during the life of this position. Initialized at position open with priceOpen/pendingAt. Updated on every tick/candle when price moves toward TP (currentDistance > 0).

    • For LONG: maximum VWAP price seen above effective entry
    • For SHORT: minimum VWAP price seen below effective entry
    -
    _trailingPriceStopLoss?: number

    Trailing stop-loss price that overrides priceStopLoss when set. +

    _trailingPriceStopLoss?: number

    Trailing stop-loss price that overrides priceStopLoss when set. Updated by trailing() method based on position type and percentage distance.

    • For LONG: moves upward as price moves toward TP (never moves down)
    • @@ -82,7 +82,7 @@ Updated by trailing() method based on position type and percentage distance.

      When _trailingPriceStopLoss is set, it replaces priceStopLoss for TP/SL checks. Original priceStopLoss is preserved in persistence but ignored during execution.
    -
    _trailingPriceTakeProfit?: number

    Trailing take-profit price that overrides priceTakeProfit when set. +

    _trailingPriceTakeProfit?: number

    Trailing take-profit price that overrides priceTakeProfit when set. Created and managed by trailingTake() method for dynamic TP adjustment. Allows moving TP further from or closer to current price based on strategy. Updated by trailingTake() method based on position type and percentage distance.

    @@ -92,41 +92,41 @@ Updated by trailingTake() method based on position type and percentage distance. When _trailingPriceTakeProfit is set, it replaces priceTakeProfit for TP/SL checks. Original priceTakeProfit is preserved in persistence but ignored during execution. -
    cost: number

    Cost of the initial position entry in USD (first entry, not DCA). +

    cost: number

    Cost of the initial position entry in USD (first entry, not DCA). Inherited from ISignalRow. Explicitly surfaced here for consumer visibility.

    -
    exchangeName: string

    Unique exchange identifier for execution

    -
    frameName: string

    Unique frame identifier for execution (empty string for live mode)

    -
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created. +

    exchangeName: string

    Unique exchange identifier for execution

    +
    frameName: string

    Unique frame identifier for execution (empty string for live mode)

    +
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created. Calculated using the worst unfavorable price reached (for long: min price below entry, for short: max price above entry) and the original entry price.

    -
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired (required in row, defaults applied in ClientStrategy)

    -
    note?: string

    Human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price set at signal creation (unchanged by averaging). +

    minuteEstimatedTime: number

    Expected duration in minutes before time_expired (required in row, defaults applied in ClientStrategy)

    +
    note?: string

    Human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price set at signal creation (unchanged by averaging). Mirrors signal.priceOpen which is preserved for identity/audit purposes.

    -
    originalPriceStopLoss: number

    Original stop-loss price set at signal creation.

    -
    originalPriceTakeProfit: number

    Original take-profit price set at signal creation.

    -
    partialExecuted: number

    Total executed percentage from partial closes. +

    originalPriceStopLoss: number

    Original stop-loss price set at signal creation.

    +
    originalPriceTakeProfit: number

    Original take-profit price set at signal creation.

    +
    partialExecuted: number

    Total executed percentage from partial closes. Sum of all percent values from _partial array (both profit and loss types). Represents the total portion of the position that has been closed through partial executions. Range: 0-100. Value of 0 means no partial closes, 100 means position fully closed through partials.

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created. +

    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created. Calculated using the highest favorable price reached (for long: max price above entry, for short: min price below entry) and the original entry price.

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Unrealized PNL at the time this public signal was created. +

    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Unrealized PNL at the time this public signal was created. Calculated using toProfitLossDto with the currentPrice at the moment of emission.

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position.

    -
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    -
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    strategyName: string

    Unique strategy identifier for execution

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when this signal was created/scheduled in backtest context or when getSignal was called in live context (before validation)

    -
    totalEntries: number

    Total number of entries in the DCA _entry history (_entry.length). +

    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position.

    +
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    +
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    strategyName: string

    Unique strategy identifier for execution

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when this signal was created/scheduled in backtest context or when getSignal was called in live context (before validation)

    +
    totalEntries: number

    Total number of entries in the DCA _entry history (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). +

    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface IRiskValidation

    Risk validation configuration. Defines validation logic with optional documentation.

    -
    interface IRiskValidation {
        note?: string;
        validate: IRiskValidationFn;
    }

    Properties

    interface IRiskValidation {
        note?: string;
        validate: IRiskValidationFn;
    }

    Properties

    Properties

    note?: string

    Optional description for documentation purposes. Aids in understanding the purpose or behavior of the validation.

    -

    The validation function to apply to the risk check parameters.

    -
    +

    The validation function to apply to the risk check parameters.

    +

    Interface IRiskValidationFn

    Risk validation function type. Returns null/void if validation passes, IRiskRejectionResult if validation fails. Can also throw error which will be caught and converted to IRiskRejectionResult.

    -
    +

    Interface IRiskValidationPayload

    Payload passed to risk validation functions. Extends IRiskCheckArgs with portfolio state data.

    -
    interface IRiskValidationPayload {
        activePositionCount: number;
        activePositions: IRiskActivePosition[];
        currentPrice: number;
        currentSignal: IRiskSignalRow;
        exchangeName: string;
        frameName: string;
        riskName: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    interface IRiskValidationPayload {
        activePositionCount: number;
        activePositions: IRiskActivePosition[];
        currentPrice: number;
        currentSignal: IRiskSignalRow;
        exchangeName: string;
        frameName: string;
        riskName: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    activePositionCount activePositions currentPrice currentSignal @@ -11,16 +11,16 @@ Extends IRiskCheckArgs with portfolio state data.

    symbol timestamp

    Properties

    activePositionCount: number

    Number of currently active positions across all strategies

    -
    activePositions: IRiskActivePosition[]

    List of currently active positions across all strategies

    -
    currentPrice: number

    Current VWAP price

    -
    currentSignal: IRiskSignalRow

    Current signal being validated (IRiskSignalRow is calculated internally so priceOpen always exist)

    -
    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name

    -
    riskName: string

    Risk name

    -
    strategyName: string

    Strategy name requesting to open a position

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Current timestamp

    -
    +
    activePositions: IRiskActivePosition[]

    List of currently active positions across all strategies

    +
    currentPrice: number

    Current VWAP price

    +
    currentSignal: IRiskSignalRow

    Current signal being validated (IRiskSignalRow is calculated internally so priceOpen always exist)

    +
    exchangeName: string

    Exchange name

    +
    frameName: string

    Frame name

    +
    riskName: string

    Risk name

    +
    strategyName: string

    Strategy name requesting to open a position

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Current timestamp

    +

    Interface IScheduledSignalCancelRow

    Scheduled signal row with cancellation ID. Extends IScheduledSignalRow to include optional cancelId for user-initiated cancellations.

    -
    interface IScheduledSignalCancelRow {
        _entry?: { cost: number; price: number; timestamp: number }[];
        _fall: { price: number; timestamp: number } & IStrategyPnL;
        _isScheduled: boolean;
        _partial?: {
            costBasisAtClose: number;
            currentPrice: number;
            entryCountAtClose: number;
            percent: number;
            timestamp: number;
            type: "profit" | "loss";
        }[];
        _peak: { price: number; timestamp: number } & IStrategyPnL;
        _trailingPriceStopLoss?: number;
        _trailingPriceTakeProfit?: number;
        cancelId?: string;
        cancelNote?: string;
        cost: number;
        exchangeName: string;
        frameName: string;
        id: string;
        minuteEstimatedTime: number;
        note?: string;
        pendingAt: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    interface IScheduledSignalCancelRow {
        _entry?: { cost: number; price: number; timestamp: number }[];
        _fall: { price: number; timestamp: number } & IStrategyPnL;
        _isScheduled: boolean;
        _partial?: {
            costBasisAtClose: number;
            currentPrice: number;
            entryCountAtClose: number;
            percent: number;
            timestamp: number;
            type: "profit" | "loss";
        }[];
        _peak: { price: number; timestamp: number } & IStrategyPnL;
        _trailingPriceStopLoss?: number;
        _trailingPriceTakeProfit?: number;
        cancelId?: string;
        cancelNote?: string;
        cost: number;
        exchangeName: string;
        frameName: string;
        id: string;
        minuteEstimatedTime: number;
        note?: string;
        pendingAt: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    _entry? _fall _isScheduled _partial? @@ -32,15 +32,15 @@ Original priceOpen is preserved unchanged for identity/audit purposes.

    Type declaration

    • cost: number

      Cost of this entry in USD (e.g. 100 for $100 position)

    • price: number

      Price at which this entry was executed

    • timestamp: number

      Unix timestamp in milliseconds when this entry was executed

      -
    _fall: { price: number; timestamp: number } & IStrategyPnL

    Worst price seen in loss direction during the life of this position. +

    _fall: { price: number; timestamp: number } & IStrategyPnL

    Worst price seen in loss direction during the life of this position. Initialized at position open with priceOpen/pendingAt (pnl = 0). Updated on every tick/candle when price moves toward SL (currentDistance < 0).

    • For LONG: minimum VWAP price seen below effective entry
    • For SHORT: maximum VWAP price seen above effective entry
    -
    _isScheduled: boolean

    Internal runtime marker for scheduled signals

    -
    _partial?: {
        costBasisAtClose: number;
        currentPrice: number;
        entryCountAtClose: number;
        percent: number;
        timestamp: number;
        type: "profit" | "loss";
    }[]

    History of partial closes for PNL calculation. +

    _isScheduled: boolean

    Internal runtime marker for scheduled signals

    +
    _partial?: {
        costBasisAtClose: number;
        currentPrice: number;
        entryCountAtClose: number;
        percent: number;
        timestamp: number;
        type: "profit" | "loss";
    }[]

    History of partial closes for PNL calculation. Each entry contains type (profit/loss), percent closed, and price. Used to calculate weighted PNL: Σ(percent_i × pnl_i) for each partial + (remaining% × final_pnl)

    Computed values (derived from this array):

    @@ -59,14 +59,14 @@ Used to slice _entry to only entries that existed at this partial.

  • percent: number

    Percentage of position closed (0-100)

  • timestamp: number

    Unix timestamp in milliseconds when this partial close was executed

  • type: "profit" | "loss"

    Type of partial close: profit (moving toward TP) or loss (moving toward SL)

    -
  • _peak: { price: number; timestamp: number } & IStrategyPnL

    Best price seen in profit direction during the life of this position. +

    _peak: { price: number; timestamp: number } & IStrategyPnL

    Best price seen in profit direction during the life of this position. Initialized at position open with priceOpen/pendingAt. Updated on every tick/candle when price moves toward TP (currentDistance > 0).

    • For LONG: maximum VWAP price seen above effective entry
    • For SHORT: minimum VWAP price seen below effective entry
    -
    _trailingPriceStopLoss?: number

    Trailing stop-loss price that overrides priceStopLoss when set. +

    _trailingPriceStopLoss?: number

    Trailing stop-loss price that overrides priceStopLoss when set. Updated by trailing() method based on position type and percentage distance.

    • For LONG: moves upward as price moves toward TP (never moves down)
    • @@ -74,7 +74,7 @@ Updated by trailing() method based on position type and percentage distance.

      When _trailingPriceStopLoss is set, it replaces priceStopLoss for TP/SL checks. Original priceStopLoss is preserved in persistence but ignored during execution.
    -
    _trailingPriceTakeProfit?: number

    Trailing take-profit price that overrides priceTakeProfit when set. +

    _trailingPriceTakeProfit?: number

    Trailing take-profit price that overrides priceTakeProfit when set. Created and managed by trailingTake() method for dynamic TP adjustment. Allows moving TP further from or closer to current price based on strategy. Updated by trailingTake() method based on position type and percentage distance.

    @@ -84,24 +84,24 @@ Updated by trailingTake() method based on position type and percentage distance. When _trailingPriceTakeProfit is set, it replaces priceTakeProfit for TP/SL checks. Original priceTakeProfit is preserved in persistence but ignored during execution. -
    cancelId?: string

    Cancellation ID (only for user-initiated cancellations)

    -
    cancelNote?: string

    Note from user payload (only for user-initiated cancellations)

    -
    cost: number

    Cost of this entry in USD (e.g. 100 for $100 position)

    -
    exchangeName: string

    Unique exchange identifier for execution

    -
    frameName: string

    Unique frame identifier for execution (empty string for live mode)

    -
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    -
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired (required in row, defaults applied in ClientStrategy)

    -
    note?: string

    Human-readable description of signal reason

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    -
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    strategyName: string

    Unique strategy identifier for execution

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when this signal was created/scheduled in backtest context or when getSignal was called in live context (before validation)

    -
    +
    cancelId?: string

    Cancellation ID (only for user-initiated cancellations)

    +
    cancelNote?: string

    Note from user payload (only for user-initiated cancellations)

    +
    cost: number

    Cost of this entry in USD (e.g. 100 for $100 position)

    +
    exchangeName: string

    Unique exchange identifier for execution

    +
    frameName: string

    Unique frame identifier for execution (empty string for live mode)

    +
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    +
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired (required in row, defaults applied in ClientStrategy)

    +
    note?: string

    Human-readable description of signal reason

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    +
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    strategyName: string

    Unique strategy identifier for execution

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when this signal was created/scheduled in backtest context or when getSignal was called in live context (before validation)

    +

    Interface ISignalDto

    Signal data transfer object returned by getSignal. Will be validated and augmented with auto-generated id.

    -
    interface ISignalDto {
        cost?: number;
        id?: string;
        minuteEstimatedTime?: number;
        note?: string;
        position: "long" | "short";
        priceOpen?: number;
        priceStopLoss: number;
        priceTakeProfit: number;
    }

    Hierarchy (View Summary)

    Properties

    interface ISignalDto {
        cost?: number;
        id?: string;
        minuteEstimatedTime?: number;
        note?: string;
        position: "long" | "short";
        priceOpen?: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        symbol?: string;
    }

    Hierarchy (View Summary)

    Properties

    cost? id? minuteEstimatedTime? note? @@ -8,17 +8,19 @@ Will be validated and augmented with auto-generated id.

    priceOpen? priceStopLoss priceTakeProfit +symbol?

    Properties

    cost?: number

    Cost of this entry in USD. Default: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST

    -
    id?: string

    Optional signal ID (auto-generated if not provided)

    -
    minuteEstimatedTime?: number

    Expected duration in minutes before time_expired. +

    id?: string

    Optional signal ID (auto-generated if not provided)

    +
    minuteEstimatedTime?: number

    Expected duration in minutes before time_expired. Use Infinity for no timeout — position stays open until TP/SL or explicit closePending(). Default: GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES

    -
    note?: string

    Human-readable description of signal reason

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen?: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    -
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    -
    +
    note?: string

    Human-readable description of signal reason

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen?: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    +
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    +
    symbol?: string

    Symbol of a ticker on exchange

    +

    Interface ISignalIntervalDto

    Signal dto for IntervalUtils.fn which allows returning multiple signals in one getSignal call. This will pause the next signal untill interval elapses

    -
    interface ISignalIntervalDto {
        cost?: number;
        id: string;
        minuteEstimatedTime?: number;
        note?: string;
        position: "long" | "short";
        priceOpen?: number;
        priceStopLoss: number;
        priceTakeProfit: number;
    }

    Hierarchy (View Summary)

    Properties

    interface ISignalIntervalDto {
        cost?: number;
        id: string;
        minuteEstimatedTime?: number;
        note?: string;
        position: "long" | "short";
        priceOpen?: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        symbol?: string;
    }

    Hierarchy (View Summary)

    Properties

    cost? id minuteEstimatedTime? note? @@ -8,17 +8,19 @@ This will pause the next signal untill interval elapses

    priceOpen? priceStopLoss priceTakeProfit +symbol?

    Properties

    cost?: number

    Cost of this entry in USD. Default: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST

    -
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    -
    minuteEstimatedTime?: number

    Expected duration in minutes before time_expired. +

    id: string

    Unique signal identifier (UUID v4 auto-generated)

    +
    minuteEstimatedTime?: number

    Expected duration in minutes before time_expired. Use Infinity for no timeout — position stays open until TP/SL or explicit closePending(). Default: GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES

    -
    note?: string

    Human-readable description of signal reason

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen?: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    -
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    -
    +
    note?: string

    Human-readable description of signal reason

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen?: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    +
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    +
    symbol?: string

    Symbol of a ticker on exchange

    +

    Interface ISignalRow

    Complete signal with auto-generated id. Used throughout the system after validation.

    -
    interface ISignalRow {
        _entry?: { cost: number; price: number; timestamp: number }[];
        _fall: { price: number; timestamp: number } & IStrategyPnL;
        _isScheduled: boolean;
        _partial?: {
            costBasisAtClose: number;
            currentPrice: number;
            entryCountAtClose: number;
            percent: number;
            timestamp: number;
            type: "profit" | "loss";
        }[];
        _peak: { price: number; timestamp: number } & IStrategyPnL;
        _trailingPriceStopLoss?: number;
        _trailingPriceTakeProfit?: number;
        cost: number;
        exchangeName: string;
        frameName: string;
        id: string;
        minuteEstimatedTime: number;
        note?: string;
        pendingAt: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    interface ISignalRow {
        _entry?: { cost: number; price: number; timestamp: number }[];
        _fall: { price: number; timestamp: number } & IStrategyPnL;
        _isScheduled: boolean;
        _partial?: {
            costBasisAtClose: number;
            currentPrice: number;
            entryCountAtClose: number;
            percent: number;
            timestamp: number;
            type: "profit" | "loss";
        }[];
        _peak: { price: number; timestamp: number } & IStrategyPnL;
        _trailingPriceStopLoss?: number;
        _trailingPriceTakeProfit?: number;
        cost: number;
        exchangeName: string;
        frameName: string;
        id: string;
        minuteEstimatedTime: number;
        note?: string;
        pendingAt: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Hierarchy (View Summary)

    Properties

    _entry? _fall _isScheduled _partial? @@ -30,15 +30,15 @@ Original priceOpen is preserved unchanged for identity/audit purposes.

    Type declaration

    • cost: number

      Cost of this entry in USD (e.g. 100 for $100 position)

    • price: number

      Price at which this entry was executed

    • timestamp: number

      Unix timestamp in milliseconds when this entry was executed

      -
    _fall: { price: number; timestamp: number } & IStrategyPnL

    Worst price seen in loss direction during the life of this position. +

    _fall: { price: number; timestamp: number } & IStrategyPnL

    Worst price seen in loss direction during the life of this position. Initialized at position open with priceOpen/pendingAt (pnl = 0). Updated on every tick/candle when price moves toward SL (currentDistance < 0).

    • For LONG: minimum VWAP price seen below effective entry
    • For SHORT: maximum VWAP price seen above effective entry
    -
    _isScheduled: boolean

    Internal runtime marker for scheduled signals

    -
    _partial?: {
        costBasisAtClose: number;
        currentPrice: number;
        entryCountAtClose: number;
        percent: number;
        timestamp: number;
        type: "profit" | "loss";
    }[]

    History of partial closes for PNL calculation. +

    _isScheduled: boolean

    Internal runtime marker for scheduled signals

    +
    _partial?: {
        costBasisAtClose: number;
        currentPrice: number;
        entryCountAtClose: number;
        percent: number;
        timestamp: number;
        type: "profit" | "loss";
    }[]

    History of partial closes for PNL calculation. Each entry contains type (profit/loss), percent closed, and price. Used to calculate weighted PNL: Σ(percent_i × pnl_i) for each partial + (remaining% × final_pnl)

    Computed values (derived from this array):

    @@ -57,14 +57,14 @@ Used to slice _entry to only entries that existed at this partial.

  • percent: number

    Percentage of position closed (0-100)

  • timestamp: number

    Unix timestamp in milliseconds when this partial close was executed

  • type: "profit" | "loss"

    Type of partial close: profit (moving toward TP) or loss (moving toward SL)

    -
  • _peak: { price: number; timestamp: number } & IStrategyPnL

    Best price seen in profit direction during the life of this position. +

    _peak: { price: number; timestamp: number } & IStrategyPnL

    Best price seen in profit direction during the life of this position. Initialized at position open with priceOpen/pendingAt. Updated on every tick/candle when price moves toward TP (currentDistance > 0).

    • For LONG: maximum VWAP price seen above effective entry
    • For SHORT: minimum VWAP price seen below effective entry
    -
    _trailingPriceStopLoss?: number

    Trailing stop-loss price that overrides priceStopLoss when set. +

    _trailingPriceStopLoss?: number

    Trailing stop-loss price that overrides priceStopLoss when set. Updated by trailing() method based on position type and percentage distance.

    • For LONG: moves upward as price moves toward TP (never moves down)
    • @@ -72,7 +72,7 @@ Updated by trailing() method based on position type and percentage distance.

      When _trailingPriceStopLoss is set, it replaces priceStopLoss for TP/SL checks. Original priceStopLoss is preserved in persistence but ignored during execution.
    -
    _trailingPriceTakeProfit?: number

    Trailing take-profit price that overrides priceTakeProfit when set. +

    _trailingPriceTakeProfit?: number

    Trailing take-profit price that overrides priceTakeProfit when set. Created and managed by trailingTake() method for dynamic TP adjustment. Allows moving TP further from or closer to current price based on strategy. Updated by trailingTake() method based on position type and percentage distance.

    @@ -82,22 +82,22 @@ Updated by trailingTake() method based on position type and percentage distance. When _trailingPriceTakeProfit is set, it replaces priceTakeProfit for TP/SL checks. Original priceTakeProfit is preserved in persistence but ignored during execution. -
    cost: number

    Cost of this entry in USD (e.g. 100 for $100 position)

    -
    exchangeName: string

    Unique exchange identifier for execution

    -
    frameName: string

    Unique frame identifier for execution (empty string for live mode)

    -
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    -
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired (required in row, defaults applied in ClientStrategy)

    -
    note?: string

    Human-readable description of signal reason

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    -
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    strategyName: string

    Unique strategy identifier for execution

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when this signal was created/scheduled in backtest context or when getSignal was called in live context (before validation)

    -
    +
    cost: number

    Cost of this entry in USD (e.g. 100 for $100 position)

    +
    exchangeName: string

    Unique exchange identifier for execution

    +
    frameName: string

    Unique frame identifier for execution (empty string for live mode)

    +
    id: string

    Unique signal identifier (UUID v4 auto-generated)

    +
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired (required in row, defaults applied in ClientStrategy)

    +
    note?: string

    Human-readable description of signal reason

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price (must be < priceOpen for long, > priceOpen for short)

    +
    priceTakeProfit: number

    Take profit target price (must be > priceOpen for long, < priceOpen for short)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    strategyName: string

    Unique strategy identifier for execution

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when this signal was created/scheduled in backtest context or when getSignal was called in live context (before validation)

    +

    Interface ISizingCalculateParamsATR

    Parameters for ATR-based sizing calculation.

    -
    interface ISizingCalculateParamsATR {
        accountBalance: number;
        atr: number;
        method: "atr-based";
        priceOpen: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • ISizingCalculateParamsATR

    Properties

    interface ISizingCalculateParamsATR {
        accountBalance: number;
        atr: number;
        method: "atr-based";
        priceOpen: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • ISizingCalculateParamsATR

    Properties

    accountBalance: number

    Current account balance

    -
    atr: number

    Current ATR value

    -
    method: "atr-based"
    priceOpen: number

    Planned entry price

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    atr: number

    Current ATR value

    +
    method: "atr-based"
    priceOpen: number

    Planned entry price

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface ISizingCalculateParamsFixedPercentage

    Parameters for fixed percentage sizing calculation.

    -
    interface ISizingCalculateParamsFixedPercentage {
        accountBalance: number;
        method: "fixed-percentage";
        priceOpen: number;
        priceStopLoss: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • ISizingCalculateParamsFixedPercentage

    Properties

    interface ISizingCalculateParamsFixedPercentage {
        accountBalance: number;
        method: "fixed-percentage";
        priceOpen: number;
        priceStopLoss: number;
        symbol: string;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • ISizingCalculateParamsFixedPercentage

    Properties

    accountBalance: number

    Current account balance

    -
    method: "fixed-percentage"
    priceOpen: number

    Planned entry price

    -
    priceStopLoss: number

    Stop-loss price

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    method: "fixed-percentage"
    priceOpen: number

    Planned entry price

    +
    priceStopLoss: number

    Stop-loss price

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface ISizingCalculateParamsKelly

    Parameters for Kelly Criterion sizing calculation.

    -
    interface ISizingCalculateParamsKelly {
        accountBalance: number;
        method: "kelly-criterion";
        priceOpen: number;
        symbol: string;
        winLossRatio: number;
        winRate: number;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • ISizingCalculateParamsKelly

    Properties

    interface ISizingCalculateParamsKelly {
        accountBalance: number;
        method: "kelly-criterion";
        priceOpen: number;
        symbol: string;
        winLossRatio: number;
        winRate: number;
    }

    Hierarchy

    • ISizingCalculateParamsBase
      • ISizingCalculateParamsKelly

    Properties

    accountBalance: number

    Current account balance

    -
    method: "kelly-criterion"
    priceOpen: number

    Planned entry price

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    winLossRatio: number

    Average win/loss ratio

    -
    winRate: number

    Win rate (0-1)

    -
    +
    method: "kelly-criterion"
    priceOpen: number

    Planned entry price

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    winLossRatio: number

    Average win/loss ratio

    +
    winRate: number

    Win rate (0-1)

    +

    Interface ISizingParamsATR

    ATR-based sizing parameters for ClientSizing constructor.

    -
    interface ISizingParamsATR {
        atrMultiplier?: number;
        callbacks?: Partial<ISizingCallbacks>;
        logger: ILogger;
        maxPositionPercentage?: number;
        maxPositionSize?: number;
        method: "atr-based";
        minPositionSize?: number;
        note?: string;
        riskPercentage: number;
        sizingName: string;
    }

    Hierarchy (View Summary)

    Properties

    interface ISizingParamsATR {
        atrMultiplier?: number;
        callbacks?: Partial<ISizingCallbacks>;
        logger: ILogger;
        maxPositionPercentage?: number;
        maxPositionSize?: number;
        method: "atr-based";
        minPositionSize?: number;
        note?: string;
        riskPercentage: number;
        sizingName: string;
    }

    Hierarchy (View Summary)

    Properties

    atrMultiplier?: number

    ATR multiplier for stop distance calculation

    -
    callbacks?: Partial<ISizingCallbacks>

    Optional lifecycle callbacks

    -
    logger: ILogger

    Logger service for debug output

    -
    maxPositionPercentage?: number

    Maximum position size as % of account (0-100)

    -
    maxPositionSize?: number

    Maximum position size (absolute value)

    -
    method: "atr-based"
    minPositionSize?: number

    Minimum position size (absolute value)

    -
    note?: string

    Optional developer note for documentation

    -
    riskPercentage: number

    Risk percentage per trade (0-100)

    -
    sizingName: string

    Unique identifier for this sizing configuration

    -
    +
    callbacks?: Partial<ISizingCallbacks>

    Optional lifecycle callbacks

    +
    logger: ILogger

    Logger service for debug output

    +
    maxPositionPercentage?: number

    Maximum position size as % of account (0-100)

    +
    maxPositionSize?: number

    Maximum position size (absolute value)

    +
    method: "atr-based"
    minPositionSize?: number

    Minimum position size (absolute value)

    +
    note?: string

    Optional developer note for documentation

    +
    riskPercentage: number

    Risk percentage per trade (0-100)

    +
    sizingName: string

    Unique identifier for this sizing configuration

    +

    Interface ISizingParamsFixedPercentage

    Fixed percentage sizing parameters for ClientSizing constructor.

    -
    interface ISizingParamsFixedPercentage {
        callbacks?: Partial<ISizingCallbacks>;
        logger: ILogger;
        maxPositionPercentage?: number;
        maxPositionSize?: number;
        method: "fixed-percentage";
        minPositionSize?: number;
        note?: string;
        riskPercentage: number;
        sizingName: string;
    }

    Hierarchy (View Summary)

    Properties

    interface ISizingParamsFixedPercentage {
        callbacks?: Partial<ISizingCallbacks>;
        logger: ILogger;
        maxPositionPercentage?: number;
        maxPositionSize?: number;
        method: "fixed-percentage";
        minPositionSize?: number;
        note?: string;
        riskPercentage: number;
        sizingName: string;
    }

    Hierarchy (View Summary)

    Properties

    callbacks?: Partial<ISizingCallbacks>

    Optional lifecycle callbacks

    -
    logger: ILogger

    Logger service for debug output

    -
    maxPositionPercentage?: number

    Maximum position size as % of account (0-100)

    -
    maxPositionSize?: number

    Maximum position size (absolute value)

    -
    method: "fixed-percentage"
    minPositionSize?: number

    Minimum position size (absolute value)

    -
    note?: string

    Optional developer note for documentation

    -
    riskPercentage: number

    Risk percentage per trade (0-100)

    -
    sizingName: string

    Unique identifier for this sizing configuration

    -
    +
    logger: ILogger

    Logger service for debug output

    +
    maxPositionPercentage?: number

    Maximum position size as % of account (0-100)

    +
    maxPositionSize?: number

    Maximum position size (absolute value)

    +
    method: "fixed-percentage"
    minPositionSize?: number

    Minimum position size (absolute value)

    +
    note?: string

    Optional developer note for documentation

    +
    riskPercentage: number

    Risk percentage per trade (0-100)

    +
    sizingName: string

    Unique identifier for this sizing configuration

    +

    Interface ISizingParamsKelly

    Kelly Criterion sizing parameters for ClientSizing constructor.

    -
    interface ISizingParamsKelly {
        callbacks?: Partial<ISizingCallbacks>;
        kellyMultiplier?: number;
        logger: ILogger;
        maxPositionPercentage?: number;
        maxPositionSize?: number;
        method: "kelly-criterion";
        minPositionSize?: number;
        note?: string;
        sizingName: string;
    }

    Hierarchy (View Summary)

    Properties

    interface ISizingParamsKelly {
        callbacks?: Partial<ISizingCallbacks>;
        kellyMultiplier?: number;
        logger: ILogger;
        maxPositionPercentage?: number;
        maxPositionSize?: number;
        method: "kelly-criterion";
        minPositionSize?: number;
        note?: string;
        sizingName: string;
    }

    Hierarchy (View Summary)

    Properties

    callbacks?: Partial<ISizingCallbacks>

    Optional lifecycle callbacks

    -
    kellyMultiplier?: number

    Kelly Criterion multiplier (0-1, default 0.25 for quarter Kelly)

    -
    logger: ILogger

    Logger service for debug output

    -
    maxPositionPercentage?: number

    Maximum position size as % of account (0-100)

    -
    maxPositionSize?: number

    Maximum position size (absolute value)

    -
    method: "kelly-criterion"
    minPositionSize?: number

    Minimum position size (absolute value)

    -
    note?: string

    Optional developer note for documentation

    -
    sizingName: string

    Unique identifier for this sizing configuration

    -
    +
    kellyMultiplier?: number

    Kelly Criterion multiplier (0-1, default 0.25 for quarter Kelly)

    +
    logger: ILogger

    Logger service for debug output

    +
    maxPositionPercentage?: number

    Maximum position size as % of account (0-100)

    +
    maxPositionSize?: number

    Maximum position size (absolute value)

    +
    method: "kelly-criterion"
    minPositionSize?: number

    Minimum position size (absolute value)

    +
    note?: string

    Optional developer note for documentation

    +
    sizingName: string

    Unique identifier for this sizing configuration

    +

    Interface IStorageUtils

    Base interface for storage adapters. All storage adapters must implement this interface.

    -
    interface IStorageUtils {
        findById(id: string): Promise<IStorageSignalRow>;
        handleActivePing(event: ActivePingContract): Promise<void>;
        handleCancelled(tick: IStrategyTickResultCancelled): Promise<void>;
        handleClosed(tick: IStrategyTickResultClosed): Promise<void>;
        handleOpened(tick: IStrategyTickResultOpened): Promise<void>;
        handleScheduled(tick: IStrategyTickResultScheduled): Promise<void>;
        handleSchedulePing(event: SchedulePingContract): Promise<void>;
        list(): Promise<IStorageSignalRow[]>;
    }

    Methods

    interface IStorageUtils {
        findById(id: string): Promise<IStorageSignalRow>;
        handleActivePing(event: ActivePingContract): Promise<void>;
        handleCancelled(tick: IStrategyTickResultCancelled): Promise<void>;
        handleClosed(tick: IStrategyTickResultClosed): Promise<void>;
        handleOpened(tick: IStrategyTickResultOpened): Promise<void>;
        handleScheduled(tick: IStrategyTickResultScheduled): Promise<void>;
        handleSchedulePing(event: SchedulePingContract): Promise<void>;
        list(): Promise<IStorageSignalRow[]>;
    }

    Methods

    findById handleActivePing handleCancelled handleClosed @@ -11,23 +11,23 @@ All storage adapters must implement this interface.

    Methods

    • Handles active ping event for opened signals. Updates updatedAt for the signal if it is currently opened.

      Parameters

      Returns Promise<void>

    Returns Promise<void>

    Returns Promise<void>

    Returns Promise<void>

    Returns Promise<void>

    • Handles schedule ping event for scheduled signals. +

    Returns Promise<void>

    • Handles schedule ping event for scheduled signals. Updates updatedAt for the signal if it is currently scheduled.

      Parameters

      Returns Promise<void>

    Returns Promise<void>

    +

    Interface IStrategyPnL

    Profit and loss calculation result. Includes adjusted prices with fees (0.1%) and slippage (0.1%).

    -
    interface IStrategyPnL {
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        priceClose: number;
        priceOpen: number;
    }

    Properties

    interface IStrategyPnL {
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        priceClose: number;
        priceOpen: number;
    }

    Properties

    pnlCost: number

    Absolute profit/loss in USD: pnlPercentage / 100 * pnlEntries

    -
    pnlEntries: number

    Total invested capital in USD: sum of all entry costs

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    priceClose: number

    Exit price adjusted with slippage and fees

    -
    priceOpen: number

    Entry price adjusted with slippage and fees

    -
    +
    pnlEntries: number

    Total invested capital in USD: sum of all entry costs

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    priceClose: number

    Exit price adjusted with slippage and fees

    +
    priceOpen: number

    Entry price adjusted with slippage and fees

    +

    Interface IStrategyResult

    Strategy result entry for comparison table. Contains strategy name, full statistics, and metric value for ranking.

    -
    interface IStrategyResult {
        firstEventTime: number;
        lastEventTime: number;
        metricValue: number;
        stats: BacktestStatisticsModel;
        strategyName: string;
    }

    Properties

    interface IStrategyResult {
        firstEventTime: number;
        lastEventTime: number;
        metricValue: number;
        stats: BacktestStatisticsModel;
        strategyName: string;
    }

    Properties

    firstEventTime: number

    Timestamp of the first signal event (pendingAt of earliest signal), null if no signals

    -
    lastEventTime: number

    Timestamp of the last signal event (closeTimestamp of latest signal), null if no signals

    -
    metricValue: number

    Value of the optimization metric (null if invalid)

    -

    Complete backtest statistics for this strategy

    -
    strategyName: string

    Strategy name

    -
    +
    lastEventTime: number

    Timestamp of the last signal event (closeTimestamp of latest signal), null if no signals

    +
    metricValue: number

    Value of the optimization metric (null if invalid)

    +

    Complete backtest statistics for this strategy

    +
    strategyName: string

    Strategy name

    +

    Interface IStrategySchema

    Strategy schema registered via addStrategy(). Defines signal generation logic and configuration.

    -
    interface IStrategySchema {
        actions?: string[];
        callbacks?: Partial<IStrategyCallbacks>;
        getSignal: (
            symbol: string,
            when: Date,
            currentPrice: number,
        ) => Promise<ISignalDto>;
        interval?: SignalInterval;
        note?: string;
        riskList?: string[];
        riskName?: string;
        strategyName: string;
    }

    Properties

    interface IStrategySchema {
        actions?: string[];
        callbacks?: Partial<IStrategyCallbacks>;
        getSignal: (
            symbol: string,
            when: Date,
            currentPrice: number,
        ) => Promise<ISignalDto>;
        interval?: SignalInterval;
        note?: string;
        riskList?: string[];
        riskName?: string;
        strategyName: string;
    }

    Properties

    actions? callbacks? getSignal interval? @@ -9,17 +9,17 @@ Defines signal generation logic and configuration.

    riskName? strategyName

    Properties

    actions?: string[]

    Optional list of action identifiers to attach to this strategy

    -
    callbacks?: Partial<IStrategyCallbacks>

    Optional lifecycle event callbacks (onOpen, onClose)

    -
    getSignal: (
        symbol: string,
        when: Date,
        currentPrice: number,
    ) => Promise<ISignalDto>

    Signal generation function (returns null if no signal, validated DTO if signal). +

    callbacks?: Partial<IStrategyCallbacks>

    Optional lifecycle event callbacks (onOpen, onClose)

    +
    getSignal: (
        symbol: string,
        when: Date,
        currentPrice: number,
    ) => Promise<ISignalDto>

    Signal generation function (returns null if no signal, validated DTO if signal). If priceOpen is provided - becomes scheduled signal waiting for price to reach entry point. If priceOpen is omitted - opens immediately at current price.

    -
    interval?: SignalInterval

    Minimum interval between getSignal calls (throttling)

    +
    interval?: SignalInterval

    Minimum interval between getSignal calls (throttling)

    Default: 1m

    -
    note?: string

    Optional developer note for documentation

    -
    riskList?: string[]

    Optional several risk profile list for risk management (if multiple required)

    -
    riskName?: string

    Optional risk profile identifier for risk management

    -
    strategyName: string

    Unique strategy identifier for registration

    -
    +
    note?: string

    Optional developer note for documentation

    +
    riskList?: string[]

    Optional several risk profile list for risk management (if multiple required)

    +
    riskName?: string

    Optional risk profile identifier for risk management

    +
    strategyName: string

    Unique strategy identifier for registration

    +

    Interface IStrategyTickResultActive

    Tick result: signal is being monitored. Waiting for TP/SL or time expiration.

    -
    interface IStrategyTickResultActive {
        _backtestLastTimestamp: number;
        action: "active";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        percentSl: number;
        percentTp: number;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultActive {
        _backtestLastTimestamp: number;
        action: "active";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        percentSl: number;
        percentTp: number;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    _backtestLastTimestamp action backtest createdAt @@ -14,19 +14,19 @@ Waiting for TP/SL or time expiration.

    strategyName symbol

    Properties

    _backtestLastTimestamp: number

    Unix timestamp in milliseconds of the last processed candle. Used by BacktestLogicPrivateService to advance chunkStart for the next chunk request.

    -
    action: "active"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Current VWAP price for monitoring

    -
    exchangeName: string

    Exchange name for tracking

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -
    percentSl: number

    Percentage progress towards stop loss (0-100%, 0 if moving towards TP)

    -
    percentTp: number

    Percentage progress towards take profit (0-100%, 0 if moving towards SL)

    -

    Unrealized PNL for active position with fees, slippage, and partial closes

    -

    Currently monitored signal

    -
    strategyName: string

    Strategy name for tracking

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    action: "active"

    Discriminator for type-safe union

    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Current VWAP price for monitoring

    +
    exchangeName: string

    Exchange name for tracking

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +
    percentSl: number

    Percentage progress towards stop loss (0-100%, 0 if moving towards TP)

    +
    percentTp: number

    Percentage progress towards take profit (0-100%, 0 if moving towards SL)

    +

    Unrealized PNL for active position with fees, slippage, and partial closes

    +

    Currently monitored signal

    +
    strategyName: string

    Strategy name for tracking

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IStrategyTickResultCancelled

    Tick result: scheduled signal cancelled without opening position. Occurs when scheduled signal doesn't activate or hits stop loss before entry.

    -
    interface IStrategyTickResultCancelled {
        action: "cancelled";
        backtest: boolean;
        cancelId?: string;
        closeTimestamp: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        reason: StrategyCancelReason;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultCancelled {
        action: "cancelled";
        backtest: boolean;
        cancelId?: string;
        closeTimestamp: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        reason: StrategyCancelReason;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    action backtest cancelId? closeTimestamp @@ -13,18 +13,18 @@ Occurs when scheduled signal doesn't activate or hits stop loss before entry.

    strategyName symbol

    Properties

    action: "cancelled"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    cancelId?: string

    Optional cancellation ID (provided when user calls Backtest.cancel() or Live.cancel())

    -
    closeTimestamp: number

    Unix timestamp in milliseconds when signal cancelled

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Final VWAP price at cancellation

    -
    exchangeName: string

    Exchange name for tracking

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -

    Reason for cancellation

    -

    Cancelled scheduled signal

    -
    strategyName: string

    Strategy name for tracking

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    cancelId?: string

    Optional cancellation ID (provided when user calls Backtest.cancel() or Live.cancel())

    +
    closeTimestamp: number

    Unix timestamp in milliseconds when signal cancelled

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Final VWAP price at cancellation

    +
    exchangeName: string

    Exchange name for tracking

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +

    Reason for cancellation

    +

    Cancelled scheduled signal

    +
    strategyName: string

    Strategy name for tracking

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IStrategyTickResultClosed

    Tick result: signal closed with PNL. Final state with close reason and profit/loss calculation.

    -
    interface IStrategyTickResultClosed {
        action: "closed";
        backtest: boolean;
        closeId?: string;
        closeReason: StrategyCloseReason;
        closeTimestamp: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultClosed {
        action: "closed";
        backtest: boolean;
        closeId?: string;
        closeReason: StrategyCloseReason;
        closeTimestamp: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    action backtest closeId? closeReason @@ -14,19 +14,19 @@ Final state with close reason and profit/loss calculation.

    strategyName symbol

    Properties

    action: "closed"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    closeId?: string

    Close ID (only for user-initiated closes with reason "closed")

    -
    closeReason: StrategyCloseReason

    Why signal closed (time_expired | take_profit | stop_loss | closed)

    -
    closeTimestamp: number

    Unix timestamp in milliseconds when signal closed

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Final VWAP price at close

    -
    exchangeName: string

    Exchange name for tracking

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -

    Profit/loss calculation with fees and slippage

    -

    Completed signal with original parameters

    -
    strategyName: string

    Strategy name for tracking

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    closeId?: string

    Close ID (only for user-initiated closes with reason "closed")

    +
    closeReason: StrategyCloseReason

    Why signal closed (time_expired | take_profit | stop_loss | closed)

    +
    closeTimestamp: number

    Unix timestamp in milliseconds when signal closed

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Final VWAP price at close

    +
    exchangeName: string

    Exchange name for tracking

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +

    Profit/loss calculation with fees and slippage

    +

    Completed signal with original parameters

    +
    strategyName: string

    Strategy name for tracking

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IStrategyTickResultIdle

    Tick result: no active signal, idle state.

    -
    interface IStrategyTickResultIdle {
        action: "idle";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        signal: null;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultIdle {
        action: "idle";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        signal: null;
        strategyName: string;
        symbol: string;
    }

    Properties

    action: "idle"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Current VWAP price during idle state

    -
    exchangeName: string

    Exchange name for tracking idle events

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -
    signal: null

    No signal in idle state

    -
    strategyName: string

    Strategy name for tracking idle events

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Current VWAP price during idle state

    +
    exchangeName: string

    Exchange name for tracking idle events

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +
    signal: null

    No signal in idle state

    +
    strategyName: string

    Strategy name for tracking idle events

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IStrategyTickResultOpened

    Tick result: new signal just created. Triggered after getSignal validation and persistence.

    -
    interface IStrategyTickResultOpened {
        action: "opened";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultOpened {
        action: "opened";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    action backtest createdAt currentPrice @@ -10,15 +10,15 @@ Triggered after getSignal validation and persistence.

    strategyName symbol

    Properties

    action: "opened"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Current VWAP price at signal open

    -
    exchangeName: string

    Exchange name for tracking

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -

    Newly created and validated signal with generated ID

    -
    strategyName: string

    Strategy name for tracking

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Current VWAP price at signal open

    +
    exchangeName: string

    Exchange name for tracking

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +

    Newly created and validated signal with generated ID

    +
    strategyName: string

    Strategy name for tracking

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IStrategyTickResultScheduled

    Tick result: scheduled signal created, waiting for price to reach entry point. Triggered when getSignal returns signal with priceOpen specified.

    -
    interface IStrategyTickResultScheduled {
        action: "scheduled";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultScheduled {
        action: "scheduled";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    action backtest createdAt currentPrice @@ -10,15 +10,15 @@ Triggered when getSignal returns signal with priceOpen specified.

    strategyName symbol

    Properties

    action: "scheduled"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Current VWAP price when scheduled signal created

    -
    exchangeName: string

    Exchange name for tracking

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -

    Scheduled signal waiting for activation

    -
    strategyName: string

    Strategy name for tracking

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Current VWAP price when scheduled signal created

    +
    exchangeName: string

    Exchange name for tracking

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +

    Scheduled signal waiting for activation

    +
    strategyName: string

    Strategy name for tracking

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface IStrategyTickResultWaiting

    Tick result: scheduled signal is waiting for price to reach entry point. This is returned on subsequent ticks while monitoring a scheduled signal. Different from "scheduled" which is only returned once when signal is first created.

    -
    interface IStrategyTickResultWaiting {
        action: "waiting";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        percentSl: number;
        percentTp: number;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface IStrategyTickResultWaiting {
        action: "waiting";
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        percentSl: number;
        percentTp: number;
        pnl: IStrategyPnL;
        signal: IPublicSignalRow;
        strategyName: string;
        symbol: string;
    }

    Properties

    action backtest createdAt currentPrice @@ -14,18 +14,18 @@ Different from "scheduled" which is only returned once when signal is strategyName symbol

    Properties

    action: "waiting"

    Discriminator for type-safe union

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Current VWAP price for monitoring

    -
    exchangeName: string

    Exchange name for tracking

    -
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    -
    percentSl: number

    Percentage progress towards stop loss (always 0 for waiting scheduled signals)

    -
    percentTp: number

    Percentage progress towards take profit (always 0 for waiting scheduled signals)

    -

    Unrealized PNL for scheduled position (theoretical, not yet activated)

    -

    Scheduled signal waiting for activation

    -
    strategyName: string

    Strategy name for tracking

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when this tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Current VWAP price for monitoring

    +
    exchangeName: string

    Exchange name for tracking

    +
    frameName: string

    Time frame name for tracking (e.g., "1m", "5m")

    +
    percentSl: number

    Percentage progress towards stop loss (always 0 for waiting scheduled signals)

    +
    percentTp: number

    Percentage progress towards take profit (always 0 for waiting scheduled signals)

    +

    Unrealized PNL for scheduled position (theoretical, not yet activated)

    +

    Scheduled signal waiting for activation

    +
    strategyName: string

    Strategy name for tracking

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +

    Interface ITrailingStopCommitRow

    Queued trailing stop commit.

    -
    interface ITrailingStopCommitRow {
        action: "trailing-stop";
        backtest: boolean;
        currentPrice: number;
        percentShift: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • ITrailingStopCommitRow

    Properties

    interface ITrailingStopCommitRow {
        action: "trailing-stop";
        backtest: boolean;
        currentPrice: number;
        percentShift: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • ITrailingStopCommitRow

    Properties

    action: "trailing-stop"

    Discriminator

    -
    backtest: boolean

    Whether running in backtest mode

    -
    currentPrice: number

    Price at which trailing was set

    -
    percentShift: number

    Percentage shift applied

    -
    symbol: string

    Trading pair symbol

    -
    +
    backtest: boolean

    Whether running in backtest mode

    +
    currentPrice: number

    Price at which trailing was set

    +
    percentShift: number

    Percentage shift applied

    +
    symbol: string

    Trading pair symbol

    +

    Interface ITrailingTakeCommitRow

    Queued trailing take commit.

    -
    interface ITrailingTakeCommitRow {
        action: "trailing-take";
        backtest: boolean;
        currentPrice: number;
        percentShift: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • ITrailingTakeCommitRow

    Properties

    interface ITrailingTakeCommitRow {
        action: "trailing-take";
        backtest: boolean;
        currentPrice: number;
        percentShift: number;
        symbol: string;
    }

    Hierarchy

    • ICommitRowBase
      • ITrailingTakeCommitRow

    Properties

    action: "trailing-take"

    Discriminator

    -
    backtest: boolean

    Whether running in backtest mode

    -
    currentPrice: number

    Price at which trailing was set

    -
    percentShift: number

    Percentage shift applied

    -
    symbol: string

    Trading pair symbol

    -
    +
    backtest: boolean

    Whether running in backtest mode

    +
    currentPrice: number

    Price at which trailing was set

    +
    percentShift: number

    Percentage shift applied

    +
    symbol: string

    Trading pair symbol

    +

    Interface IWalkerResults

    Complete walker results after comparing all strategies.

    -
    interface IWalkerResults {
        bestMetric: number;
        bestStats: BacktestStatisticsModel;
        bestStrategy: string;
        exchangeName: string;
        frameName: string;
        metric: WalkerMetric;
        symbol: string;
        totalStrategies: number;
        walkerName: string;
    }

    Hierarchy (View Summary)

    Properties

    interface IWalkerResults {
        bestMetric: number;
        bestStats: BacktestStatisticsModel;
        bestStrategy: string;
        exchangeName: string;
        frameName: string;
        metric: WalkerMetric;
        symbol: string;
        totalStrategies: number;
        walkerName: string;
    }

    Hierarchy (View Summary)

    Properties

    bestMetric: number

    bestMetric - Best metric value achieved

    -

    bestStats - Best strategy statistics

    -
    bestStrategy: string

    bestStrategy - Best performing strategy name

    -
    exchangeName: string

    Exchange used

    -
    frameName: string

    Frame used

    -
    metric: WalkerMetric

    metric - Metric used for optimization

    -
    symbol: string

    Symbol tested

    -
    totalStrategies: number

    totalStrategies - Total number of strategies tested

    -
    walkerName: string

    Walker name

    -
    +

    bestStats - Best strategy statistics

    +
    bestStrategy: string

    bestStrategy - Best performing strategy name

    +
    exchangeName: string

    Exchange used

    +
    frameName: string

    Frame used

    +
    metric: WalkerMetric

    metric - Metric used for optimization

    +
    symbol: string

    Symbol tested

    +
    totalStrategies: number

    totalStrategies - Total number of strategies tested

    +
    walkerName: string

    Walker name

    +

    Interface IWalkerSchema

    Walker schema registered via addWalker(). Defines A/B testing configuration for multiple strategies.

    -
    interface IWalkerSchema {
        callbacks?: Partial<IWalkerCallbacks>;
        exchangeName: string;
        frameName: string;
        metric?: WalkerMetric;
        note?: string;
        strategies: string[];
        walkerName: string;
    }

    Properties

    interface IWalkerSchema {
        callbacks?: Partial<IWalkerCallbacks>;
        exchangeName: string;
        frameName: string;
        metric?: WalkerMetric;
        note?: string;
        strategies: string[];
        walkerName: string;
    }

    Properties

    callbacks? exchangeName frameName metric? @@ -8,13 +8,13 @@ Defines A/B testing configuration for multiple strategies.

    strategies walkerName

    Properties

    callbacks?: Partial<IWalkerCallbacks>

    Optional lifecycle event callbacks

    -
    exchangeName: string

    Exchange to use for backtesting all strategies

    -
    frameName: string

    Timeframe generator to use for backtesting all strategies

    -
    metric?: WalkerMetric

    Metric to optimize (default: "sharpeRatio")

    -
    note?: string

    Optional developer note for documentation

    -
    strategies: string[]

    List of strategy names to compare (must be registered via addStrategy)

    -
    walkerName: string

    Unique walker identifier for registration

    -
    +
    exchangeName: string

    Exchange to use for backtesting all strategies

    +
    frameName: string

    Timeframe generator to use for backtesting all strategies

    +
    metric?: WalkerMetric

    Metric to optimize (default: "sharpeRatio")

    +
    note?: string

    Optional developer note for documentation

    +
    strategies: string[]

    List of strategy names to compare (must be registered via addStrategy)

    +
    walkerName: string

    Unique walker identifier for registration

    +

    Interface IWalkerStrategyResult

    Result for a single strategy in the comparison.

    -
    interface IWalkerStrategyResult {
        metric: number;
        rank: number;
        stats: BacktestStatisticsModel;
        strategyName: string;
    }

    Properties

    interface IWalkerStrategyResult {
        metric: number;
        rank: number;
        stats: BacktestStatisticsModel;
        strategyName: string;
    }

    Properties

    metric: number

    Metric value used for comparison (null if invalid)

    -
    rank: number

    Rank position (1 = best, 2 = second best, etc.)

    -

    Backtest statistics for this strategy

    -
    strategyName: string

    Strategy name

    -
    +
    rank: number

    Rank position (1 = best, 2 = second best, etc.)

    +

    Backtest statistics for this strategy

    +
    strategyName: string

    Strategy name

    +

    Interface InfoErrorNotification

    Error notification. Emitted for recoverable errors in background tasks.

    -
    interface InfoErrorNotification {
        backtest: boolean;
        error: object;
        id: string;
        message: string;
        type: "error.info";
    }

    Properties

    interface InfoErrorNotification {
        backtest: boolean;
        error: object;
        id: string;
        message: string;
        type: "error.info";
    }

    Properties

    backtest: boolean

    Always false for error notifications (errors are from live context)

    -
    error: object

    Serialized error object with stack trace and metadata

    -
    id: string

    Unique notification identifier

    -
    message: string

    Human-readable error message

    -
    type: "error.info"

    Discriminator for type-safe union

    -
    +
    error: object

    Serialized error object with stack trace and metadata

    +
    id: string

    Unique notification identifier

    +
    message: string

    Human-readable error message

    +
    type: "error.info"

    Discriminator for type-safe union

    +

    Interface MaxDrawdownEvent

    Single max drawdown event recorded for a position.

    -
    interface MaxDrawdownEvent {
        backtest: boolean;
        currentPrice: number;
        maxDrawdown: IStrategyPnL;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Properties

    interface MaxDrawdownEvent {
        backtest: boolean;
        currentPrice: number;
        maxDrawdown: IStrategyPnL;
        peakProfit: IStrategyPnL;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Properties

    backtest: boolean

    Whether the event occurred in backtest mode

    -
    currentPrice: number

    Record price reached in the loss direction

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Position direction

    -
    priceOpen: number

    Effective entry price at the time of the update

    -
    priceStopLoss: number

    Stop loss price

    -
    priceTakeProfit: number

    Take profit price

    -
    signalId: string

    Signal unique identifier

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Unix timestamp in milliseconds when the record was set

    -
    +
    currentPrice: number

    Record price reached in the loss direction

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Position direction

    +
    priceOpen: number

    Effective entry price at the time of the update

    +
    priceStopLoss: number

    Stop loss price

    +
    priceTakeProfit: number

    Take profit price

    +
    signalId: string

    Signal unique identifier

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Unix timestamp in milliseconds when the record was set

    +

    Interface MaxDrawdownStatisticsModel

    Aggregated statistics model for max drawdown events.

    -
    interface MaxDrawdownStatisticsModel {
        eventList: MaxDrawdownEvent[];
        totalEvents: number;
    }

    Properties

    interface MaxDrawdownStatisticsModel {
        eventList: MaxDrawdownEvent[];
        totalEvents: number;
    }

    Properties

    eventList: MaxDrawdownEvent[]

    Full list of recorded events (newest first)

    -
    totalEvents: number

    Total number of recorded events

    -
    +
    totalEvents: number

    Total number of recorded events

    +

    Interface MessageModel<Role>

    A single message in an LLM chat history. Covers all roles: system instructions, user input, assistant responses, and tool results.

    -
    interface MessageModel<Role extends MessageRole = MessageRole> {
        content: string;
        images?: string[] | Blob[] | Uint8Array<ArrayBufferLike>[];
        reasoning_content?: string;
        role: Role;
        tool_call_id?: string;
        tool_calls?: MessageToolCall[];
    }

    Type Parameters

    Properties

    interface MessageModel<Role extends MessageRole = MessageRole> {
        content: string;
        images?: string[] | Blob[] | Uint8Array<ArrayBufferLike>[];
        reasoning_content?: string;
        role: Role;
        tool_call_id?: string;
        tool_calls?: MessageToolCall[];
    }

    Type Parameters

    Properties

    content: string

    Text content of the message. Empty string for assistant messages that only contain tool_calls.

    -
    images?: string[] | Blob[] | Uint8Array<ArrayBufferLike>[]

    Images attached to the message. Supported as Blob, raw bytes, or base64 strings.

    -
    reasoning_content?: string

    Chain-of-thought / reasoning exposed by some providers (e.g. DeepSeek).

    -
    role: Role

    Sender role — determines how the message is interpreted by the model.

    -
    tool_call_id?: string

    ID of the tool call this message is responding to. Present only on tool messages.

    -
    tool_calls?: MessageToolCall[]

    Tool calls emitted by the assistant. Present only on assistant messages.

    -
    +
    images?: string[] | Blob[] | Uint8Array<ArrayBufferLike>[]

    Images attached to the message. Supported as Blob, raw bytes, or base64 strings.

    +
    reasoning_content?: string

    Chain-of-thought / reasoning exposed by some providers (e.g. DeepSeek).

    +
    role: Role

    Sender role — determines how the message is interpreted by the model.

    +
    tool_call_id?: string

    ID of the tool call this message is responding to. Present only on tool messages.

    +
    tool_calls?: MessageToolCall[]

    Tool calls emitted by the assistant. Present only on assistant messages.

    +

    Interface MetricStats

    Aggregated statistics for a specific metric type.

    -
    interface MetricStats {
        avgDuration: number;
        avgWaitTime: number;
        count: number;
        maxDuration: number;
        maxWaitTime: number;
        median: number;
        metricType: PerformanceMetricType;
        minDuration: number;
        minWaitTime: number;
        p95: number;
        p99: number;
        stdDev: number;
        totalDuration: number;
    }

    Properties

    interface MetricStats {
        avgDuration: number;
        avgWaitTime: number;
        count: number;
        maxDuration: number;
        maxWaitTime: number;
        median: number;
        metricType: PerformanceMetricType;
        minDuration: number;
        minWaitTime: number;
        p95: number;
        p99: number;
        stdDev: number;
        totalDuration: number;
    }

    Properties

    avgDuration: number

    Average duration (ms)

    -
    avgWaitTime: number

    Average wait time between events (ms)

    -
    count: number

    Number of recorded samples

    -
    maxDuration: number

    Maximum duration (ms)

    -
    maxWaitTime: number

    Maximum wait time between events (ms)

    -
    median: number

    Median duration (ms)

    -

    Type of metric

    -
    minDuration: number

    Minimum duration (ms)

    -
    minWaitTime: number

    Minimum wait time between events (ms)

    -
    p95: number

    95th percentile duration (ms)

    -
    p99: number

    99th percentile duration (ms)

    -
    stdDev: number

    Standard deviation of duration (ms)

    -
    totalDuration: number

    Total duration across all samples (ms)

    -
    +
    avgWaitTime: number

    Average wait time between events (ms)

    +
    count: number

    Number of recorded samples

    +
    maxDuration: number

    Maximum duration (ms)

    +
    maxWaitTime: number

    Maximum wait time between events (ms)

    +
    median: number

    Median duration (ms)

    +

    Type of metric

    +
    minDuration: number

    Minimum duration (ms)

    +
    minWaitTime: number

    Minimum wait time between events (ms)

    +
    p95: number

    95th percentile duration (ms)

    +
    p99: number

    99th percentile duration (ms)

    +
    stdDev: number

    Standard deviation of duration (ms)

    +
    totalDuration: number

    Total duration across all samples (ms)

    +

    Interface PartialEvent

    Unified partial profit/loss event data for report generation. Contains all information about profit and loss level milestones.

    -
    interface PartialEvent {
        action: "profit" | "loss";
        backtest: boolean;
        currentPrice: number;
        level: PartialLevel;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        pendingAt?: number;
        pnl?: IStrategyPnL;
        position: string;
        priceOpen?: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    interface PartialEvent {
        action: "profit" | "loss";
        backtest: boolean;
        currentPrice: number;
        level: PartialLevel;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        pendingAt?: number;
        pnl?: IStrategyPnL;
        position: string;
        priceOpen?: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    action backtest currentPrice level @@ -23,28 +23,28 @@ Contains all information about profit and loss level milestones.

    totalEntries? totalPartials?

    Properties

    action: "profit" | "loss"

    Event action type (profit or loss)

    -
    backtest: boolean

    True if backtest mode, false if live mode

    -
    currentPrice: number

    Current market price

    -
    level: PartialLevel

    Profit/loss level reached (10, 20, 30, etc)

    -
    note?: string

    Human-readable description of signal reason

    -
    originalPriceOpen?: number

    Original entry price before DCA averaging (present when averageBuy was applied)

    -
    originalPriceStopLoss?: number

    Original stop loss price set at signal creation

    -
    originalPriceTakeProfit?: number

    Original take profit price set at signal creation

    -
    partialExecuted?: number

    Total executed percentage from partial closes

    -
    pendingAt?: number

    Timestamp when position became active (ms)

    -

    Unrealized PNL at the moment this level was reached

    -
    position: string

    Position type

    -
    priceOpen?: number

    Entry price for the position

    -
    priceStopLoss?: number

    Stop loss exit price

    -
    priceTakeProfit?: number

    Take profit target price

    -
    scheduledAt?: number

    Timestamp when signal was created/scheduled (ms)

    -
    signalId: string

    Signal ID

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Event timestamp in milliseconds

    -
    totalEntries?: number

    Total number of DCA entries (present when averageBuy was applied)

    -
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    -
    +
    backtest: boolean

    True if backtest mode, false if live mode

    +
    currentPrice: number

    Current market price

    +
    level: PartialLevel

    Profit/loss level reached (10, 20, 30, etc)

    +
    note?: string

    Human-readable description of signal reason

    +
    originalPriceOpen?: number

    Original entry price before DCA averaging (present when averageBuy was applied)

    +
    originalPriceStopLoss?: number

    Original stop loss price set at signal creation

    +
    originalPriceTakeProfit?: number

    Original take profit price set at signal creation

    +
    partialExecuted?: number

    Total executed percentage from partial closes

    +
    pendingAt?: number

    Timestamp when position became active (ms)

    +

    Unrealized PNL at the moment this level was reached

    +
    position: string

    Position type

    +
    priceOpen?: number

    Entry price for the position

    +
    priceStopLoss?: number

    Stop loss exit price

    +
    priceTakeProfit?: number

    Take profit target price

    +
    scheduledAt?: number

    Timestamp when signal was created/scheduled (ms)

    +
    signalId: string

    Signal ID

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Event timestamp in milliseconds

    +
    totalEntries?: number

    Total number of DCA entries (present when averageBuy was applied)

    +
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    +

    Interface PartialLossAvailableNotification

    Partial loss notification. Emitted when signal reaches loss level milestone (-10%, -20%, etc).

    -
    interface PartialLossAvailableNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        level: PartialLevel;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_loss.available";
    }

    Properties

    interface PartialLossAvailableNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        level: PartialLevel;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_loss.available";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when signal reaches loss level milestone (-10%, -20%, etc).

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when milestone was reached

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    level: PartialLevel

    Loss level milestone reached (10, 20, 30, etc)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when partial loss level was reached

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "partial_loss.available"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when milestone was reached

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    level: PartialLevel

    Loss level milestone reached (10, 20, 30, etc)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when partial loss level was reached

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "partial_loss.available"

    Discriminator for type-safe union

    +

    Interface PartialLossCommit

    Partial loss event.

    -
    interface PartialLossCommit {
        action: "partial-loss";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • PartialLossCommit

    Properties

    interface PartialLossCommit {
        action: "partial-loss";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • PartialLossCommit

    Properties

    action: "partial-loss"

    Discriminator for partial-loss action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price at time of action

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    -
    percentToClose: number

    Percentage of position to close (0-100)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    -
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price at time of action

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    +
    percentToClose: number

    Percentage of position to close (0-100)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    +
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface PartialLossCommitNotification

    Partial loss commit notification. Emitted when partial loss action is executed.

    -
    interface PartialLossCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_loss.commit";
    }

    Properties

    interface PartialLossCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_loss.commit";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when partial loss action is executed.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when partial was executed

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    percentToClose: number

    Percentage of position closed (0-100)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when partial loss was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "partial_loss.commit"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when partial was executed

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    percentToClose: number

    Percentage of position closed (0-100)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when partial loss was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "partial_loss.commit"

    Discriminator for type-safe union

    +

    Interface PartialProfitAvailableNotification

    Partial profit notification. Emitted when signal reaches profit level milestone (10%, 20%, etc).

    -
    interface PartialProfitAvailableNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        level: PartialLevel;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_profit.available";
    }

    Properties

    interface PartialProfitAvailableNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        level: PartialLevel;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_profit.available";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when signal reaches profit level milestone (10%, 20%, etc).

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when milestone was reached

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    level: PartialLevel

    Profit level milestone reached (10, 20, 30, etc)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when partial profit level was reached

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "partial_profit.available"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when milestone was reached

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    level: PartialLevel

    Profit level milestone reached (10, 20, 30, etc)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when partial profit level was reached

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "partial_profit.available"

    Discriminator for type-safe union

    +

    Interface PartialProfitCommit

    Partial profit event.

    -
    interface PartialProfitCommit {
        action: "partial-profit";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • PartialProfitCommit

    Properties

    interface PartialProfitCommit {
        action: "partial-profit";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • PartialProfitCommit

    Properties

    action: "partial-profit"

    Discriminator for partial-profit action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price at time of action

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    -
    percentToClose: number

    Percentage of position to close (0-100)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    -
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price at time of action

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    +
    percentToClose: number

    Percentage of position to close (0-100)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    +
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface PartialProfitCommitNotification

    Partial profit commit notification. Emitted when partial profit action is executed.

    -
    interface PartialProfitCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_profit.commit";
    }

    Properties

    interface PartialProfitCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentToClose: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "partial_profit.commit";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when partial profit action is executed.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when partial was executed

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    percentToClose: number

    Percentage of position closed (0-100)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when partial profit was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "partial_profit.commit"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when partial was executed

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    percentToClose: number

    Percentage of position closed (0-100)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when partial profit was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "partial_profit.commit"

    Discriminator for type-safe union

    +

    Interface PerformanceStatisticsModel

    Performance statistics aggregated by strategy.

    -
    interface PerformanceStatisticsModel {
        events: PerformanceContract[];
        metricStats: Record<string, MetricStats>;
        strategyName: string;
        totalDuration: number;
        totalEvents: number;
    }

    Properties

    interface PerformanceStatisticsModel {
        events: PerformanceContract[];
        metricStats: Record<string, MetricStats>;
        strategyName: string;
        totalDuration: number;
        totalEvents: number;
    }

    Properties

    All raw performance events

    -
    metricStats: Record<string, MetricStats>

    Statistics grouped by metric type

    -
    strategyName: string

    Strategy name

    -
    totalDuration: number

    Total execution time across all metrics (ms)

    -
    totalEvents: number

    Total number of performance events recorded

    -
    +
    metricStats: Record<string, MetricStats>

    Statistics grouped by metric type

    +
    strategyName: string

    Strategy name

    +
    totalDuration: number

    Total execution time across all metrics (ms)

    +
    totalEvents: number

    Total number of performance events recorded

    +

    Interface RiskEvent

    Risk rejection event data for report generation. Contains all information about rejected signals due to risk limits.

    -
    interface RiskEvent {
        activePositionCount: number;
        backtest: boolean;
        currentPrice: number;
        currentSignal: IRiskSignalRow;
        exchangeName: string;
        frameName: string;
        rejectionId: string;
        rejectionNote: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Properties

    interface RiskEvent {
        activePositionCount: number;
        backtest: boolean;
        currentPrice: number;
        currentSignal: IRiskSignalRow;
        exchangeName: string;
        frameName: string;
        rejectionId: string;
        rejectionNote: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
    }

    Properties

    activePositionCount backtest currentPrice currentSignal @@ -12,17 +12,17 @@ Contains all information about rejected signals due to risk limits.

    symbol timestamp

    Properties

    activePositionCount: number

    Number of active positions at rejection time

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price

    -
    currentSignal: IRiskSignalRow

    Pending signal details

    -
    exchangeName: string

    Exchange name

    -
    frameName: string

    Time frame name

    -
    rejectionId: string

    Unique identifier for this rejection instance (null if validation threw exception without custom ID)

    -
    rejectionNote: string

    Rejection reason from validation note

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Event timestamp in milliseconds

    -
    +
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price

    +
    currentSignal: IRiskSignalRow

    Pending signal details

    +
    exchangeName: string

    Exchange name

    +
    frameName: string

    Time frame name

    +
    rejectionId: string

    Unique identifier for this rejection instance (null if validation threw exception without custom ID)

    +
    rejectionNote: string

    Rejection reason from validation note

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Event timestamp in milliseconds

    +

    Interface RiskRejectionNotification

    Risk rejection notification. Emitted when a signal is rejected due to risk management rules.

    -
    interface RiskRejectionNotification {
        activePositionCount: number;
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        minuteEstimatedTime: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        rejectionId: string;
        rejectionNote: string;
        signalId: string;
        signalNote?: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        type: "risk.rejection";
    }

    Properties

    interface RiskRejectionNotification {
        activePositionCount: number;
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        minuteEstimatedTime: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        rejectionId: string;
        rejectionNote: string;
        signalId: string;
        signalNote?: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        type: "risk.rejection";
    }

    Properties

    activePositionCount backtest createdAt currentPrice @@ -20,25 +20,25 @@ Emitted when a signal is rejected due to risk management rules.

    timestamp type

    Properties

    activePositionCount: number

    Number of currently active positions at rejection time

    -
    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when rejection occurred

    -
    exchangeName: string

    Exchange name where signal was rejected

    -
    id: string

    Unique notification identifier

    -
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position (may be undefined if not provided)

    -
    priceStopLoss: number

    Stop loss exit price

    -
    priceTakeProfit: number

    Take profit target price

    -
    rejectionId: string

    Optional unique rejection identifier for tracking

    -
    rejectionNote: string

    Human-readable reason for rejection

    -
    signalId: string

    Unique signal identifier from pending signal (may be undefined if not provided)

    -
    signalNote?: string

    Optional human-readable description of signal reason

    -
    strategyName: string

    Strategy name that attempted to create signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was rejected

    -
    type: "risk.rejection"

    Discriminator for type-safe union

    -
    +
    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when rejection occurred

    +
    exchangeName: string

    Exchange name where signal was rejected

    +
    id: string

    Unique notification identifier

    +
    minuteEstimatedTime: number

    Expected duration in minutes before time_expired

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position (may be undefined if not provided)

    +
    priceStopLoss: number

    Stop loss exit price

    +
    priceTakeProfit: number

    Take profit target price

    +
    rejectionId: string

    Optional unique rejection identifier for tracking

    +
    rejectionNote: string

    Human-readable reason for rejection

    +
    signalId: string

    Unique signal identifier from pending signal (may be undefined if not provided)

    +
    signalNote?: string

    Optional human-readable description of signal reason

    +
    strategyName: string

    Strategy name that attempted to create signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was rejected

    +
    type: "risk.rejection"

    Discriminator for type-safe union

    +

    Interface ScheduledEvent

    Unified scheduled signal event data for report generation. Contains all information about scheduled, opened and cancelled events.

    -
    interface ScheduledEvent {
        action: "opened" | "scheduled" | "cancelled";
        cancelId?: string;
        cancelReason?: "timeout" | "user" | "price_reject";
        closeTimestamp?: number;
        currentPrice: number;
        duration?: number;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        pendingAt?: number;
        pnl?: IStrategyPnL;
        position: string;
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt?: number;
        signalId: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    interface ScheduledEvent {
        action: "opened" | "scheduled" | "cancelled";
        cancelId?: string;
        cancelReason?: "timeout" | "user" | "price_reject";
        closeTimestamp?: number;
        currentPrice: number;
        duration?: number;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        pendingAt?: number;
        pnl?: IStrategyPnL;
        position: string;
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt?: number;
        signalId: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    action cancelId? cancelReason? closeTimestamp? @@ -24,29 +24,29 @@ Contains all information about scheduled, opened and cancelled events.

    totalEntries? totalPartials?

    Properties

    action: "opened" | "scheduled" | "cancelled"

    Event action type

    -
    cancelId?: string

    Cancellation ID (only for user-initiated cancellations)

    -
    cancelReason?: "timeout" | "user" | "price_reject"

    Cancellation reason (only for cancelled events)

    -
    closeTimestamp?: number

    Close timestamp (only for cancelled)

    -
    currentPrice: number

    Current market price

    -
    duration?: number

    Duration in minutes (only for cancelled/opened)

    -
    note?: string

    Signal note

    -
    originalPriceOpen?: number

    Original entry price before DCA averaging (present when averageBuy was applied)

    -
    originalPriceStopLoss?: number

    Original stop loss price before modifications

    -
    originalPriceTakeProfit?: number

    Original take profit price before modifications

    -
    partialExecuted?: number

    Total executed percentage from partial closes

    -
    pendingAt?: number

    Timestamp when position became active (only for opened events)

    -

    Unrealized PNL at the moment of this event

    -
    position: string

    Position type

    -
    priceOpen: number

    Scheduled entry price

    -
    priceStopLoss: number

    Stop loss price

    -
    priceTakeProfit: number

    Take profit price

    -
    scheduledAt?: number

    Timestamp when signal was created/scheduled (for all events)

    -
    signalId: string

    Signal ID

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Event timestamp in milliseconds (scheduledAt for scheduled/cancelled events)

    -
    totalEntries?: number

    Total number of DCA entries (present when averageBuy was applied)

    -
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    -
    +
    cancelId?: string

    Cancellation ID (only for user-initiated cancellations)

    +
    cancelReason?: "timeout" | "user" | "price_reject"

    Cancellation reason (only for cancelled events)

    +
    closeTimestamp?: number

    Close timestamp (only for cancelled)

    +
    currentPrice: number

    Current market price

    +
    duration?: number

    Duration in minutes (only for cancelled/opened)

    +
    note?: string

    Signal note

    +
    originalPriceOpen?: number

    Original entry price before DCA averaging (present when averageBuy was applied)

    +
    originalPriceStopLoss?: number

    Original stop loss price before modifications

    +
    originalPriceTakeProfit?: number

    Original take profit price before modifications

    +
    partialExecuted?: number

    Total executed percentage from partial closes

    +
    pendingAt?: number

    Timestamp when position became active (only for opened events)

    +

    Unrealized PNL at the moment of this event

    +
    position: string

    Position type

    +
    priceOpen: number

    Scheduled entry price

    +
    priceStopLoss: number

    Stop loss price

    +
    priceTakeProfit: number

    Take profit price

    +
    scheduledAt?: number

    Timestamp when signal was created/scheduled (for all events)

    +
    signalId: string

    Signal ID

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Event timestamp in milliseconds (scheduledAt for scheduled/cancelled events)

    +
    totalEntries?: number

    Total number of DCA entries (present when averageBuy was applied)

    +
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    +

    Interface SignalCancelledNotification

    Signal cancelled notification. Emitted when a scheduled signal is cancelled before activation.

    -
    interface SignalCancelledNotification {
        backtest: boolean;
        cancelId: string;
        cancelReason: string;
        createdAt: number;
        duration: number;
        exchangeName: string;
        id: string;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        pendingAt: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.cancelled";
    }

    Properties

    interface SignalCancelledNotification {
        backtest: boolean;
        cancelId: string;
        cancelReason: string;
        createdAt: number;
        duration: number;
        exchangeName: string;
        id: string;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        pendingAt: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.cancelled";
    }

    Properties

    backtest cancelId cancelReason createdAt @@ -25,30 +25,30 @@ Emitted when a scheduled signal is cancelled before activation.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    cancelId: string

    Optional cancellation identifier (provided when user calls cancel())

    -
    cancelReason: string

    Why signal was cancelled (timeout | price_reject | user)

    -
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    duration: number

    Duration in minutes from scheduledAt to cancellation

    -
    exchangeName: string

    Exchange name where signal was scheduled

    -
    id: string

    Unique notification identifier

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price

    -
    priceTakeProfit: number

    Take profit target price

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was cancelled (closeTimestamp)

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal.cancelled"

    Discriminator for type-safe union

    -
    +
    cancelId: string

    Optional cancellation identifier (provided when user calls cancel())

    +
    cancelReason: string

    Why signal was cancelled (timeout | price_reject | user)

    +
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    duration: number

    Duration in minutes from scheduledAt to cancellation

    +
    exchangeName: string

    Exchange name where signal was scheduled

    +
    id: string

    Unique notification identifier

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price

    +
    priceTakeProfit: number

    Take profit target price

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was cancelled (closeTimestamp)

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal.cancelled"

    Discriminator for type-safe union

    +

    Interface SignalClosedNotification

    Signal closed notification. Emitted when a trading position is closed (TP/SL hit).

    -
    interface SignalClosedNotification {
        backtest: boolean;
        closeReason: string;
        createdAt: number;
        duration: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceClose: number;
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.closed";
    }

    Properties

    interface SignalClosedNotification {
        backtest: boolean;
        closeReason: string;
        createdAt: number;
        duration: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceClose: number;
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.closed";
    }

    Properties

    backtest closeReason createdAt duration @@ -43,48 +43,48 @@ Emitted when a trading position is closed (TP/SL hit).

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    closeReason: string

    Why signal closed (time_expired | take_profit | stop_loss | closed)

    -
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    duration: number

    Duration of position in minutes (from pendingAt to closeTimestamp)

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceClose: number

    Exit price when position was closed

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price

    -
    priceTakeProfit: number

    Take profit target price

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was closed (closeTimestamp)

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal.closed"

    Discriminator for type-safe union

    -
    +
    closeReason: string

    Why signal closed (time_expired | take_profit | stop_loss | closed)

    +
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    duration: number

    Duration of position in minutes (from pendingAt to closeTimestamp)

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceClose: number

    Exit price when position was closed

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price

    +
    priceTakeProfit: number

    Take profit target price

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was closed (closeTimestamp)

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal.closed"

    Discriminator for type-safe union

    +

    Interface SignalInfoNotification

    Signal info notification. Emitted when a strategy broadcasts a user-defined informational note for an open position.

    -
    interface SignalInfoNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note: string;
        notificationId?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.info";
    }

    Properties

    interface SignalInfoNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note: string;
        notificationId?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.info";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when a strategy broadcasts a user-defined informational note for an open totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when the info event was emitted

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note: string

    User-defined informational note provided by the strategy

    -
    notificationId?: string

    Optional user-defined identifier for correlating this notification with external systems

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when the info event was emitted

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal.info"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when the info event was emitted

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note: string

    User-defined informational note provided by the strategy

    +
    notificationId?: string

    Optional user-defined identifier for correlating this notification with external systems

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when the info event was emitted

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal.info"

    Discriminator for type-safe union

    +

    Interface SignalOpenedNotification

    Signal opened notification. Emitted when a new trading position is opened.

    -
    interface SignalOpenedNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.opened";
    }

    Properties

    interface SignalOpenedNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.opened";
    }

    Properties

    backtest cost createdAt exchangeName @@ -41,46 +41,46 @@ Emitted when a new trading position is opened.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    cost: number

    Cost of the initial position entry in USD (from signal.cost)

    -
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Stop loss exit price

    -
    priceTakeProfit: number

    Take profit target price

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was opened (pendingAt)

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal.opened"

    Discriminator for type-safe union

    -
    +
    cost: number

    Cost of the initial position entry in USD (from signal.cost)

    +
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Stop loss exit price

    +
    priceTakeProfit: number

    Take profit target price

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was opened (pendingAt)

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal.opened"

    Discriminator for type-safe union

    +

    Interface SignalScheduledNotification

    Scheduled signal notification. Emitted when a signal is scheduled for future execution.

    -
    interface SignalScheduledNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.scheduled";
    }

    Properties

    interface SignalScheduledNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal.scheduled";
    }

    Properties

    backtest cost createdAt currentPrice @@ -41,46 +41,46 @@ Emitted when a signal is scheduled for future execution.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    cost: number

    Cost of the initial position entry in USD (from signal.cost)

    -
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    -
    currentPrice: number

    Current market price when signal was scheduled

    -
    exchangeName: string

    Exchange name where signal will be executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Target entry price for activation

    -
    priceStopLoss: number

    Stop loss exit price

    -
    priceTakeProfit: number

    Take profit target price

    -
    scheduledAt: number

    Unix timestamp in milliseconds when signal was scheduled

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was scheduled (scheduledAt)

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal.scheduled"

    Discriminator for type-safe union

    -
    +
    cost: number

    Cost of the initial position entry in USD (from signal.cost)

    +
    createdAt: number

    Unix timestamp in milliseconds when the tick result was created (from candle timestamp in backtest or execution context when in live)

    +
    currentPrice: number

    Current market price when signal was scheduled

    +
    exchangeName: string

    Exchange name where signal will be executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Target entry price for activation

    +
    priceStopLoss: number

    Stop loss exit price

    +
    priceTakeProfit: number

    Take profit target price

    +
    scheduledAt: number

    Unix timestamp in milliseconds when signal was scheduled

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was scheduled (scheduledAt)

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal.scheduled"

    Discriminator for type-safe union

    +

    Interface SignalSyncCloseNotification

    Signal sync close notification. Emitted when an active pending signal is closed (TP/SL hit, time expired, or user-initiated).

    -
    interface SignalSyncCloseNotification {
        backtest: boolean;
        closeReason: string;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal_sync.close";
    }

    Properties

    interface SignalSyncCloseNotification {
        backtest: boolean;
        closeReason: string;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal_sync.close";
    }

    Properties

    backtest closeReason createdAt currentPrice @@ -42,47 +42,47 @@ Emitted when an active pending signal is closed (TP/SL hit, time expired, or use totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    closeReason: string

    Why the signal was closed (take_profit | stop_loss | time_expired | closed)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price at close

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price before any DCA averaging

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Position activation timestamp in milliseconds

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage

    -
    pnlPriceClose: number

    Exit price from PNL calculation

    -
    pnlPriceOpen: number

    Entry price from PNL calculation

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Effective entry price at close

    -
    priceStopLoss: number

    Effective stop loss price at close

    -
    priceTakeProfit: number

    Effective take profit price at close

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was closed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal_sync.close"

    Discriminator for type-safe union

    -
    +
    closeReason: string

    Why the signal was closed (take_profit | stop_loss | time_expired | closed)

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price at close

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price before any DCA averaging

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Position activation timestamp in milliseconds

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage

    +
    pnlPriceClose: number

    Exit price from PNL calculation

    +
    pnlPriceOpen: number

    Entry price from PNL calculation

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Effective entry price at close

    +
    priceStopLoss: number

    Effective stop loss price at close

    +
    priceTakeProfit: number

    Effective take profit price at close

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was closed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal_sync.close"

    Discriminator for type-safe union

    +

    Interface SignalSyncOpenNotification

    Signal sync open notification. Emitted when a scheduled (limit order) signal is activated and the position is opened.

    -
    interface SignalSyncOpenNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal_sync.open";
    }

    Properties

    interface SignalSyncOpenNotification {
        backtest: boolean;
        cost: number;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "signal_sync.open";
    }

    Properties

    backtest cost createdAt currentPrice @@ -42,47 +42,47 @@ Emitted when a scheduled (limit order) signal is activated and the position is o totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    cost: number

    Cost of the position entry in USD

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price at activation

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price before any DCA averaging

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Position activation timestamp in milliseconds

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage

    -
    pnlPriceClose: number

    Exit price from PNL calculation

    -
    pnlPriceOpen: number

    Entry price from PNL calculation

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price at which the limit order was filled

    -
    priceStopLoss: number

    Effective stop loss price at activation

    -
    priceTakeProfit: number

    Effective take profit price at activation

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when signal was opened

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "signal_sync.open"

    Discriminator for type-safe union

    -
    +
    cost: number

    Cost of the position entry in USD

    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price at activation

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price before any DCA averaging

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Position activation timestamp in milliseconds

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage

    +
    pnlPriceClose: number

    Exit price from PNL calculation

    +
    pnlPriceOpen: number

    Entry price from PNL calculation

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price at which the limit order was filled

    +
    priceStopLoss: number

    Effective stop loss price at activation

    +
    priceTakeProfit: number

    Effective take profit price at activation

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when signal was opened

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "signal_sync.open"

    Discriminator for type-safe union

    +

    Interface StrategyEvent

    Unified strategy event data for markdown report generation. Contains all information about strategy management actions.

    -
    interface StrategyEvent {
        action: StrategyActionType;
        activateId?: string;
        backtest: boolean;
        cancelId?: string;
        closeId?: string;
        cost?: number;
        createdAt: string;
        currentPrice?: number;
        effectivePriceOpen?: number;
        exchangeName: string;
        frameName: string;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        pendingAt?: number;
        percentShift?: number;
        percentToClose?: number;
        pnl?: IStrategyPnL;
        position?: "long" | "short";
        priceOpen?: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    interface StrategyEvent {
        action: StrategyActionType;
        activateId?: string;
        backtest: boolean;
        cancelId?: string;
        closeId?: string;
        cost?: number;
        createdAt: string;
        currentPrice?: number;
        effectivePriceOpen?: number;
        exchangeName: string;
        frameName: string;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        pendingAt?: number;
        percentShift?: number;
        percentToClose?: number;
        pnl?: IStrategyPnL;
        position?: "long" | "short";
        priceOpen?: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    action activateId? backtest cancelId? @@ -31,36 +31,36 @@ Contains all information about strategy management actions.

    totalEntries? totalPartials?

    Properties

    Action type

    -
    activateId?: string

    Activate ID for activate-scheduled action

    -
    backtest: boolean

    True if backtest mode, false if live mode

    -
    cancelId?: string

    Cancel ID for cancel-scheduled action

    -
    closeId?: string

    Close ID for close-pending action

    -
    cost?: number

    Cost of this entry in USD (average-buy action only)

    -
    createdAt: string

    ISO timestamp string when action was created

    -
    currentPrice?: number

    Current market price when action was executed

    -
    effectivePriceOpen?: number

    Averaged entry price after DCA addition (average-buy action only)

    -
    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name (empty for live)

    -
    note?: string

    Optional note from commit payload

    -
    originalPriceOpen?: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss?: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit?: number

    Original take profit price before any trailing adjustments

    -
    pendingAt?: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    percentShift?: number

    Percent shift for trailing stop/take

    -
    percentToClose?: number

    Percent to close for partial profit/loss

    -

    PNL at the moment of this action

    -
    position?: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen?: number

    Entry price for the position

    -
    priceStopLoss?: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit?: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt?: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Signal ID

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Event timestamp in milliseconds

    -
    totalEntries?: number

    Total number of DCA entries after this addition (average-buy action only)

    -
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    -
    +
    activateId?: string

    Activate ID for activate-scheduled action

    +
    backtest: boolean

    True if backtest mode, false if live mode

    +
    cancelId?: string

    Cancel ID for cancel-scheduled action

    +
    closeId?: string

    Close ID for close-pending action

    +
    cost?: number

    Cost of this entry in USD (average-buy action only)

    +
    createdAt: string

    ISO timestamp string when action was created

    +
    currentPrice?: number

    Current market price when action was executed

    +
    effectivePriceOpen?: number

    Averaged entry price after DCA addition (average-buy action only)

    +
    exchangeName: string

    Exchange name

    +
    frameName: string

    Frame name (empty for live)

    +
    note?: string

    Optional note from commit payload

    +
    originalPriceOpen?: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss?: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit?: number

    Original take profit price before any trailing adjustments

    +
    pendingAt?: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    percentShift?: number

    Percent shift for trailing stop/take

    +
    percentToClose?: number

    Percent to close for partial profit/loss

    +

    PNL at the moment of this action

    +
    position?: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen?: number

    Entry price for the position

    +
    priceStopLoss?: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit?: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt?: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Signal ID

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Event timestamp in milliseconds

    +
    totalEntries?: number

    Total number of DCA entries after this addition (average-buy action only)

    +
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    +

    Interface SyncEvent

    Unified sync event data for markdown report generation. Contains all information about signal lifecycle sync events.

    -
    interface SyncEvent {
        action: SyncActionType;
        backtest: boolean;
        closeReason?: StrategyCloseReason;
        createdAt: string;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Properties

    interface SyncEvent {
        action: SyncActionType;
        backtest: boolean;
        closeReason?: StrategyCloseReason;
        createdAt: string;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Properties

    action backtest closeReason? createdAt @@ -26,31 +26,31 @@ Contains all information about signal lifecycle sync events.

    totalEntries totalPartials

    Properties

    action: SyncActionType

    Sync action type

    -
    backtest: boolean

    Whether this event is from backtest mode

    -
    closeReason?: StrategyCloseReason

    Why the signal was closed (signal-close only)

    -
    createdAt: string

    ISO timestamp string when event was created

    -
    currentPrice: number

    Market price at the moment of this event

    -
    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name (empty for live)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    originalPriceOpen: number

    Original entry price before any DCA averaging

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price at which the limit order was filled

    -
    priceStopLoss: number

    Effective stop loss price

    -
    priceTakeProfit: number

    Effective take profit price

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -
    signalId: string

    Signal unique identifier

    -
    strategyName: string

    Strategy name

    -
    symbol: string

    Trading pair symbol

    -
    timestamp: number

    Event timestamp in milliseconds

    -
    totalEntries: number

    Total number of DCA entries

    -
    totalPartials: number

    Total number of partial closes executed

    -
    +
    backtest: boolean

    Whether this event is from backtest mode

    +
    closeReason?: StrategyCloseReason

    Why the signal was closed (signal-close only)

    +
    createdAt: string

    ISO timestamp string when event was created

    +
    currentPrice: number

    Market price at the moment of this event

    +
    exchangeName: string

    Exchange name

    +
    frameName: string

    Frame name (empty for live)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    originalPriceOpen: number

    Original entry price before any DCA averaging

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price at which the limit order was filled

    +
    priceStopLoss: number

    Effective stop loss price

    +
    priceTakeProfit: number

    Effective take profit price

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +
    signalId: string

    Signal unique identifier

    +
    strategyName: string

    Strategy name

    +
    symbol: string

    Trading pair symbol

    +
    timestamp: number

    Event timestamp in milliseconds

    +
    totalEntries: number

    Total number of DCA entries

    +
    totalPartials: number

    Total number of partial closes executed

    +

    Interface TickEvent

    Unified tick event data for report generation. Contains all information about a tick event regardless of action type.

    -
    interface TickEvent {
        action:
            | "waiting"
            | "active"
            | "closed"
            | "idle"
            | "opened"
            | "scheduled"
            | "cancelled";
        cancelReason?: string;
        closeReason?: string;
        currentPrice: number;
        duration?: number;
        fallPnl?: number;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        peakPnl?: number;
        pendingAt?: number;
        percentSl?: number;
        percentTp?: number;
        pnl?: number;
        pnlCost?: number;
        pnlEntries?: number;
        position?: string;
        priceOpen?: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId?: string;
        symbol?: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    interface TickEvent {
        action:
            | "waiting"
            | "active"
            | "closed"
            | "idle"
            | "opened"
            | "scheduled"
            | "cancelled";
        cancelReason?: string;
        closeReason?: string;
        currentPrice: number;
        duration?: number;
        fallPnl?: number;
        note?: string;
        originalPriceOpen?: number;
        originalPriceStopLoss?: number;
        originalPriceTakeProfit?: number;
        partialExecuted?: number;
        peakPnl?: number;
        pendingAt?: number;
        percentSl?: number;
        percentTp?: number;
        pnl?: number;
        pnlCost?: number;
        pnlEntries?: number;
        position?: string;
        priceOpen?: number;
        priceStopLoss?: number;
        priceTakeProfit?: number;
        scheduledAt?: number;
        signalId?: string;
        symbol?: string;
        timestamp: number;
        totalEntries?: number;
        totalPartials?: number;
    }

    Properties

    action cancelReason? closeReason? currentPrice @@ -29,34 +29,34 @@ Contains all information about a tick event regardless of action type.

    totalEntries? totalPartials?

    Properties

    action:
        | "waiting"
        | "active"
        | "closed"
        | "idle"
        | "opened"
        | "scheduled"
        | "cancelled"

    Event action type

    -
    cancelReason?: string

    Cancel reason (only for cancelled)

    -
    closeReason?: string

    Close reason (only for closed)

    -
    currentPrice: number

    Current price

    -
    duration?: number

    Duration in minutes (only for closed)

    -
    fallPnl?: number

    Fall PNL percentage at worst price during position (_fall.pnlPercentage, only for closed)

    -
    note?: string

    Signal note (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    originalPriceOpen?: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss?: number

    Original stop loss price before modifications (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    originalPriceTakeProfit?: number

    Original take profit price before modifications (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    partialExecuted?: number

    Total executed percentage from partial closes (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    peakPnl?: number

    Peak PNL percentage at best price during position (_peak.pnlPercentage, only for closed)

    -
    pendingAt?: number

    Timestamp when position became active (only for opened/active/closed)

    -
    percentSl?: number

    Percentage progress towards stop loss (only for active/waiting)

    -
    percentTp?: number

    Percentage progress towards take profit (only for active/waiting)

    -
    pnl?: number

    PNL percentage (for active/waiting: unrealized, for closed: realized)

    -
    pnlCost?: number

    Absolute profit/loss in USD (for active/waiting: unrealized, for closed: realized)

    -
    pnlEntries?: number

    Total invested capital in USD

    -
    position?: string

    Position type (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    priceOpen?: number

    Open price (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    priceStopLoss?: number

    Stop loss price (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    priceTakeProfit?: number

    Take profit price (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    scheduledAt?: number

    Timestamp when signal was created/scheduled (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    signalId?: string

    Signal ID (only for scheduled/waiting/opened/active/closed/cancelled)

    -
    symbol?: string

    Trading pair symbol (only for non-idle events)

    -
    timestamp: number

    Event timestamp in milliseconds (scheduledAt for scheduled events, pendingAt for opened/closed events)

    -
    totalEntries?: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    -
    +
    cancelReason?: string

    Cancel reason (only for cancelled)

    +
    closeReason?: string

    Close reason (only for closed)

    +
    currentPrice: number

    Current price

    +
    duration?: number

    Duration in minutes (only for closed)

    +
    fallPnl?: number

    Fall PNL percentage at worst price during position (_fall.pnlPercentage, only for closed)

    +
    note?: string

    Signal note (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    originalPriceOpen?: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss?: number

    Original stop loss price before modifications (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    originalPriceTakeProfit?: number

    Original take profit price before modifications (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    partialExecuted?: number

    Total executed percentage from partial closes (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    peakPnl?: number

    Peak PNL percentage at best price during position (_peak.pnlPercentage, only for closed)

    +
    pendingAt?: number

    Timestamp when position became active (only for opened/active/closed)

    +
    percentSl?: number

    Percentage progress towards stop loss (only for active/waiting)

    +
    percentTp?: number

    Percentage progress towards take profit (only for active/waiting)

    +
    pnl?: number

    PNL percentage (for active/waiting: unrealized, for closed: realized)

    +
    pnlCost?: number

    Absolute profit/loss in USD (for active/waiting: unrealized, for closed: realized)

    +
    pnlEntries?: number

    Total invested capital in USD

    +
    position?: string

    Position type (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    priceOpen?: number

    Open price (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    priceStopLoss?: number

    Stop loss price (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    priceTakeProfit?: number

    Take profit price (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    scheduledAt?: number

    Timestamp when signal was created/scheduled (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    signalId?: string

    Signal ID (only for scheduled/waiting/opened/active/closed/cancelled)

    +
    symbol?: string

    Trading pair symbol (only for non-idle events)

    +
    timestamp: number

    Event timestamp in milliseconds (scheduledAt for scheduled events, pendingAt for opened/closed events)

    +
    totalEntries?: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials?: number

    Total number of partial closes executed (_partial.length)

    +

    Interface TrailingStopCommit

    Trailing stop event.

    -
    interface TrailingStopCommit {
        action: "trailing-stop";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • TrailingStopCommit

    Properties

    interface TrailingStopCommit {
        action: "trailing-stop";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • TrailingStopCommit

    Properties

    action: "trailing-stop"

    Discriminator for trailing-stop action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price at time of trailing adjustment

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    -
    percentShift: number

    Percentage shift for stop loss adjustment

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (updated by this trailing action)

    -
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price at time of trailing adjustment

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    +
    percentShift: number

    Percentage shift for stop loss adjustment

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (updated by this trailing action)

    +
    priceTakeProfit: number

    Effective take profit price (may differ from original after trailing)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface TrailingStopCommitNotification

    Trailing stop commit notification. Emitted when trailing stop action is executed.

    -
    interface TrailingStopCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "trailing_stop.commit";
    }

    Properties

    interface TrailingStopCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "trailing_stop.commit";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when trailing stop action is executed.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when trailing stop was executed

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    percentShift: number

    Percentage shift of original SL distance (-100 to 100)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price after trailing adjustment

    -
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when trailing stop was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "trailing_stop.commit"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when trailing stop was executed

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    percentShift: number

    Percentage shift of original SL distance (-100 to 100)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price after trailing adjustment

    +
    priceTakeProfit: number

    Effective take profit price (with trailing if set)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when trailing stop was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "trailing_stop.commit"

    Discriminator for type-safe union

    +

    Interface TrailingTakeCommit

    Trailing take event.

    -
    interface TrailingTakeCommit {
        action: "trailing-take";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • TrailingTakeCommit

    Properties

    interface TrailingTakeCommit {
        action: "trailing-take";
        backtest: boolean;
        currentPrice: number;
        exchangeName: string;
        frameName: string;
        maxDrawdown: IStrategyPnL;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signal: IPublicSignalRow;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
    }

    Hierarchy

    • SignalCommitBase
      • TrailingTakeCommit

    Properties

    action: "trailing-take"

    Discriminator for trailing-take action

    -
    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    -
    currentPrice: number

    Current market price at time of trailing adjustment

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    -
    percentShift: number

    Percentage shift for take profit adjustment

    -

    Total PNL of the closed position (including all entries and partials)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    -
    priceTakeProfit: number

    Effective take profit price (updated by this trailing action)

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds

    -

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    -
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). +

    backtest: boolean

    Whether this event is from backtest mode (true) or live mode (false)

    +
    currentPrice: number

    Current market price at time of trailing adjustment

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    frameName: string

    Timeframe name (used in backtest mode, empty string in live mode)

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging).

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    pendingAt: number

    Position activation timestamp in milliseconds (when price reached priceOpen)

    +
    percentShift: number

    Percentage shift for take profit adjustment

    +

    Total PNL of the closed position (including all entries and partials)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (may differ from original after trailing)

    +
    priceTakeProfit: number

    Effective take profit price (updated by this trailing action)

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds

    +

    Signal data at the moment of this event (snapshot of IPublicSignalRow)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Timestamp from execution context (tick's when or backtest candle timestamp)

    +
    totalEntries: number

    Total number of DCA entries at the time of this event (_entry.length). 1 = no averaging done (only initial entry). 2+ = averaged positions.

    -
    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). +

    totalPartials: number

    Total number of partial closes executed at the time of this event (_partial.length). 0 = no partial closes done. 1+ = partial closes executed.

    -
    +

    Interface TrailingTakeCommitNotification

    Trailing take commit notification. Emitted when trailing take action is executed.

    -
    interface TrailingTakeCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "trailing_take.commit";
    }

    Properties

    interface TrailingTakeCommitNotification {
        backtest: boolean;
        createdAt: number;
        currentPrice: number;
        exchangeName: string;
        id: string;
        maxDrawdown: IStrategyPnL;
        maxDrawdownCost: number;
        maxDrawdownEntries: number;
        maxDrawdownPercentage: number;
        maxDrawdownPriceClose: number;
        maxDrawdownPriceOpen: number;
        note?: string;
        originalPriceOpen: number;
        originalPriceStopLoss: number;
        originalPriceTakeProfit: number;
        peakProfit: IStrategyPnL;
        peakProfitCost: number;
        peakProfitEntries: number;
        peakProfitPercentage: number;
        peakProfitPriceClose: number;
        peakProfitPriceOpen: number;
        pendingAt: number;
        percentShift: number;
        pnl: IStrategyPnL;
        pnlCost: number;
        pnlEntries: number;
        pnlPercentage: number;
        pnlPriceClose: number;
        pnlPriceOpen: number;
        position: "long" | "short";
        priceOpen: number;
        priceStopLoss: number;
        priceTakeProfit: number;
        scheduledAt: number;
        signalId: string;
        strategyName: string;
        symbol: string;
        timestamp: number;
        totalEntries: number;
        totalPartials: number;
        type: "trailing_take.commit";
    }

    Properties

    backtest createdAt currentPrice exchangeName @@ -42,47 +42,47 @@ Emitted when trailing take action is executed.

    totalPartials type

    Properties

    backtest: boolean

    Whether this notification is from backtest mode (true) or live mode (false)

    -
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    -
    currentPrice: number

    Current market price when trailing take was executed

    -
    exchangeName: string

    Exchange name where signal was executed

    -
    id: string

    Unique notification identifier

    -
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    -
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    -
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    -
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    -
    note?: string

    Optional human-readable description of signal reason

    -
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    -
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    -
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    -
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    -
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    -
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    -
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    -
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    -
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    -
    percentShift: number

    Percentage shift of original TP distance (-100 to 100)

    -

    Total PNL of the closed position (including all entries and partials)

    -
    pnlCost: number

    Absolute profit/loss in USD

    -
    pnlEntries: number

    Total invested capital in USD

    -
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    -
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    -
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    -
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    -
    priceOpen: number

    Entry price for the position

    -
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    -
    priceTakeProfit: number

    Effective take profit price after trailing adjustment

    -
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    -
    signalId: string

    Unique signal identifier (UUID v4)

    -
    strategyName: string

    Strategy name that generated this signal

    -
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    -
    timestamp: number

    Unix timestamp in milliseconds when trailing take was committed

    -
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    -
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    -
    type: "trailing_take.commit"

    Discriminator for type-safe union

    -
    +
    createdAt: number

    Unix timestamp in milliseconds when the notification was created

    +
    currentPrice: number

    Current market price when trailing take was executed

    +
    exchangeName: string

    Exchange name where signal was executed

    +
    id: string

    Unique notification identifier

    +
    maxDrawdown: IStrategyPnL

    Maximum drawdown experienced during the life of this position up to the moment this public signal was created

    +
    maxDrawdownCost: number

    Absolute profit/loss in USD at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownEntries: number

    Number of entries executed at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPercentage: number

    Profit/loss as percentage at the moment the position reached its maximum drawdown during the life of this position

    +
    maxDrawdownPriceClose: number

    Exit price for PNL calculation at the moment of max drawdown

    +
    maxDrawdownPriceOpen: number

    Maximum drawdown price reached in loss direction during the life of this position

    +
    note?: string

    Optional human-readable description of signal reason

    +
    originalPriceOpen: number

    Original entry price at signal creation (unchanged by DCA averaging)

    +
    originalPriceStopLoss: number

    Original stop loss price before any trailing adjustments

    +
    originalPriceTakeProfit: number

    Original take profit price before any trailing adjustments

    +
    peakProfit: IStrategyPnL

    Peak profit achieved during the life of this position up to the moment this public signal was created

    +
    peakProfitCost: number

    Absolute profit/loss in USD at the moment the position reached its peak profit during the life of this position

    +
    peakProfitEntries: number

    Number of entries executed at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPercentage: number

    Profit/loss as percentage at the moment the position reached its peak profit during the life of this position

    +
    peakProfitPriceClose: number

    Exit price for PNL calculation at the moment of peak profit

    +
    peakProfitPriceOpen: number

    Peak price reached in profit direction during the life of this position

    +
    pendingAt: number

    Pending timestamp in milliseconds (when position became pending/active at priceOpen)

    +
    percentShift: number

    Percentage shift of original TP distance (-100 to 100)

    +

    Total PNL of the closed position (including all entries and partials)

    +
    pnlCost: number

    Absolute profit/loss in USD

    +
    pnlEntries: number

    Total invested capital in USD

    +
    pnlPercentage: number

    Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%)

    +
    pnlPriceClose: number

    Exit price from PNL calculation (adjusted with slippage and fees)

    +
    pnlPriceOpen: number

    Entry price from PNL calculation (effective price adjusted with slippage and fees)

    +
    position: "long" | "short"

    Trade direction: "long" (buy) or "short" (sell)

    +
    priceOpen: number

    Entry price for the position

    +
    priceStopLoss: number

    Effective stop loss price (with trailing if set)

    +
    priceTakeProfit: number

    Effective take profit price after trailing adjustment

    +
    scheduledAt: number

    Signal creation timestamp in milliseconds (when signal was first created/scheduled)

    +
    signalId: string

    Unique signal identifier (UUID v4)

    +
    strategyName: string

    Strategy name that generated this signal

    +
    symbol: string

    Trading pair symbol (e.g., "BTCUSDT")

    +
    timestamp: number

    Unix timestamp in milliseconds when trailing take was committed

    +
    totalEntries: number

    Total number of DCA entries (_entry.length). 1 = no averaging.

    +
    totalPartials: number

    Total number of partial closes executed (_partial.length). 0 = no partial closes done.

    +
    type: "trailing_take.commit"

    Discriminator for type-safe union

    +

    Interface ValidationErrorNotification

    Validation error notification. Emitted when risk validation functions throw errors.

    -
    interface ValidationErrorNotification {
        backtest: boolean;
        error: object;
        id: string;
        message: string;
        type: "error.validation";
    }

    Properties

    interface ValidationErrorNotification {
        backtest: boolean;
        error: object;
        id: string;
        message: string;
        type: "error.validation";
    }

    Properties

    backtest: boolean

    Always false for error notifications (errors are from live context)

    -
    error: object

    Serialized error object with stack trace and metadata

    -
    id: string

    Unique notification identifier

    -
    message: string

    Human-readable validation error message

    -
    type: "error.validation"

    Discriminator for type-safe union

    -
    +
    error: object

    Serialized error object with stack trace and metadata

    +
    id: string

    Unique notification identifier

    +
    message: string

    Human-readable validation error message

    +
    type: "error.validation"

    Discriminator for type-safe union

    +

    Interface WalkerContract

    Contract for walker progress events during strategy comparison. Emitted each time a strategy completes testing with its current ranking.

    -
    interface WalkerContract {
        bestMetric: number;
        bestStrategy: string;
        exchangeName: string;
        frameName: string;
        metric: WalkerMetric;
        metricValue: number;
        stats: BacktestStatisticsModel;
        strategiesTested: number;
        strategyName: string;
        symbol: string;
        totalStrategies: number;
        walkerName: string;
    }

    Properties

    interface WalkerContract {
        bestMetric: number;
        bestStrategy: string;
        exchangeName: string;
        frameName: string;
        metric: WalkerMetric;
        metricValue: number;
        stats: BacktestStatisticsModel;
        strategiesTested: number;
        strategyName: string;
        symbol: string;
        totalStrategies: number;
        walkerName: string;
    }

    Properties

    bestMetric bestStrategy exchangeName frameName @@ -13,18 +13,18 @@ Emitted each time a strategy completes testing with its current ranking.

    totalStrategies walkerName

    Properties

    bestMetric: number

    Current best metric value across all tested strategies so far

    -
    bestStrategy: string

    Current best strategy name

    -
    exchangeName: string

    Exchange name

    -
    frameName: string

    Frame name

    -
    metric: WalkerMetric

    Metric being optimized

    -
    metricValue: number

    Metric value for this strategy (null if invalid)

    -

    Backtest statistics for this strategy

    -
    strategiesTested: number

    Number of strategies tested so far

    -
    strategyName: string

    Strategy that just completed

    -
    symbol: string

    Symbol being tested

    -
    totalStrategies: number

    Total number of strategies to test

    -
    walkerName: string

    Walker name

    -
    +
    bestStrategy: string

    Current best strategy name

    +
    exchangeName: string

    Exchange name

    +
    frameName: string

    Frame name

    +
    metric: WalkerMetric

    Metric being optimized

    +
    metricValue: number

    Metric value for this strategy (null if invalid)

    +

    Backtest statistics for this strategy

    +
    strategiesTested: number

    Number of strategies tested so far

    +
    strategyName: string

    Strategy that just completed

    +
    symbol: string

    Symbol being tested

    +
    totalStrategies: number

    Total number of strategies to test

    +
    walkerName: string

    Walker name

    +

    Interface WalkerSignalData

    Signal data for PNL table. Represents a single closed signal with essential trading information.

    -
    interface WalkerSignalData {
        closeReason: string;
        closeTime: number;
        openTime: number;
        pnl: number;
        position: string;
        signalId: string;
        strategyName: string;
        symbol: string;
    }

    Properties

    interface WalkerSignalData {
        closeReason: string;
        closeTime: number;
        openTime: number;
        pnl: number;
        position: string;
        signalId: string;
        strategyName: string;
        symbol: string;
    }

    Properties

    closeReason closeTime openTime pnl @@ -9,14 +9,14 @@ Represents a single closed signal with essential trading information.

    strategyName symbol

    Properties

    closeReason: string

    Reason why signal was closed

    -
    closeTime: number

    Timestamp when signal closed

    -
    openTime: number

    Timestamp when signal opened

    -
    pnl: number

    PNL as percentage

    -
    position: string

    Position type (long/short)

    -
    signalId: string

    Unique signal identifier

    -
    strategyName: string

    Strategy that generated this signal

    -
    symbol: string

    Trading pair symbol

    -
    +
    closeTime: number

    Timestamp when signal closed

    +
    openTime: number

    Timestamp when signal opened

    +
    pnl: number

    PNL as percentage

    +
    position: string

    Position type (long/short)

    +
    signalId: string

    Unique signal identifier

    +
    strategyName: string

    Strategy that generated this signal

    +
    symbol: string

    Trading pair symbol

    +

    Interface WalkerStatisticsModel

    Alias for walker statistics result interface. Used for clarity in markdown service context.

    Extends IWalkerResults with additional strategy comparison data.

    -
    interface WalkerStatisticsModel {
        bestMetric: number;
        bestStats: BacktestStatisticsModel;
        bestStrategy: string;
        exchangeName: string;
        frameName: string;
        metric: WalkerMetric;
        strategyResults: IStrategyResult[];
        symbol: string;
        totalStrategies: number;
        walkerName: string;
    }

    Hierarchy (View Summary)

    Properties

    interface WalkerStatisticsModel {
        bestMetric: number;
        bestStats: BacktestStatisticsModel;
        bestStrategy: string;
        exchangeName: string;
        frameName: string;
        metric: WalkerMetric;
        strategyResults: IStrategyResult[];
        symbol: string;
        totalStrategies: number;
        walkerName: string;
    }

    Hierarchy (View Summary)

    Properties

    bestMetric bestStats bestStrategy exchangeName @@ -12,16 +12,16 @@ Used for clarity in markdown service context.

    totalStrategies walkerName

    Properties

    bestMetric: number

    bestMetric - Best metric value achieved

    -

    bestStats - Best strategy statistics

    -
    bestStrategy: string

    bestStrategy - Best performing strategy name

    -
    exchangeName: string

    exchangeName - Exchange used

    -
    frameName: string

    frameName - Frame used

    -
    metric: WalkerMetric

    metric - Metric used for optimization

    -
    strategyResults: IStrategyResult[]

    Array of all strategy results for comparison and analysis

    -
    symbol: string

    symbol - Symbol tested

    -
    totalStrategies: number

    totalStrategies - Total number of strategies tested

    -
    walkerName: string

    walkerName - Walker name

    -
    +

    bestStats - Best strategy statistics

    +
    bestStrategy: string

    bestStrategy - Best performing strategy name

    +
    exchangeName: string

    exchangeName - Exchange used

    +
    frameName: string

    frameName - Frame used

    +
    metric: WalkerMetric

    metric - Metric used for optimization

    +
    strategyResults: IStrategyResult[]

    Array of all strategy results for comparison and analysis

    +
    symbol: string

    symbol - Symbol tested

    +
    totalStrategies: number

    totalStrategies - Total number of strategies tested

    +
    walkerName: string

    walkerName - Walker name

    +

    backtest-kit

    Modules

    types

    article

    article/01_look_ahead_bias
    article/02_second_order_chaos
    article/03_claude_trader
    article/04_option_hedging
    article/05_ai_strategy_workflow
    article/06_ai_strategy_blueprint
    article/07_ai_news_trading_signals
    article/08_ai_liquidity_harvesting
    article/09_pinescript_local_markets
    article/10_dca_averaging_strategy

    begin

    begin/01_project_overview
    begin/02_getting_started_configuration
    begin/03_system_architecture_overview
    begin/04_llm_forecast_engine_logic
    begin/05_forecast_pipeline_outline
    begin/06_advisors_news_market_data
    begin/07_news_fetching_caching_fetchnews
    begin/08_ollama_completions
    begin/09_trading_strategy_feb_2026_strategy
    begin/10_signal_generation_sentiment_mapping
    begin/11_position_lifecycle_exit_logic
    begin/12_backtest_module_frame_configuration
    begin/13_february_2026_case_study_performance
    begin/14_backtest_kit_framework
    begin/15_backtesting_execution_reporting
    begin/16_signal_state_machine
    begin/17_live_trading_mode
    begin/18_risk_management
    begin/19_ai_strategy_optimization_walker
    begin/20_exchange_integration_modules
    begin/21_ccxt_exchange_adapter
    begin/22_symbol_configuration
    begin/23_glossary

    cli

    cli/readme

    concept

    concept/01_monorepo_parallel_execution

    demo/backtest

    demo/backtest/readme

    demo/exchange

    demo/exchange/readme

    demo/live

    demo/live/readme

    demo/optimization

    demo/optimization/readme

    demo/pinets

    demo/pinets/readme

    design

    design/01_overview
    design/02_key_features
    design/03_installation_and_setup
    design/04_quick_start_guide
    design/05_core_concepts
    design/06_execution_modes
    design/07_signal_lifecycle_overview
    design/08_component_registration
    design/09_temporal_isolation_and_look-ahead_prevention
    design/10_architecture
    design/11_layer_responsibilities
    design/12_dependency_injection_system
    design/13_context_propagation
    design/14_event_system
    design/15_public_api_reference
    design/16_configuration_functions
    design/17_component_registration_functions
    design/18_backtest_api
    design/19_live_trading_api
    design/20_walker_api
    design/21_persistence_utilities
    design/22_exchange_functions
    design/23_event_listeners
    design/24_component_schemas
    design/25_strategy_schemas
    design/26_exchange_schemas
    design/27_frame_schemas
    design/28_risk_schemas
    design/29_sizing_schemas
    design/30_walker_schemas
    design/31_optimizer_schemas
    design/32_client_implementations
    design/33_clientstrategy
    design/34_clientexchange
    design/35_clientframe
    design/36_clientrisk
    design/37_clientsizing
    design/38_clientpartial
    design/39_clientoptimizer
    design/40_service_layer
    design/41_service_architecture_overview
    design/42_connection_services
    design/43_schema_services
    design/44_validation_services
    design/45_global_services
    design/46_logic_services
    design/47_markdown_services
    design/48_signal_lifecycle
    design/49_signal_states
    design/50_signal_generation_and_validation
    design/51_scheduled_signals
    design/52_signal_persistence
    design/53_pnl_calculation
    design/54_backtesting
    design/55_backtest_execution_flow
    design/56_timeframe_generation
    design/57_fast-forward_simulation
    design/58_live_trading
    design/59_live_execution_flow
    design/60_crash_recovery
    design/61_real-time_monitoring
    design/62_interval_throttling
    design/63_walker_mode
    design/64_walker_execution_flow
    design/65_strategy_comparison
    design/66_walker_reports
    design/67_risk_management
    design/68_risk_profiles
    design/69_risk_validation
    design/70_position_tracking
    design/71_reporting_and_analytics
    design/72_markdown_report_generation
    design/73_performance_metrics
    design/74_statistics_calculation
    design/75_partial_profit_loss_tracking
    design/76_heatmap_analytics
    design/77_configuration
    design/78_global_configuration
    design/79_validation_parameters
    design/80_timing_parameters
    design/81_cross-cutting_concerns
    design/82_logging_system
    design/83_error_handling
    design/84_persistence_layer
    design/85_advanced_topics
    design/86_custom_exchange_integration
    design/87_custom_persistence_backends
    design/88_custom_risk_validations
    design/89_multi-symbol_strategies
    design/90_ai-powered_strategy_optimization
    design/91_optimizer_architecture
    design/92_data_collection_pipeline
    design/93_llm_integration
    design/94_strategy_code_generation
    design/95_training_vs_testing_ranges

    docs

    docs
    docs/class/ActionBase
    docs/class/ActionConnectionService
    docs/class/ActionCoreService
    docs/class/ActionProxy
    docs/class/ActionSchemaService
    docs/class/ActionValidationService
    docs/class/BacktestCommandService
    docs/class/BacktestLogicPrivateService
    docs/class/BacktestLogicPublicService
    docs/class/BacktestMarkdownService
    docs/class/BacktestReportService
    docs/class/BacktestUtils
    docs/class/BreakevenConnectionService
    docs/class/BreakevenGlobalService
    docs/class/BreakevenMarkdownService
    docs/class/BreakevenReportService
    docs/class/BreakevenUtils
    docs/class/BrokerAdapter
    docs/class/BrokerBase
    docs/class/CacheUtils
    docs/class/ClientAction
    docs/class/ClientExchange
    docs/class/ClientFrame
    docs/class/ClientRisk
    docs/class/ClientSizing
    docs/class/ColumnValidationService
    docs/class/ConfigValidationService
    docs/class/ConstantUtils
    docs/class/DumpAdapter
    docs/class/ExchangeConnectionService
    docs/class/ExchangeCoreService
    docs/class/ExchangeSchemaService
    docs/class/ExchangeUtils
    docs/class/ExchangeValidationService
    docs/class/FrameConnectionService
    docs/class/FrameCoreService
    docs/class/FrameSchemaService
    docs/class/FrameValidationService
    docs/class/HeatMarkdownService
    docs/class/HeatReportService
    docs/class/HeatUtils
    docs/class/HighestProfitMarkdownService
    docs/class/HighestProfitReportService
    docs/class/HighestProfitUtils
    docs/class/IntervalUtils
    docs/class/LiveCommandService
    docs/class/LiveLogicPrivateService
    docs/class/LiveLogicPublicService
    docs/class/LiveMarkdownService
    docs/class/LiveReportService
    docs/class/LiveUtils
    docs/class/LogAdapter
    docs/class/LoggerService
    docs/class/LookupUtils
    docs/class/MarkdownAdapter
    docs/class/MarkdownFileBase
    docs/class/MarkdownFolderBase
    docs/class/MarkdownUtils
    docs/class/MarkdownWriterAdapter
    docs/class/MaxDrawdownMarkdownService
    docs/class/MaxDrawdownReportService
    docs/class/MaxDrawdownUtils
    docs/class/MemoryAdapter
    docs/class/MemoryBacktestAdapter
    docs/class/MemoryLiveAdapter
    docs/class/NotificationAdapter
    docs/class/NotificationBacktestAdapter
    docs/class/NotificationHelperService
    docs/class/NotificationLiveAdapter
    docs/class/PartialConnectionService
    docs/class/PartialGlobalService
    docs/class/PartialMarkdownService
    docs/class/PartialReportService
    docs/class/PartialUtils
    docs/class/Performance
    docs/class/PerformanceMarkdownService
    docs/class/PerformanceReportService
    docs/class/PersistBase
    docs/class/PersistBreakevenInstance
    docs/class/PersistBreakevenUtils
    docs/class/PersistCandleInstance
    docs/class/PersistCandleUtils
    docs/class/PersistIntervalInstance
    docs/class/PersistIntervalUtils
    docs/class/PersistLogInstance
    docs/class/PersistLogUtils
    docs/class/PersistMeasureInstance
    docs/class/PersistMeasureUtils
    docs/class/PersistMemoryInstance
    docs/class/PersistMemoryUtils
    docs/class/PersistNotificationInstance
    docs/class/PersistNotificationUtils
    docs/class/PersistPartialInstance
    docs/class/PersistPartialUtils
    docs/class/PersistRecentInstance
    docs/class/PersistRecentUtils
    docs/class/PersistRiskInstance
    docs/class/PersistRiskUtils
    docs/class/PersistScheduleInstance
    docs/class/PersistScheduleUtils
    docs/class/PersistSessionInstance
    docs/class/PersistSessionUtils
    docs/class/PersistSignalInstance
    docs/class/PersistSignalUtils
    docs/class/PersistStateInstance
    docs/class/PersistStateUtils
    docs/class/PersistStorageInstance
    docs/class/PersistStorageUtils
    docs/class/Position
    docs/class/PositionSizeUtils
    docs/class/PriceMetaService
    docs/class/RecentAdapter
    docs/class/RecentBacktestAdapter
    docs/class/RecentLiveAdapter
    docs/class/ReflectUtils
    docs/class/ReportAdapter
    docs/class/ReportBase
    docs/class/ReportUtils
    docs/class/ReportWriterAdapter
    docs/class/RiskConnectionService
    docs/class/RiskGlobalService
    docs/class/RiskMarkdownService
    docs/class/RiskReportService
    docs/class/RiskSchemaService
    docs/class/RiskUtils
    docs/class/RiskValidationService
    docs/class/ScheduleMarkdownService
    docs/class/ScheduleReportService
    docs/class/ScheduleUtils
    docs/class/SessionAdapter
    docs/class/SessionBacktestAdapter
    docs/class/SessionLiveAdapter
    docs/class/SizingConnectionService
    docs/class/SizingGlobalService
    docs/class/SizingSchemaService
    docs/class/SizingValidationService
    docs/class/StateAdapter
    docs/class/StateBacktestAdapter
    docs/class/StateLiveAdapter
    docs/class/StorageAdapter
    docs/class/StorageBacktestAdapter
    docs/class/StorageLiveAdapter
    docs/class/StrategyConnectionService
    docs/class/StrategyCoreService
    docs/class/StrategyMarkdownService
    docs/class/StrategyReportService
    docs/class/StrategySchemaService
    docs/class/StrategyUtils
    docs/class/StrategyValidationService
    docs/class/SyncMarkdownService
    docs/class/SyncReportService
    docs/class/SyncUtils
    docs/class/SystemUtils
    docs/class/TimeMetaService
    docs/class/WalkerCommandService
    docs/class/WalkerLogicPrivateService
    docs/class/WalkerLogicPublicService
    docs/class/WalkerMarkdownService
    docs/class/WalkerReportService
    docs/class/WalkerSchemaService
    docs/class/WalkerUtils
    docs/class/WalkerValidationService
    docs/function/addActionSchema
    docs/function/addExchangeSchema
    docs/function/addFrameSchema
    docs/function/addRiskSchema
    docs/function/addSizingSchema
    docs/function/addStrategySchema
    docs/function/addWalkerSchema
    docs/function/cacheCandles
    docs/function/checkCandles
    docs/function/commitActivateScheduled
    docs/function/commitAverageBuy
    docs/function/commitBreakeven
    docs/function/commitCancelScheduled
    docs/function/commitClosePending
    docs/function/commitPartialLoss
    docs/function/commitPartialLossCost
    docs/function/commitPartialProfit
    docs/function/commitPartialProfitCost
    docs/function/commitSignalNotify
    docs/function/commitTrailingStop
    docs/function/commitTrailingStopCost
    docs/function/commitTrailingTake
    docs/function/commitTrailingTakeCost
    docs/function/createSignalState
    docs/function/dumpAgentAnswer
    docs/function/dumpError
    docs/function/dumpJson
    docs/function/dumpRecord
    docs/function/dumpTable
    docs/function/dumpText
    docs/function/formatPrice
    docs/function/formatQuantity
    docs/function/getActionSchema
    docs/function/getAggregatedTrades
    docs/function/getAveragePrice
    docs/function/getBacktestTimeframe
    docs/function/getBreakeven
    docs/function/getCandles
    docs/function/getClosePrice
    docs/function/getColumns
    docs/function/getConfig
    docs/function/getContext
    docs/function/getDate
    docs/function/getDefaultColumns
    docs/function/getDefaultConfig
    docs/function/getExchangeSchema
    docs/function/getFrameSchema
    docs/function/getLatestSignal
    docs/function/getMaxDrawdownDistancePnlCost
    docs/function/getMaxDrawdownDistancePnlPercentage
    docs/function/getMinutesSinceLatestSignalCreated
    docs/function/getMode
    docs/function/getNextCandles
    docs/function/getOrderBook
    docs/function/getPendingSignal
    docs/function/getPositionActiveMinutes
    docs/function/getPositionCountdownMinutes
    docs/function/getPositionDrawdownMinutes
    docs/function/getPositionEffectivePrice
    docs/function/getPositionEntries
    docs/function/getPositionEntryOverlap
    docs/function/getPositionEstimateMinutes
    docs/function/getPositionHighestMaxDrawdownPnlCost
    docs/function/getPositionHighestMaxDrawdownPnlPercentage
    docs/function/getPositionHighestPnlCost
    docs/function/getPositionHighestPnlPercentage
    docs/function/getPositionHighestProfitBreakeven
    docs/function/getPositionHighestProfitDistancePnlCost
    docs/function/getPositionHighestProfitDistancePnlPercentage
    docs/function/getPositionHighestProfitMinutes
    docs/function/getPositionHighestProfitPrice
    docs/function/getPositionHighestProfitTimestamp
    docs/function/getPositionInvestedCost
    docs/function/getPositionInvestedCount
    docs/function/getPositionLevels
    docs/function/getPositionMaxDrawdownMinutes
    docs/function/getPositionMaxDrawdownPnlCost
    docs/function/getPositionMaxDrawdownPnlPercentage
    docs/function/getPositionMaxDrawdownPrice
    docs/function/getPositionMaxDrawdownTimestamp
    docs/function/getPositionPartialOverlap
    docs/function/getPositionPartials
    docs/function/getPositionPnlCost
    docs/function/getPositionPnlPercent
    docs/function/getPositionWaitingMinutes
    docs/function/getRawCandles
    docs/function/getRiskSchema
    docs/function/getScheduledSignal
    docs/function/getSessionData
    docs/function/getSignalState
    docs/function/getSizingSchema
    docs/function/getStrategySchema
    docs/function/getSymbol
    docs/function/getTimestamp
    docs/function/getTotalCostClosed
    docs/function/getTotalPercentClosed
    docs/function/getWalkerSchema
    docs/function/hasNoPendingSignal
    docs/function/hasNoScheduledSignal
    docs/function/hasTradeContext
    docs/function/listenActivePing
    docs/function/listenActivePingOnce
    docs/function/listenBacktestProgress
    docs/function/listenBreakevenAvailable
    docs/function/listenBreakevenAvailableOnce
    docs/function/listenDoneBacktest
    docs/function/listenDoneBacktestOnce
    docs/function/listenDoneLive
    docs/function/listenDoneLiveOnce
    docs/function/listenDoneWalker
    docs/function/listenDoneWalkerOnce
    docs/function/listenError
    docs/function/listenExit
    docs/function/listenHighestProfit
    docs/function/listenHighestProfitOnce
    docs/function/listenIdlePing
    docs/function/listenIdlePingOnce
    docs/function/listenMaxDrawdown
    docs/function/listenMaxDrawdownOnce
    docs/function/listenPartialLossAvailable
    docs/function/listenPartialLossAvailableOnce
    docs/function/listenPartialProfitAvailable
    docs/function/listenPartialProfitAvailableOnce
    docs/function/listenPerformance
    docs/function/listenRisk
    docs/function/listenRiskOnce
    docs/function/listenSchedulePing
    docs/function/listenSchedulePingOnce
    docs/function/listenSignal
    docs/function/listenSignalBacktest
    docs/function/listenSignalBacktestOnce
    docs/function/listenSignalLive
    docs/function/listenSignalLiveOnce
    docs/function/listenSignalNotify
    docs/function/listenSignalNotifyOnce
    docs/function/listenSignalOnce
    docs/function/listenStrategyCommit
    docs/function/listenStrategyCommitOnce
    docs/function/listenSync
    docs/function/listenSyncOnce
    docs/function/listenValidation
    docs/function/listenWalker
    docs/function/listenWalkerComplete
    docs/function/listenWalkerOnce
    docs/function/listenWalkerProgress
    docs/function/listExchangeSchema
    docs/function/listFrameSchema
    docs/function/listMemory
    docs/function/listRiskSchema
    docs/function/listSizingSchema
    docs/function/listStrategySchema
    docs/function/listWalkerSchema
    docs/function/overrideActionSchema
    docs/function/overrideExchangeSchema
    docs/function/overrideFrameSchema
    docs/function/overrideRiskSchema
    docs/function/overrideSizingSchema
    docs/function/overrideStrategySchema
    docs/function/overrideWalkerSchema
    docs/function/readMemory
    docs/function/removeMemory
    docs/function/runInMockContext
    docs/function/searchMemory
    docs/function/setColumns
    docs/function/setConfig
    docs/function/setLogger
    docs/function/setSessionData
    docs/function/setSignalState
    docs/function/shutdown
    docs/function/stopStrategy
    docs/function/validate
    docs/function/waitForReady
    docs/function/warmCandles
    docs/function/writeMemory
    docs/interface/ActivateScheduledCommit
    docs/interface/ActivateScheduledCommitNotification
    docs/interface/ActivePingContract
    docs/interface/AverageBuyCommit
    docs/interface/AverageBuyCommitNotification
    docs/interface/BacktestStatisticsModel
    docs/interface/BreakevenAvailableNotification
    docs/interface/BreakevenCommit
    docs/interface/BreakevenCommitNotification
    docs/interface/BreakevenContract
    docs/interface/BreakevenEvent
    docs/interface/BreakevenStatisticsModel
    docs/interface/CancelScheduledCommit
    docs/interface/CancelScheduledCommitNotification
    docs/interface/ClosePendingCommit
    docs/interface/ClosePendingCommitNotification
    docs/interface/ColumnModel
    docs/interface/CriticalErrorNotification
    docs/interface/DoneContract
    docs/interface/HeatmapStatisticsModel
    docs/interface/HighestProfitContract
    docs/interface/HighestProfitEvent
    docs/interface/HighestProfitStatisticsModel
    docs/interface/IAction
    docs/interface/IActionCallbacks
    docs/interface/IActionParams
    docs/interface/IActionSchema
    docs/interface/IActionStrategy
    docs/interface/IActivateScheduledCommitRow
    docs/interface/IActivityEntry
    docs/interface/IAggregatedTradeData
    docs/interface/IAverageBuyCommitRow
    docs/interface/IBidData
    docs/interface/IBreakeven
    docs/interface/IBreakevenCommitRow
    docs/interface/IBreakevenData
    docs/interface/IBroker
    docs/interface/ICacheCandlesParams
    docs/interface/ICandleData
    docs/interface/ICheckCandlesParams
    docs/interface/ICommitRowBase
    docs/interface/IdlePingContract
    docs/interface/IDumpContext
    docs/interface/IDumpInstance
    docs/interface/IEntity
    docs/interface/IExchange
    docs/interface/IExchangeCallbacks
    docs/interface/IExchangeParams
    docs/interface/IExchangeSchema
    docs/interface/IExecutionContext
    docs/interface/IFrame
    docs/interface/IFrameCallbacks
    docs/interface/IFrameParams
    docs/interface/IFrameSchema
    docs/interface/IHeatmapRow
    docs/interface/ILog
    docs/interface/ILogEntry
    docs/interface/ILogger
    docs/interface/IMarkdownDumpOptions
    docs/interface/IMarkdownTarget
    docs/interface/IMemoryInstance
    docs/interface/IMethodContext
    docs/interface/InfoErrorNotification
    docs/interface/INotificationTarget
    docs/interface/INotificationUtils
    docs/interface/IOrderBookData
    docs/interface/IParseArgsParams
    docs/interface/IParseArgsResult
    docs/interface/IPartial
    docs/interface/IPartialData
    docs/interface/IPartialLossCommitRow
    docs/interface/IPartialProfitCommitRow
    docs/interface/IPersistBase
    docs/interface/IPersistBreakevenInstance
    docs/interface/IPersistCandleInstance
    docs/interface/IPersistIntervalInstance
    docs/interface/IPersistLogInstance
    docs/interface/IPersistMeasureInstance
    docs/interface/IPersistMemoryInstance
    docs/interface/IPersistNotificationInstance
    docs/interface/IPersistPartialInstance
    docs/interface/IPersistRecentInstance
    docs/interface/IPersistRiskInstance
    docs/interface/IPersistScheduleInstance
    docs/interface/IPersistSessionInstance
    docs/interface/IPersistSignalInstance
    docs/interface/IPersistStateInstance
    docs/interface/IPersistStorageInstance
    docs/interface/IPositionOverlapLadder
    docs/interface/IPositionSizeATRParams
    docs/interface/IPositionSizeFixedPercentageParams
    docs/interface/IPositionSizeKellyParams
    docs/interface/IPublicCandleData
    docs/interface/IPublicSignalRow
    docs/interface/IRecentUtils
    docs/interface/IReportDumpOptions
    docs/interface/IReportTarget
    docs/interface/IRisk
    docs/interface/IRiskActivePosition
    docs/interface/IRiskCallbacks
    docs/interface/IRiskCheckArgs
    docs/interface/IRiskCheckOptions
    docs/interface/IRiskParams
    docs/interface/IRiskRejectionResult
    docs/interface/IRiskSchema
    docs/interface/IRiskSignalRow
    docs/interface/IRiskValidation
    docs/interface/IRiskValidationFn
    docs/interface/IRiskValidationPayload
    docs/interface/IRunContext
    docs/interface/IScheduledSignalCancelRow
    docs/interface/IScheduledSignalRow
    docs/interface/ISessionInstance
    docs/interface/ISignalDto
    docs/interface/ISignalIntervalDto
    docs/interface/ISignalRow
    docs/interface/ISizing
    docs/interface/ISizingCalculateParamsATR
    docs/interface/ISizingCalculateParamsBase
    docs/interface/ISizingCalculateParamsFixedPercentage
    docs/interface/ISizingCalculateParamsKelly
    docs/interface/ISizingCallbacks
    docs/interface/ISizingParamsATR
    docs/interface/ISizingParamsFixedPercentage
    docs/interface/ISizingParamsKelly
    docs/interface/ISizingSchemaATR
    docs/interface/ISizingSchemaBase
    docs/interface/ISizingSchemaFixedPercentage
    docs/interface/ISizingSchemaKelly
    docs/interface/IStateInstance
    docs/interface/IStateParams
    docs/interface/IStorageSignalRowBase
    docs/interface/IStorageSignalRowCancelled
    docs/interface/IStorageSignalRowClosed
    docs/interface/IStorageSignalRowOpened
    docs/interface/IStorageSignalRowScheduled
    docs/interface/IStorageUtils
    docs/interface/IStrategy
    docs/interface/IStrategyCallbacks
    docs/interface/IStrategyPnL
    docs/interface/IStrategyResult
    docs/interface/IStrategySchema
    docs/interface/IStrategyTickResultActive
    docs/interface/IStrategyTickResultCancelled
    docs/interface/IStrategyTickResultClosed
    docs/interface/IStrategyTickResultIdle
    docs/interface/IStrategyTickResultOpened
    docs/interface/IStrategyTickResultScheduled
    docs/interface/IStrategyTickResultWaiting
    docs/interface/ITrailingStopCommitRow
    docs/interface/ITrailingTakeCommitRow
    docs/interface/IWalkerCallbacks
    docs/interface/IWalkerResults
    docs/interface/IWalkerSchema
    docs/interface/IWalkerStrategyResult
    docs/interface/IWarmCandlesParams
    docs/interface/LiveStatisticsModel
    docs/interface/MaxDrawdownContract
    docs/interface/MaxDrawdownEvent
    docs/interface/MaxDrawdownStatisticsModel
    docs/interface/MessageModel
    docs/interface/MetricStats
    docs/interface/PartialEvent
    docs/interface/PartialLossAvailableNotification
    docs/interface/PartialLossCommit
    docs/interface/PartialLossCommitNotification
    docs/interface/PartialLossContract
    docs/interface/PartialProfitAvailableNotification
    docs/interface/PartialProfitCommit
    docs/interface/PartialProfitCommitNotification
    docs/interface/PartialProfitContract
    docs/interface/PartialStatisticsModel
    docs/interface/PerformanceContract
    docs/interface/PerformanceStatisticsModel
    docs/interface/ProgressBacktestContract
    docs/interface/ProgressWalkerContract
    docs/interface/RiskContract
    docs/interface/RiskEvent
    docs/interface/RiskRejectionNotification
    docs/interface/RiskStatisticsModel
    docs/interface/ScheduledEvent
    docs/interface/SchedulePingContract
    docs/interface/ScheduleStatisticsModel
    docs/interface/Signal
    docs/interface/Signal$1
    docs/interface/Signal$2
    docs/interface/SignalCancelledNotification
    docs/interface/SignalCloseContract
    docs/interface/SignalClosedNotification
    docs/interface/SignalCommitBase
    docs/interface/SignalData$1
    docs/interface/SignalInfoContract
    docs/interface/SignalInfoNotification
    docs/interface/SignalOpenContract
    docs/interface/SignalOpenedNotification
    docs/interface/SignalScheduledNotification
    docs/interface/SignalSyncBase
    docs/interface/SignalSyncCloseNotification
    docs/interface/SignalSyncOpenNotification
    docs/interface/StrategyEvent
    docs/interface/StrategyStatisticsModel
    docs/interface/SyncEvent
    docs/interface/SyncStatisticsModel
    docs/interface/TickEvent
    docs/interface/TrailingStopCommit
    docs/interface/TrailingStopCommitNotification
    docs/interface/TrailingTakeCommit
    docs/interface/TrailingTakeCommitNotification
    docs/interface/ValidateArgs
    docs/interface/ValidationErrorNotification
    docs/interface/WalkerCompleteContract
    docs/interface/WalkerContract
    docs/interface/WalkerStatisticsModel
    docs/interface/WalkerStopContract
    docs/type/ActionName
    docs/type/Args
    docs/type/BreakevenData
    docs/type/BrokerAverageBuyPayload
    docs/type/BrokerBreakevenPayload
    docs/type/BrokerPartialLossPayload
    docs/type/BrokerPartialProfitPayload
    docs/type/BrokerSignalClosePayload
    docs/type/BrokerSignalOpenPayload
    docs/type/BrokerTrailingStopPayload
    docs/type/BrokerTrailingTakePayload
    docs/type/BucketName
    docs/type/CacheFileFunction
    docs/type/CacheFileKeyArgs
    docs/type/CandleData
    docs/type/CandleInterval
    docs/type/ColumnConfig
    docs/type/Columns
    docs/type/Columns$1
    docs/type/Columns$2
    docs/type/Columns$3
    docs/type/Columns$4
    docs/type/Columns$5
    docs/type/Columns$6
    docs/type/Columns$7
    docs/type/Columns$8
    docs/type/Columns$9
    docs/type/Columns$a
    docs/type/Columns$b
    docs/type/CommitPayload
    docs/type/Dispatch
    docs/type/Dispatch$1
    docs/type/DropFirst
    docs/type/DropFirst$1
    docs/type/EntityId
    docs/type/Enum
    docs/type/ExchangeName
    docs/type/FrameInterval
    docs/type/FrameName
    docs/type/Function
    docs/type/Function$1
    docs/type/Function$2
    docs/type/GetStateFn
    docs/type/GlobalConfig
    docs/type/IBacktestLogicPrivateService
    docs/type/ICommitRow
    docs/type/ILiveLogicPrivateService
    docs/type/IntervalData
    docs/type/IntervalFileFunction
    docs/type/IntervalFileKeyArgs
    docs/type/IPublicAction
    docs/type/ISizingCalculateParams
    docs/type/ISizingParams
    docs/type/ISizingSchema
    docs/type/IStorageSignalRow
    docs/type/IStrategyBacktestResult
    docs/type/IStrategyTickResult
    docs/type/IWalkerLogicPrivateService
    docs/type/LogData
    docs/type/MarkdownName
    docs/type/MeasureData
    docs/type/MemoryData
    docs/type/MessageRole
    docs/type/MessageToolCall
    docs/type/NotificationData
    docs/type/NotificationModel
    docs/type/Num
    docs/type/PartialData
    docs/type/PartialLevel
    docs/type/PerformanceMetricType
    docs/type/PnlColumn
    docs/type/RecentData
    docs/type/ReportName
    docs/type/RestoreSnapshot
    docs/type/RiskData
    docs/type/RiskMap
    docs/type/RiskName
    docs/type/RiskRejection
    docs/type/ScheduleData
    docs/type/SearchSettings
    docs/type/SessionData
    docs/type/SetStateFn
    docs/type/SignalData
    docs/type/SignalInterval
    docs/type/SignalNotificationPayload
    docs/type/SignalStateTuple
    docs/type/SignalSyncContract
    docs/type/SizingName
    docs/type/StateData
    docs/type/StorageData
    docs/type/StorageId
    docs/type/StrategyActionType
    docs/type/StrategyCancelReason
    docs/type/StrategyCloseReason
    docs/type/StrategyColumn
    docs/type/StrategyCommitContract
    docs/type/StrategyName
    docs/type/SyncActionType
    docs/type/TAction
    docs/type/TAction$1
    docs/type/TActionCtor
    docs/type/TActionSchema
    docs/type/TBacktestLogicPrivateService
    docs/type/TBacktestLogicPublicService
    docs/type/TBreakeven
    docs/type/TBrokerCtor
    docs/type/TDumpInstanceCtor
    docs/type/TExchange
    docs/type/TExchangeSchema
    docs/type/TExecutionContextService
    docs/type/TFrame
    docs/type/TFrameSchema
    docs/type/TLiveLogicPrivateService
    docs/type/TLiveLogicPublicService
    docs/type/TLogCtor
    docs/type/TMarkdownBase
    docs/type/TMarkdownBaseCtor
    docs/type/TMemoryInstance
    docs/type/TMemoryInstanceCtor
    docs/type/TNotificationUtilsCtor
    docs/type/TPartial
    docs/type/TPersistBase
    docs/type/TPersistBaseCtor
    docs/type/TPersistBreakevenInstanceCtor
    docs/type/TPersistCandleInstanceCtor
    docs/type/TPersistIntervalInstanceCtor
    docs/type/TPersistLogInstanceCtor
    docs/type/TPersistMeasureInstanceCtor
    docs/type/TPersistMemoryInstanceCtor
    docs/type/TPersistNotificationInstanceCtor
    docs/type/TPersistPartialInstanceCtor
    docs/type/TPersistRecentInstanceCtor
    docs/type/TPersistRiskInstanceCtor
    docs/type/TPersistScheduleInstanceCtor
    docs/type/TPersistSessionInstanceCtor
    docs/type/TPersistSignalInstanceCtor
    docs/type/TPersistStateInstanceCtor
    docs/type/TPersistStorageInstanceCtor
    docs/type/TRecentUtilsCtor
    docs/type/TReportBase
    docs/type/TReportBaseCtor
    docs/type/TRisk
    docs/type/TRisk$1
    docs/type/TRiskSchema
    docs/type/TSessionAdapter
    docs/type/TSessionInstanceCtor
    docs/type/TSizing
    docs/type/TSizing$1
    docs/type/TSizingSchema
    docs/type/TStateAdapter
    docs/type/TStateInstanceCtor
    docs/type/TStorageUtilsCtor
    docs/type/TStrategy
    docs/type/TStrategy$1
    docs/type/TStrategySchema
    docs/type/TWalkerLogicPrivateService
    docs/type/TWalkerLogicPublicService
    docs/type/TWalkerSchema
    docs/type/WalkerMetric
    docs/type/WalkerName

    example

    example/01_getting_started
    example/02_first_backtest
    example/03_understanding_signals
    example/04_live_trading
    example/05_risk_management
    example/06_ai_optimization
    example/07_llm_trading

    packages/front

    packages/front/readme

    packages/graph

    packages/graph/readme

    packages/mongo

    packages/mongo/readme

    packages/ollama

    packages/ollama/readme

    packages/pinets

    packages/pinets/readme

    packages/sidekick

    packages/sidekick/readme

    packages/signals

    packages/signals/readme

    private

    private/classes
    private/functions
    private/interfaces
    +backtest-kit

    backtest-kit

    Modules

    types

    article

    article/01_look_ahead_bias
    article/02_second_order_chaos
    article/03_claude_trader
    article/04_option_hedging
    article/05_ai_strategy_workflow
    article/06_ai_strategy_blueprint
    article/07_ai_news_trading_signals
    article/08_ai_liquidity_harvesting
    article/09_pinescript_local_markets
    article/10_dca_averaging_strategy

    begin

    begin/01_project_overview
    begin/02_getting_started_configuration
    begin/03_system_architecture_overview
    begin/04_llm_forecast_engine_logic
    begin/05_forecast_pipeline_outline
    begin/06_advisors_news_market_data
    begin/07_news_fetching_caching_fetchnews
    begin/08_ollama_completions
    begin/09_trading_strategy_feb_2026_strategy
    begin/10_signal_generation_sentiment_mapping
    begin/11_position_lifecycle_exit_logic
    begin/12_backtest_module_frame_configuration
    begin/13_february_2026_case_study_performance
    begin/14_backtest_kit_framework
    begin/15_backtesting_execution_reporting
    begin/16_signal_state_machine
    begin/17_live_trading_mode
    begin/18_risk_management
    begin/19_ai_strategy_optimization_walker
    begin/20_exchange_integration_modules
    begin/21_ccxt_exchange_adapter
    begin/22_symbol_configuration
    begin/23_glossary

    cli

    cli/readme

    concept

    concept/01_monorepo_parallel_execution
    concept/02_zero_expectation_escape

    data

    data/test-guidelines

    demo/backtest

    demo/backtest/readme

    demo/exchange

    demo/exchange/readme

    demo/live

    demo/live/readme

    demo/optimization

    demo/optimization/readme

    demo/pinets

    demo/pinets/readme

    design

    design/01_overview
    design/02_key_features
    design/03_installation_and_setup
    design/04_quick_start_guide
    design/05_core_concepts
    design/06_execution_modes
    design/07_signal_lifecycle_overview
    design/08_component_registration
    design/09_temporal_isolation_and_look-ahead_prevention
    design/10_architecture
    design/11_layer_responsibilities
    design/12_dependency_injection_system
    design/13_context_propagation
    design/14_event_system
    design/15_public_api_reference
    design/16_configuration_functions
    design/17_component_registration_functions
    design/18_backtest_api
    design/19_live_trading_api
    design/20_walker_api
    design/21_persistence_utilities
    design/22_exchange_functions
    design/23_event_listeners
    design/24_component_schemas
    design/25_strategy_schemas
    design/26_exchange_schemas
    design/27_frame_schemas
    design/28_risk_schemas
    design/29_sizing_schemas
    design/30_walker_schemas
    design/31_optimizer_schemas
    design/32_client_implementations
    design/33_clientstrategy
    design/34_clientexchange
    design/35_clientframe
    design/36_clientrisk
    design/37_clientsizing
    design/38_clientpartial
    design/39_clientoptimizer
    design/40_service_layer
    design/41_service_architecture_overview
    design/42_connection_services
    design/43_schema_services
    design/44_validation_services
    design/45_global_services
    design/46_logic_services
    design/47_markdown_services
    design/48_signal_lifecycle
    design/49_signal_states
    design/50_signal_generation_and_validation
    design/51_scheduled_signals
    design/52_signal_persistence
    design/53_pnl_calculation
    design/54_backtesting
    design/55_backtest_execution_flow
    design/56_timeframe_generation
    design/57_fast-forward_simulation
    design/58_live_trading
    design/59_live_execution_flow
    design/60_crash_recovery
    design/61_real-time_monitoring
    design/62_interval_throttling
    design/63_walker_mode
    design/64_walker_execution_flow
    design/65_strategy_comparison
    design/66_walker_reports
    design/67_risk_management
    design/68_risk_profiles
    design/69_risk_validation
    design/70_position_tracking
    design/71_reporting_and_analytics
    design/72_markdown_report_generation
    design/73_performance_metrics
    design/74_statistics_calculation
    design/75_partial_profit_loss_tracking
    design/76_heatmap_analytics
    design/77_configuration
    design/78_global_configuration
    design/79_validation_parameters
    design/80_timing_parameters
    design/81_cross-cutting_concerns
    design/82_logging_system
    design/83_error_handling
    design/84_persistence_layer
    design/85_advanced_topics
    design/86_custom_exchange_integration
    design/87_custom_persistence_backends
    design/88_custom_risk_validations
    design/89_multi-symbol_strategies
    design/90_ai-powered_strategy_optimization
    design/91_optimizer_architecture
    design/92_data_collection_pipeline
    design/93_llm_integration
    design/94_strategy_code_generation
    design/95_training_vs_testing_ranges

    docs

    docs
    docs/class/ActionBase
    docs/class/ActionConnectionService
    docs/class/ActionCoreService
    docs/class/ActionProxy
    docs/class/ActionSchemaService
    docs/class/ActionValidationService
    docs/class/BacktestCommandService
    docs/class/BacktestLogicPrivateService
    docs/class/BacktestLogicPublicService
    docs/class/BacktestMarkdownService
    docs/class/BacktestReportService
    docs/class/BacktestUtils
    docs/class/BreakevenConnectionService
    docs/class/BreakevenGlobalService
    docs/class/BreakevenMarkdownService
    docs/class/BreakevenReportService
    docs/class/BreakevenUtils
    docs/class/BrokerAdapter
    docs/class/BrokerBase
    docs/class/CacheUtils
    docs/class/ClientAction
    docs/class/ClientExchange
    docs/class/ClientFrame
    docs/class/ClientRisk
    docs/class/ClientSizing
    docs/class/ColumnValidationService
    docs/class/ConfigValidationService
    docs/class/ConstantUtils
    docs/class/CronUtils
    docs/class/DumpAdapter
    docs/class/ExchangeConnectionService
    docs/class/ExchangeCoreService
    docs/class/ExchangeSchemaService
    docs/class/ExchangeUtils
    docs/class/ExchangeValidationService
    docs/class/FrameConnectionService
    docs/class/FrameCoreService
    docs/class/FrameSchemaService
    docs/class/FrameValidationService
    docs/class/HeatMarkdownService
    docs/class/HeatReportService
    docs/class/HeatUtils
    docs/class/HighestProfitMarkdownService
    docs/class/HighestProfitReportService
    docs/class/HighestProfitUtils
    docs/class/IntervalUtils
    docs/class/LiveCommandService
    docs/class/LiveLogicPrivateService
    docs/class/LiveLogicPublicService
    docs/class/LiveMarkdownService
    docs/class/LiveReportService
    docs/class/LiveUtils
    docs/class/LogAdapter
    docs/class/LoggerService
    docs/class/LookupUtils
    docs/class/MarkdownAdapter
    docs/class/MarkdownFileBase
    docs/class/MarkdownFolderBase
    docs/class/MarkdownUtils
    docs/class/MarkdownWriterAdapter
    docs/class/MaxDrawdownMarkdownService
    docs/class/MaxDrawdownReportService
    docs/class/MaxDrawdownUtils
    docs/class/MemoryAdapter
    docs/class/MemoryBacktestAdapter
    docs/class/MemoryLiveAdapter
    docs/class/NotificationAdapter
    docs/class/NotificationBacktestAdapter
    docs/class/NotificationHelperService
    docs/class/NotificationLiveAdapter
    docs/class/PartialConnectionService
    docs/class/PartialGlobalService
    docs/class/PartialMarkdownService
    docs/class/PartialReportService
    docs/class/PartialUtils
    docs/class/Performance
    docs/class/PerformanceMarkdownService
    docs/class/PerformanceReportService
    docs/class/PersistBase
    docs/class/PersistBreakevenInstance
    docs/class/PersistBreakevenUtils
    docs/class/PersistCandleInstance
    docs/class/PersistCandleUtils
    docs/class/PersistIntervalInstance
    docs/class/PersistIntervalUtils
    docs/class/PersistLogInstance
    docs/class/PersistLogUtils
    docs/class/PersistMeasureInstance
    docs/class/PersistMeasureUtils
    docs/class/PersistMemoryInstance
    docs/class/PersistMemoryUtils
    docs/class/PersistNotificationInstance
    docs/class/PersistNotificationUtils
    docs/class/PersistPartialInstance
    docs/class/PersistPartialUtils
    docs/class/PersistRecentInstance
    docs/class/PersistRecentUtils
    docs/class/PersistRiskInstance
    docs/class/PersistRiskUtils
    docs/class/PersistScheduleInstance
    docs/class/PersistScheduleUtils
    docs/class/PersistSessionInstance
    docs/class/PersistSessionUtils
    docs/class/PersistSignalInstance
    docs/class/PersistSignalUtils
    docs/class/PersistStateInstance
    docs/class/PersistStateUtils
    docs/class/PersistStorageInstance
    docs/class/PersistStorageUtils
    docs/class/Position
    docs/class/PositionSizeUtils
    docs/class/PriceMetaService
    docs/class/RecentAdapter
    docs/class/RecentBacktestAdapter
    docs/class/RecentLiveAdapter
    docs/class/ReflectUtils
    docs/class/ReportAdapter
    docs/class/ReportBase
    docs/class/ReportUtils
    docs/class/ReportWriterAdapter
    docs/class/RiskConnectionService
    docs/class/RiskGlobalService
    docs/class/RiskMarkdownService
    docs/class/RiskReportService
    docs/class/RiskSchemaService
    docs/class/RiskUtils
    docs/class/RiskValidationService
    docs/class/ScheduleMarkdownService
    docs/class/ScheduleReportService
    docs/class/ScheduleUtils
    docs/class/SessionAdapter
    docs/class/SessionBacktestAdapter
    docs/class/SessionLiveAdapter
    docs/class/SizingConnectionService
    docs/class/SizingGlobalService
    docs/class/SizingSchemaService
    docs/class/SizingValidationService
    docs/class/StateAdapter
    docs/class/StateBacktestAdapter
    docs/class/StateLiveAdapter
    docs/class/StorageAdapter
    docs/class/StorageBacktestAdapter
    docs/class/StorageLiveAdapter
    docs/class/StrategyConnectionService
    docs/class/StrategyCoreService
    docs/class/StrategyMarkdownService
    docs/class/StrategyReportService
    docs/class/StrategySchemaService
    docs/class/StrategyUtils
    docs/class/StrategyValidationService
    docs/class/SyncMarkdownService
    docs/class/SyncReportService
    docs/class/SyncUtils
    docs/class/SystemUtils
    docs/class/TimeMetaService
    docs/class/WalkerCommandService
    docs/class/WalkerLogicPrivateService
    docs/class/WalkerLogicPublicService
    docs/class/WalkerMarkdownService
    docs/class/WalkerReportService
    docs/class/WalkerSchemaService
    docs/class/WalkerUtils
    docs/class/WalkerValidationService
    docs/function/addActionSchema
    docs/function/addExchangeSchema
    docs/function/addFrameSchema
    docs/function/addRiskSchema
    docs/function/addSizingSchema
    docs/function/addStrategySchema
    docs/function/addWalkerSchema
    docs/function/cacheCandles
    docs/function/checkCandles
    docs/function/commitActivateScheduled
    docs/function/commitAverageBuy
    docs/function/commitBreakeven
    docs/function/commitCancelScheduled
    docs/function/commitClosePending
    docs/function/commitPartialLoss
    docs/function/commitPartialLossCost
    docs/function/commitPartialProfit
    docs/function/commitPartialProfitCost
    docs/function/commitSignalNotify
    docs/function/commitTrailingStop
    docs/function/commitTrailingStopCost
    docs/function/commitTrailingTake
    docs/function/commitTrailingTakeCost
    docs/function/createSignalState
    docs/function/dumpAgentAnswer
    docs/function/dumpError
    docs/function/dumpJson
    docs/function/dumpRecord
    docs/function/dumpTable
    docs/function/dumpText
    docs/function/formatPrice
    docs/function/formatQuantity
    docs/function/getActionSchema
    docs/function/getAggregatedTrades
    docs/function/getAveragePrice
    docs/function/getBacktestTimeframe
    docs/function/getBreakeven
    docs/function/getCandles
    docs/function/getClosePrice
    docs/function/getColumns
    docs/function/getConfig
    docs/function/getContext
    docs/function/getDate
    docs/function/getDefaultColumns
    docs/function/getDefaultConfig
    docs/function/getExchangeSchema
    docs/function/getFrameSchema
    docs/function/getLatestSignal
    docs/function/getMaxDrawdownDistancePnlCost
    docs/function/getMaxDrawdownDistancePnlPercentage
    docs/function/getMinutesSinceLatestSignalCreated
    docs/function/getMode
    docs/function/getNextCandles
    docs/function/getOrderBook
    docs/function/getPendingSignal
    docs/function/getPositionActiveMinutes
    docs/function/getPositionCountdownMinutes
    docs/function/getPositionDrawdownMinutes
    docs/function/getPositionEffectivePrice
    docs/function/getPositionEntries
    docs/function/getPositionEntryOverlap
    docs/function/getPositionEstimateMinutes
    docs/function/getPositionHighestMaxDrawdownPnlCost
    docs/function/getPositionHighestMaxDrawdownPnlPercentage
    docs/function/getPositionHighestPnlCost
    docs/function/getPositionHighestPnlPercentage
    docs/function/getPositionHighestProfitBreakeven
    docs/function/getPositionHighestProfitDistancePnlCost
    docs/function/getPositionHighestProfitDistancePnlPercentage
    docs/function/getPositionHighestProfitMinutes
    docs/function/getPositionHighestProfitPrice
    docs/function/getPositionHighestProfitTimestamp
    docs/function/getPositionInvestedCost
    docs/function/getPositionInvestedCount
    docs/function/getPositionLevels
    docs/function/getPositionMaxDrawdownMinutes
    docs/function/getPositionMaxDrawdownPnlCost
    docs/function/getPositionMaxDrawdownPnlPercentage
    docs/function/getPositionMaxDrawdownPrice
    docs/function/getPositionMaxDrawdownTimestamp
    docs/function/getPositionPartialOverlap
    docs/function/getPositionPartials
    docs/function/getPositionPnlCost
    docs/function/getPositionPnlPercent
    docs/function/getPositionWaitingMinutes
    docs/function/getRawCandles
    docs/function/getRiskSchema
    docs/function/getScheduledSignal
    docs/function/getSessionData
    docs/function/getSignalState
    docs/function/getSizingSchema
    docs/function/getStrategySchema
    docs/function/getSymbol
    docs/function/getTimestamp
    docs/function/getTotalCostClosed
    docs/function/getTotalPercentClosed
    docs/function/getWalkerSchema
    docs/function/hasNoPendingSignal
    docs/function/hasNoScheduledSignal
    docs/function/hasTradeContext
    docs/function/listenActivePing
    docs/function/listenActivePingOnce
    docs/function/listenAfterEnd
    docs/function/listenAfterEndOnce
    docs/function/listenBacktestProgress
    docs/function/listenBeforeStart
    docs/function/listenBeforeStartOnce
    docs/function/listenBreakevenAvailable
    docs/function/listenBreakevenAvailableOnce
    docs/function/listenDoneBacktest
    docs/function/listenDoneBacktestOnce
    docs/function/listenDoneLive
    docs/function/listenDoneLiveOnce
    docs/function/listenDoneWalker
    docs/function/listenDoneWalkerOnce
    docs/function/listenError
    docs/function/listenExit
    docs/function/listenHighestProfit
    docs/function/listenHighestProfitOnce
    docs/function/listenIdlePing
    docs/function/listenIdlePingOnce
    docs/function/listenMaxDrawdown
    docs/function/listenMaxDrawdownOnce
    docs/function/listenPartialLossAvailable
    docs/function/listenPartialLossAvailableOnce
    docs/function/listenPartialProfitAvailable
    docs/function/listenPartialProfitAvailableOnce
    docs/function/listenPerformance
    docs/function/listenRisk
    docs/function/listenRiskOnce
    docs/function/listenSchedulePing
    docs/function/listenSchedulePingOnce
    docs/function/listenSignal
    docs/function/listenSignalBacktest
    docs/function/listenSignalBacktestOnce
    docs/function/listenSignalLive
    docs/function/listenSignalLiveOnce
    docs/function/listenSignalNotify
    docs/function/listenSignalNotifyOnce
    docs/function/listenSignalOnce
    docs/function/listenStrategyCommit
    docs/function/listenStrategyCommitOnce
    docs/function/listenSync
    docs/function/listenSyncOnce
    docs/function/listenValidation
    docs/function/listenWalker
    docs/function/listenWalkerComplete
    docs/function/listenWalkerOnce
    docs/function/listenWalkerProgress
    docs/function/listExchangeSchema
    docs/function/listFrameSchema
    docs/function/listMemory
    docs/function/listRiskSchema
    docs/function/listSizingSchema
    docs/function/listStrategySchema
    docs/function/listWalkerSchema
    docs/function/overrideActionSchema
    docs/function/overrideExchangeSchema
    docs/function/overrideFrameSchema
    docs/function/overrideRiskSchema
    docs/function/overrideSizingSchema
    docs/function/overrideStrategySchema
    docs/function/overrideWalkerSchema
    docs/function/readMemory
    docs/function/removeMemory
    docs/function/runInMockContext
    docs/function/searchMemory
    docs/function/setColumns
    docs/function/setConfig
    docs/function/setLogger
    docs/function/setSessionData
    docs/function/setSignalState
    docs/function/shutdown
    docs/function/stopStrategy
    docs/function/validate
    docs/function/waitForReady
    docs/function/warmCandles
    docs/function/writeMemory
    docs/interface/ActivateScheduledCommit
    docs/interface/ActivateScheduledCommitNotification
    docs/interface/ActivePingContract
    docs/interface/AfterEndContract
    docs/interface/AverageBuyCommit
    docs/interface/AverageBuyCommitNotification
    docs/interface/BacktestStatisticsModel
    docs/interface/BeforeStartContract
    docs/interface/BreakevenAvailableNotification
    docs/interface/BreakevenCommit
    docs/interface/BreakevenCommitNotification
    docs/interface/BreakevenContract
    docs/interface/BreakevenEvent
    docs/interface/BreakevenStatisticsModel
    docs/interface/CancelScheduledCommit
    docs/interface/CancelScheduledCommitNotification
    docs/interface/ClosePendingCommit
    docs/interface/ClosePendingCommitNotification
    docs/interface/ColumnModel
    docs/interface/CriticalErrorNotification
    docs/interface/CronEntry
    docs/interface/CronHandle
    docs/interface/DoneContract
    docs/interface/HeatmapStatisticsModel
    docs/interface/HighestProfitContract
    docs/interface/HighestProfitEvent
    docs/interface/HighestProfitStatisticsModel
    docs/interface/IAction
    docs/interface/IActionCallbacks
    docs/interface/IActionParams
    docs/interface/IActionSchema
    docs/interface/IActionStrategy
    docs/interface/IActivateScheduledCommitRow
    docs/interface/IActivityEntry
    docs/interface/IAggregatedTradeData
    docs/interface/IAverageBuyCommitRow
    docs/interface/IBidData
    docs/interface/IBreakeven
    docs/interface/IBreakevenCommitRow
    docs/interface/IBreakevenData
    docs/interface/IBroker
    docs/interface/ICacheCandlesParams
    docs/interface/ICandleData
    docs/interface/ICheckCandlesParams
    docs/interface/ICommitRowBase
    docs/interface/IdlePingContract
    docs/interface/IDumpContext
    docs/interface/IDumpInstance
    docs/interface/IEntity
    docs/interface/IExchange
    docs/interface/IExchangeCallbacks
    docs/interface/IExchangeParams
    docs/interface/IExchangeSchema
    docs/interface/IExecutionContext
    docs/interface/IFrame
    docs/interface/IFrameCallbacks
    docs/interface/IFrameParams
    docs/interface/IFrameSchema
    docs/interface/IHeatmapRow
    docs/interface/ILog
    docs/interface/ILogEntry
    docs/interface/ILogger
    docs/interface/IMarkdownDumpOptions
    docs/interface/IMarkdownTarget
    docs/interface/IMemoryInstance
    docs/interface/IMethodContext
    docs/interface/InfoErrorNotification
    docs/interface/INotificationTarget
    docs/interface/INotificationUtils
    docs/interface/IOrderBookData
    docs/interface/IParseArgsParams
    docs/interface/IParseArgsResult
    docs/interface/IPartial
    docs/interface/IPartialData
    docs/interface/IPartialLossCommitRow
    docs/interface/IPartialProfitCommitRow
    docs/interface/IPersistBase
    docs/interface/IPersistBreakevenInstance
    docs/interface/IPersistCandleInstance
    docs/interface/IPersistIntervalInstance
    docs/interface/IPersistLogInstance
    docs/interface/IPersistMeasureInstance
    docs/interface/IPersistMemoryInstance
    docs/interface/IPersistNotificationInstance
    docs/interface/IPersistPartialInstance
    docs/interface/IPersistRecentInstance
    docs/interface/IPersistRiskInstance
    docs/interface/IPersistScheduleInstance
    docs/interface/IPersistSessionInstance
    docs/interface/IPersistSignalInstance
    docs/interface/IPersistStateInstance
    docs/interface/IPersistStorageInstance
    docs/interface/IPositionOverlapLadder
    docs/interface/IPositionSizeATRParams
    docs/interface/IPositionSizeFixedPercentageParams
    docs/interface/IPositionSizeKellyParams
    docs/interface/IPublicCandleData
    docs/interface/IPublicSignalRow
    docs/interface/IRecentUtils
    docs/interface/IReportDumpOptions
    docs/interface/IReportTarget
    docs/interface/IRisk
    docs/interface/IRiskActivePosition
    docs/interface/IRiskCallbacks
    docs/interface/IRiskCheckArgs
    docs/interface/IRiskCheckOptions
    docs/interface/IRiskParams
    docs/interface/IRiskRejectionResult
    docs/interface/IRiskSchema
    docs/interface/IRiskSignalRow
    docs/interface/IRiskValidation
    docs/interface/IRiskValidationFn
    docs/interface/IRiskValidationPayload
    docs/interface/IRunContext
    docs/interface/IScheduledSignalCancelRow
    docs/interface/IScheduledSignalRow
    docs/interface/ISessionInstance
    docs/interface/ISignalDto
    docs/interface/ISignalIntervalDto
    docs/interface/ISignalRow
    docs/interface/ISizing
    docs/interface/ISizingCalculateParamsATR
    docs/interface/ISizingCalculateParamsBase
    docs/interface/ISizingCalculateParamsFixedPercentage
    docs/interface/ISizingCalculateParamsKelly
    docs/interface/ISizingCallbacks
    docs/interface/ISizingParamsATR
    docs/interface/ISizingParamsFixedPercentage
    docs/interface/ISizingParamsKelly
    docs/interface/ISizingSchemaATR
    docs/interface/ISizingSchemaBase
    docs/interface/ISizingSchemaFixedPercentage
    docs/interface/ISizingSchemaKelly
    docs/interface/IStateInstance
    docs/interface/IStateParams
    docs/interface/IStorageSignalRowBase
    docs/interface/IStorageSignalRowCancelled
    docs/interface/IStorageSignalRowClosed
    docs/interface/IStorageSignalRowOpened
    docs/interface/IStorageSignalRowScheduled
    docs/interface/IStorageUtils
    docs/interface/IStrategy
    docs/interface/IStrategyCallbacks
    docs/interface/IStrategyPnL
    docs/interface/IStrategyResult
    docs/interface/IStrategySchema
    docs/interface/IStrategyTickResultActive
    docs/interface/IStrategyTickResultCancelled
    docs/interface/IStrategyTickResultClosed
    docs/interface/IStrategyTickResultIdle
    docs/interface/IStrategyTickResultOpened
    docs/interface/IStrategyTickResultScheduled
    docs/interface/IStrategyTickResultWaiting
    docs/interface/ITrailingStopCommitRow
    docs/interface/ITrailingTakeCommitRow
    docs/interface/IWalkerCallbacks
    docs/interface/IWalkerResults
    docs/interface/IWalkerSchema
    docs/interface/IWalkerStrategyResult
    docs/interface/IWarmCandlesParams
    docs/interface/LiveStatisticsModel
    docs/interface/MaxDrawdownContract
    docs/interface/MaxDrawdownEvent
    docs/interface/MaxDrawdownStatisticsModel
    docs/interface/MessageModel
    docs/interface/MetricStats
    docs/interface/PartialEvent
    docs/interface/PartialLossAvailableNotification
    docs/interface/PartialLossCommit
    docs/interface/PartialLossCommitNotification
    docs/interface/PartialLossContract
    docs/interface/PartialProfitAvailableNotification
    docs/interface/PartialProfitCommit
    docs/interface/PartialProfitCommitNotification
    docs/interface/PartialProfitContract
    docs/interface/PartialStatisticsModel
    docs/interface/PerformanceContract
    docs/interface/PerformanceStatisticsModel
    docs/interface/ProgressBacktestContract
    docs/interface/ProgressWalkerContract
    docs/interface/RiskContract
    docs/interface/RiskEvent
    docs/interface/RiskRejectionNotification
    docs/interface/RiskStatisticsModel
    docs/interface/ScheduledEvent
    docs/interface/SchedulePingContract
    docs/interface/ScheduleStatisticsModel
    docs/interface/Signal
    docs/interface/Signal$1
    docs/interface/Signal$2
    docs/interface/SignalCancelledNotification
    docs/interface/SignalCloseContract
    docs/interface/SignalClosedNotification
    docs/interface/SignalCommitBase
    docs/interface/SignalData$1
    docs/interface/SignalInfoContract
    docs/interface/SignalInfoNotification
    docs/interface/SignalOpenContract
    docs/interface/SignalOpenedNotification
    docs/interface/SignalScheduledNotification
    docs/interface/SignalSyncBase
    docs/interface/SignalSyncCloseNotification
    docs/interface/SignalSyncOpenNotification
    docs/interface/StrategyEvent
    docs/interface/StrategyStatisticsModel
    docs/interface/SyncEvent
    docs/interface/SyncStatisticsModel
    docs/interface/TickEvent
    docs/interface/TrailingStopCommit
    docs/interface/TrailingStopCommitNotification
    docs/interface/TrailingTakeCommit
    docs/interface/TrailingTakeCommitNotification
    docs/interface/ValidateArgs
    docs/interface/ValidationErrorNotification
    docs/interface/WalkerCompleteContract
    docs/interface/WalkerContract
    docs/interface/WalkerStatisticsModel
    docs/interface/WalkerStopContract
    docs/type/ActionName
    docs/type/Args
    docs/type/BreakevenData
    docs/type/BrokerAverageBuyPayload
    docs/type/BrokerBreakevenPayload
    docs/type/BrokerPartialLossPayload
    docs/type/BrokerPartialProfitPayload
    docs/type/BrokerSignalClosePayload
    docs/type/BrokerSignalOpenPayload
    docs/type/BrokerTrailingStopPayload
    docs/type/BrokerTrailingTakePayload
    docs/type/BucketName
    docs/type/CacheFileFunction
    docs/type/CacheFileKeyArgs
    docs/type/CandleData
    docs/type/CandleInterval
    docs/type/ColumnConfig
    docs/type/Columns
    docs/type/Columns$1
    docs/type/Columns$2
    docs/type/Columns$3
    docs/type/Columns$4
    docs/type/Columns$5
    docs/type/Columns$6
    docs/type/Columns$7
    docs/type/Columns$8
    docs/type/Columns$9
    docs/type/Columns$a
    docs/type/Columns$b
    docs/type/CommitPayload
    docs/type/CronCallback
    docs/type/Dispatch
    docs/type/Dispatch$1
    docs/type/DropFirst
    docs/type/DropFirst$1
    docs/type/EntityId
    docs/type/Enum
    docs/type/ExchangeName
    docs/type/FrameInterval
    docs/type/FrameName
    docs/type/Function
    docs/type/Function$1
    docs/type/Function$2
    docs/type/GetStateFn
    docs/type/GlobalConfig
    docs/type/IBacktestLogicPrivateService
    docs/type/ICommitRow
    docs/type/ILiveLogicPrivateService
    docs/type/IntervalData
    docs/type/IntervalFileFunction
    docs/type/IntervalFileKeyArgs
    docs/type/IPublicAction
    docs/type/ISizingCalculateParams
    docs/type/ISizingParams
    docs/type/ISizingSchema
    docs/type/IStorageSignalRow
    docs/type/IStrategyBacktestResult
    docs/type/IStrategyTickResult
    docs/type/IWalkerLogicPrivateService
    docs/type/Keys
    docs/type/Keys$1
    docs/type/LogData
    docs/type/MarkdownName
    docs/type/MeasureData
    docs/type/MemoryData
    docs/type/MessageRole
    docs/type/MessageToolCall
    docs/type/NotificationData
    docs/type/NotificationModel
    docs/type/Num
    docs/type/PartialData
    docs/type/PartialLevel
    docs/type/PerformanceMetricType
    docs/type/PnlColumn
    docs/type/RecentData
    docs/type/ReportName
    docs/type/RestoreSnapshot
    docs/type/RiskData
    docs/type/RiskMap
    docs/type/RiskName
    docs/type/RiskRejection
    docs/type/ScheduleData
    docs/type/SearchSettings
    docs/type/SessionData
    docs/type/SetStateFn
    docs/type/SignalData
    docs/type/SignalInterval
    docs/type/SignalNotificationPayload
    docs/type/SignalStateTuple
    docs/type/SignalSyncContract
    docs/type/SizingName
    docs/type/StateData
    docs/type/StorageData
    docs/type/StorageId
    docs/type/StrategyActionType
    docs/type/StrategyCancelReason
    docs/type/StrategyCloseReason
    docs/type/StrategyColumn
    docs/type/StrategyCommitContract
    docs/type/StrategyName
    docs/type/SyncActionType
    docs/type/TAction
    docs/type/TAction$1
    docs/type/TActionCtor
    docs/type/TActionSchema
    docs/type/TBacktestLogicPrivateService
    docs/type/TBacktestLogicPublicService
    docs/type/TBreakeven
    docs/type/TBrokerCtor
    docs/type/TDumpInstanceCtor
    docs/type/TExchange
    docs/type/TExchangeSchema
    docs/type/TExecutionContextService
    docs/type/TFrame
    docs/type/TFrameSchema
    docs/type/TLiveLogicPrivateService
    docs/type/TLiveLogicPublicService
    docs/type/TLogCtor
    docs/type/TMarkdownBase
    docs/type/TMarkdownBaseCtor
    docs/type/TMemoryInstance
    docs/type/TMemoryInstanceCtor
    docs/type/TNotificationUtilsCtor
    docs/type/TPartial
    docs/type/TPersistBase
    docs/type/TPersistBaseCtor
    docs/type/TPersistBreakevenInstanceCtor
    docs/type/TPersistCandleInstanceCtor
    docs/type/TPersistIntervalInstanceCtor
    docs/type/TPersistLogInstanceCtor
    docs/type/TPersistMeasureInstanceCtor
    docs/type/TPersistMemoryInstanceCtor
    docs/type/TPersistNotificationInstanceCtor
    docs/type/TPersistPartialInstanceCtor
    docs/type/TPersistRecentInstanceCtor
    docs/type/TPersistRiskInstanceCtor
    docs/type/TPersistScheduleInstanceCtor
    docs/type/TPersistSessionInstanceCtor
    docs/type/TPersistSignalInstanceCtor
    docs/type/TPersistStateInstanceCtor
    docs/type/TPersistStorageInstanceCtor
    docs/type/TRecentUtilsCtor
    docs/type/TReportBase
    docs/type/TReportBaseCtor
    docs/type/TRisk
    docs/type/TRisk$1
    docs/type/TRiskSchema
    docs/type/TSessionAdapter
    docs/type/TSessionInstanceCtor
    docs/type/TSizing
    docs/type/TSizing$1
    docs/type/TSizingSchema
    docs/type/TStateAdapter
    docs/type/TStateInstanceCtor
    docs/type/TStorageUtilsCtor
    docs/type/TStrategy
    docs/type/TStrategy$1
    docs/type/TStrategySchema
    docs/type/TWalkerLogicPrivateService
    docs/type/TWalkerLogicPublicService
    docs/type/TWalkerSchema
    docs/type/WalkerMetric
    docs/type/WalkerName

    example

    example/01_getting_started
    example/02_first_backtest
    example/03_understanding_signals
    example/04_live_trading
    example/05_risk_management
    example/06_ai_optimization
    example/07_llm_trading

    packages/front

    packages/front/readme

    packages/graph

    packages/graph/readme

    packages/mongo

    packages/mongo/readme

    packages/ollama

    packages/ollama/readme

    packages/pinets

    packages/pinets/readme

    packages/sidekick

    packages/sidekick/readme

    packages/signals

    packages/signals/readme

    private

    private/classes
    private/functions
    private/interfaces
    +emitters | backtest-kit

    Module types

    Namespaces

    emitters

    Classes

    ActionBase
    BrokerBase
    MarkdownFileBase
    MarkdownFolderBase
    MemoryBacktestAdapter
    MemoryLiveAdapter
    Performance
    PersistBase
    PersistBreakevenInstance
    PersistCandleInstance
    PersistIntervalInstance
    PersistLogInstance
    PersistMeasureInstance
    PersistMemoryInstance
    PersistNotificationInstance
    PersistPartialInstance
    PersistRecentInstance
    PersistRiskInstance
    PersistScheduleInstance
    PersistSessionInstance
    PersistSignalInstance
    PersistStateInstance
    PersistStorageInstance
    Position
    ReportBase
    StateBacktestAdapter
    StateLiveAdapter

    Interfaces

    ActivateScheduledCommit
    ActivateScheduledCommitNotification
    ActivePingContract
    AverageBuyCommit
    AverageBuyCommitNotification
    BacktestStatisticsModel
    BreakevenAvailableNotification
    BreakevenCommit
    BreakevenCommitNotification
    BreakevenContract
    BreakevenEvent
    BreakevenStatisticsModel
    CancelScheduledCommit
    CancelScheduledCommitNotification
    ClosePendingCommit
    ClosePendingCommitNotification
    ColumnModel
    CriticalErrorNotification
    DoneContract
    HeatmapStatisticsModel
    HighestProfitContract
    HighestProfitEvent
    HighestProfitStatisticsModel
    IActionSchema
    IActivateScheduledCommitRow
    IAggregatedTradeData
    IBidData
    IBreakevenCommitRow
    IBroker
    ICandleData
    IdlePingContract
    IDumpContext
    IDumpInstance
    IExchangeSchema
    IFrameSchema
    IHeatmapRow
    ILog
    ILogEntry
    ILogger
    IMarkdownDumpOptions
    IMemoryInstance
    InfoErrorNotification
    INotificationUtils
    IOrderBookData
    IPartialLossCommitRow
    IPartialProfitCommitRow
    IPersistBase
    IPersistBreakevenInstance
    IPersistCandleInstance
    IPersistIntervalInstance
    IPersistLogInstance
    IPersistMeasureInstance
    IPersistMemoryInstance
    IPersistNotificationInstance
    IPersistPartialInstance
    IPersistRecentInstance
    IPersistRiskInstance
    IPersistScheduleInstance
    IPersistSessionInstance
    IPersistSignalInstance
    IPersistStateInstance
    IPersistStorageInstance
    IPositionSizeATRParams
    IPositionSizeFixedPercentageParams
    IPositionSizeKellyParams
    IPublicCandleData
    IPublicSignalRow
    IRecentUtils
    IReportDumpOptions
    IRiskActivePosition
    IRiskCheckArgs
    IRiskSchema
    IRiskSignalRow
    IRiskValidation
    IRiskValidationFn
    IRiskValidationPayload
    IScheduledSignalCancelRow
    IScheduledSignalRow
    ISessionInstance
    ISignalDto
    ISignalIntervalDto
    ISignalRow
    ISizingCalculateParamsATR
    ISizingCalculateParamsFixedPercentage
    ISizingCalculateParamsKelly
    ISizingParamsATR
    ISizingParamsFixedPercentage
    ISizingParamsKelly
    ISizingSchemaATR
    ISizingSchemaFixedPercentage
    ISizingSchemaKelly
    IStateInstance
    IStorageUtils
    IStrategyPnL
    IStrategyResult
    IStrategySchema
    IStrategyTickResultActive
    IStrategyTickResultCancelled
    IStrategyTickResultClosed
    IStrategyTickResultIdle
    IStrategyTickResultOpened
    IStrategyTickResultScheduled
    IStrategyTickResultWaiting
    ITrailingStopCommitRow
    ITrailingTakeCommitRow
    IWalkerResults
    IWalkerSchema
    IWalkerStrategyResult
    LiveStatisticsModel
    MaxDrawdownContract
    MaxDrawdownEvent
    MaxDrawdownStatisticsModel
    MessageModel
    MetricStats
    PartialEvent
    PartialLossAvailableNotification
    PartialLossCommit
    PartialLossCommitNotification
    PartialLossContract
    PartialProfitAvailableNotification
    PartialProfitCommit
    PartialProfitCommitNotification
    PartialProfitContract
    PartialStatisticsModel
    PerformanceContract
    PerformanceStatisticsModel
    ProgressBacktestContract
    ProgressWalkerContract
    RiskContract
    RiskEvent
    RiskRejectionNotification
    RiskStatisticsModel
    ScheduledEvent
    SchedulePingContract
    ScheduleStatisticsModel
    SignalCancelledNotification
    SignalCloseContract
    SignalClosedNotification
    SignalInfoContract
    SignalInfoNotification
    SignalOpenContract
    SignalOpenedNotification
    SignalScheduledNotification
    SignalSyncCloseNotification
    SignalSyncOpenNotification
    StrategyEvent
    StrategyStatisticsModel
    SyncEvent
    SyncStatisticsModel
    TickEvent
    TrailingStopCommit
    TrailingStopCommitNotification
    TrailingTakeCommit
    TrailingTakeCommitNotification
    ValidationErrorNotification
    WalkerCompleteContract
    WalkerContract
    WalkerSignalData
    WalkerStatisticsModel

    Type Aliases

    BreakevenData
    BrokerAverageBuyPayload
    BrokerBreakevenPayload
    BrokerPartialLossPayload
    BrokerPartialProfitPayload
    BrokerSignalClosePayload
    BrokerSignalOpenPayload
    BrokerTrailingStopPayload
    BrokerTrailingTakePayload
    CandleData
    CandleInterval
    ColumnConfig
    CommitPayload
    EntityId
    FrameInterval
    GlobalConfig
    ICommitRow
    IntervalData
    IPublicAction
    ISizingCalculateParams
    ISizingParams
    ISizingSchema
    IStorageSignalRow
    IStrategyTickResult
    LogData
    MarkdownName
    MeasureData
    MemoryData
    MessageRole
    MessageToolCall
    NotificationData
    NotificationModel
    PartialData
    PerformanceMetricType
    RecentData
    ReportName
    RiskData
    ScheduleData
    SessionData
    SignalData
    SignalInterval
    SignalSyncContract
    StateData
    StorageData
    StrategyActionType
    StrategyCancelReason
    StrategyCloseReason
    StrategyCommitContract
    TBrokerCtor
    TDumpInstanceCtor
    TLogCtor
    TMarkdownBase
    TMemoryInstanceCtor
    TNotificationUtilsCtor
    TPersistBase
    TPersistBaseCtor
    TPersistBreakevenInstanceCtor
    TPersistCandleInstanceCtor
    TPersistIntervalInstanceCtor
    TPersistLogInstanceCtor
    TPersistMeasureInstanceCtor
    TPersistMemoryInstanceCtor
    TPersistNotificationInstanceCtor
    TPersistPartialInstanceCtor
    TPersistRecentInstanceCtor
    TPersistRiskInstanceCtor
    TPersistScheduleInstanceCtor
    TPersistSessionInstanceCtor
    TPersistSignalInstanceCtor
    TPersistStateInstanceCtor
    TPersistStorageInstanceCtor
    TRecentUtilsCtor
    TReportBase
    TSessionInstanceCtor
    TStateInstanceCtor
    TStorageUtilsCtor
    WalkerMetric

    Variables

    Backtest
    Breakeven
    Broker
    Cache
    Constant
    Dump
    Exchange
    ExecutionContextService
    Heat
    HighestProfit
    Interval
    lib
    Live
    Log
    Lookup
    Markdown
    MarkdownWriter
    MaxDrawdown
    Memory
    MemoryBacktest
    MemoryLive
    MethodContextService
    Notification
    NotificationBacktest
    NotificationLive
    Partial
    PersistBreakevenAdapter
    PersistCandleAdapter
    PersistIntervalAdapter
    PersistLogAdapter
    PersistMeasureAdapter
    PersistMemoryAdapter
    PersistNotificationAdapter
    PersistPartialAdapter
    PersistRecentAdapter
    PersistRiskAdapter
    PersistScheduleAdapter
    PersistSessionAdapter
    PersistSignalAdapter
    PersistStateAdapter
    PersistStorageAdapter
    PositionSize
    Recent
    RecentBacktest
    RecentLive
    Reflect
    Report
    ReportWriter
    Risk
    Schedule
    Session
    SessionBacktest
    SessionLive
    State
    StateBacktest
    StateLive
    Storage
    StorageBacktest
    StorageLive
    Strategy
    Sync
    System
    Walker

    Functions

    addActionSchema
    addExchangeSchema
    addFrameSchema
    addRiskSchema
    addSizingSchema
    addStrategySchema
    addWalkerSchema
    alignToInterval
    cacheCandles
    checkCandles
    commitActivateScheduled
    commitAverageBuy
    commitBreakeven
    commitCancelScheduled
    commitClosePending
    commitPartialLoss
    commitPartialLossCost
    commitPartialProfit
    commitPartialProfitCost
    commitSignalNotify
    commitTrailingStop
    commitTrailingStopCost
    commitTrailingTake
    commitTrailingTakeCost
    createSignalState
    dumpAgentAnswer
    dumpError
    dumpJson
    dumpRecord
    dumpTable
    dumpText
    formatPrice
    formatQuantity
    get
    getActionSchema
    getAggregatedTrades
    getAveragePrice
    getBacktestTimeframe
    getBreakeven
    getCandles
    getClosePrice
    getColumns
    getConfig
    getContext
    getDate
    getDefaultColumns
    getDefaultConfig
    getEffectivePriceOpen
    getExchangeSchema
    getFrameSchema
    getLatestSignal
    getMaxDrawdownDistancePnlCost
    getMaxDrawdownDistancePnlPercentage
    getMinutesSinceLatestSignalCreated
    getMode
    getNextCandles
    getOrderBook
    getPendingSignal
    getPositionActiveMinutes
    getPositionCountdownMinutes
    getPositionDrawdownMinutes
    getPositionEffectivePrice
    getPositionEntries
    getPositionEntryOverlap
    getPositionEstimateMinutes
    getPositionHighestMaxDrawdownPnlCost
    getPositionHighestMaxDrawdownPnlPercentage
    getPositionHighestPnlCost
    getPositionHighestPnlPercentage
    getPositionHighestProfitBreakeven
    getPositionHighestProfitDistancePnlCost
    getPositionHighestProfitDistancePnlPercentage
    getPositionHighestProfitMinutes
    getPositionHighestProfitPrice
    getPositionHighestProfitTimestamp
    getPositionInvestedCost
    getPositionInvestedCount
    getPositionLevels
    getPositionMaxDrawdownMinutes
    getPositionMaxDrawdownPnlCost
    getPositionMaxDrawdownPnlPercentage
    getPositionMaxDrawdownPrice
    getPositionMaxDrawdownTimestamp
    getPositionPartialOverlap
    getPositionPartials
    getPositionPnlCost
    getPositionPnlPercent
    getPositionWaitingMinutes
    getRawCandles
    getRiskSchema
    getScheduledSignal
    getSessionData
    getSignalState
    getSizingSchema
    getStrategySchema
    getSymbol
    getTimestamp
    getTotalClosed
    getTotalCostClosed
    getTotalPercentClosed
    getWalkerSchema
    hasNoPendingSignal
    hasNoScheduledSignal
    hasTradeContext
    intervalStepMs
    investedCostToPercent
    listenActivePing
    listenActivePingOnce
    listenBacktestProgress
    listenBreakevenAvailable
    listenBreakevenAvailableOnce
    listenDoneBacktest
    listenDoneBacktestOnce
    listenDoneLive
    listenDoneLiveOnce
    listenDoneWalker
    listenDoneWalkerOnce
    listenError
    listenExit
    listenHighestProfit
    listenHighestProfitOnce
    listenIdlePing
    listenIdlePingOnce
    listenMaxDrawdown
    listenMaxDrawdownOnce
    listenPartialLossAvailable
    listenPartialLossAvailableOnce
    listenPartialProfitAvailable
    listenPartialProfitAvailableOnce
    listenPerformance
    listenRisk
    listenRiskOnce
    listenSchedulePing
    listenSchedulePingOnce
    listenSignal
    listenSignalBacktest
    listenSignalBacktestOnce
    listenSignalLive
    listenSignalLiveOnce
    listenSignalNotify
    listenSignalNotifyOnce
    listenSignalOnce
    listenStrategyCommit
    listenStrategyCommitOnce
    listenSync
    listenSyncOnce
    listenValidation
    listenWalker
    listenWalkerComplete
    listenWalkerOnce
    listenWalkerProgress
    listExchangeSchema
    listFrameSchema
    listMemory
    listRiskSchema
    listSizingSchema
    listStrategySchema
    listWalkerSchema
    overrideActionSchema
    overrideExchangeSchema
    overrideFrameSchema
    overrideRiskSchema
    overrideSizingSchema
    overrideStrategySchema
    overrideWalkerSchema
    parseArgs
    percentDiff
    percentToCloseCost
    percentValue
    readMemory
    removeMemory
    roundTicks
    runInMockContext
    searchMemory
    set
    setColumns
    setConfig
    setLogger
    setSessionData
    setSignalState
    shutdown
    slPercentShiftToPrice
    slPriceToPercentShift
    stopStrategy
    toProfitLossDto
    tpPercentShiftToPrice
    tpPriceToPercentShift
    validate
    validateCommonSignal
    validatePendingSignal
    validateScheduledSignal
    validateSignal
    waitForCandle
    waitForReady
    warmCandles
    writeMemory
    +types | backtest-kit

    Module types

    Namespaces

    emitters

    Classes

    ActionBase
    BrokerBase
    MarkdownFileBase
    MarkdownFolderBase
    MemoryBacktestAdapter
    MemoryLiveAdapter
    Performance
    PersistBase
    PersistBreakevenInstance
    PersistCandleInstance
    PersistIntervalInstance
    PersistLogInstance
    PersistMeasureInstance
    PersistMemoryInstance
    PersistNotificationInstance
    PersistPartialInstance
    PersistRecentInstance
    PersistRiskInstance
    PersistScheduleInstance
    PersistSessionInstance
    PersistSignalInstance
    PersistStateInstance
    PersistStorageInstance
    Position
    ReportBase
    StateBacktestAdapter
    StateLiveAdapter

    Interfaces

    ActivateScheduledCommit
    ActivateScheduledCommitNotification
    ActivePingContract
    AfterEndContract
    AverageBuyCommit
    AverageBuyCommitNotification
    BacktestStatisticsModel
    BeforeStartContract
    BreakevenAvailableNotification
    BreakevenCommit
    BreakevenCommitNotification
    BreakevenContract
    BreakevenEvent
    BreakevenStatisticsModel
    CancelScheduledCommit
    CancelScheduledCommitNotification
    ClosePendingCommit
    ClosePendingCommitNotification
    ColumnModel
    CriticalErrorNotification
    CronEntry
    CronHandle
    DoneContract
    HeatmapStatisticsModel
    HighestProfitContract
    HighestProfitEvent
    HighestProfitStatisticsModel
    IActionSchema
    IActivateScheduledCommitRow
    IAggregatedTradeData
    IBidData
    IBreakevenCommitRow
    IBroker
    ICandleData
    IdlePingContract
    IDumpContext
    IDumpInstance
    IExchangeSchema
    IFrameSchema
    IHeatmapRow
    ILog
    ILogEntry
    ILogger
    IMarkdownDumpOptions
    IMemoryInstance
    InfoErrorNotification
    INotificationUtils
    IOrderBookData
    IPartialLossCommitRow
    IPartialProfitCommitRow
    IPersistBase
    IPersistBreakevenInstance
    IPersistCandleInstance
    IPersistIntervalInstance
    IPersistLogInstance
    IPersistMeasureInstance
    IPersistMemoryInstance
    IPersistNotificationInstance
    IPersistPartialInstance
    IPersistRecentInstance
    IPersistRiskInstance
    IPersistScheduleInstance
    IPersistSessionInstance
    IPersistSignalInstance
    IPersistStateInstance
    IPersistStorageInstance
    IPositionSizeATRParams
    IPositionSizeFixedPercentageParams
    IPositionSizeKellyParams
    IPublicCandleData
    IPublicSignalRow
    IRecentUtils
    IReportDumpOptions
    IRiskActivePosition
    IRiskCheckArgs
    IRiskSchema
    IRiskSignalRow
    IRiskValidation
    IRiskValidationFn
    IRiskValidationPayload
    IScheduledSignalCancelRow
    IScheduledSignalRow
    ISessionInstance
    ISignalDto
    ISignalIntervalDto
    ISignalRow
    ISizingCalculateParamsATR
    ISizingCalculateParamsFixedPercentage
    ISizingCalculateParamsKelly
    ISizingParamsATR
    ISizingParamsFixedPercentage
    ISizingParamsKelly
    ISizingSchemaATR
    ISizingSchemaFixedPercentage
    ISizingSchemaKelly
    IStateInstance
    IStorageUtils
    IStrategyPnL
    IStrategyResult
    IStrategySchema
    IStrategyTickResultActive
    IStrategyTickResultCancelled
    IStrategyTickResultClosed
    IStrategyTickResultIdle
    IStrategyTickResultOpened
    IStrategyTickResultScheduled
    IStrategyTickResultWaiting
    ITrailingStopCommitRow
    ITrailingTakeCommitRow
    IWalkerResults
    IWalkerSchema
    IWalkerStrategyResult
    LiveStatisticsModel
    MaxDrawdownContract
    MaxDrawdownEvent
    MaxDrawdownStatisticsModel
    MessageModel
    MetricStats
    PartialEvent
    PartialLossAvailableNotification
    PartialLossCommit
    PartialLossCommitNotification
    PartialLossContract
    PartialProfitAvailableNotification
    PartialProfitCommit
    PartialProfitCommitNotification
    PartialProfitContract
    PartialStatisticsModel
    PerformanceContract
    PerformanceStatisticsModel
    ProgressBacktestContract
    ProgressWalkerContract
    RiskContract
    RiskEvent
    RiskRejectionNotification
    RiskStatisticsModel
    ScheduledEvent
    SchedulePingContract
    ScheduleStatisticsModel
    SignalCancelledNotification
    SignalCloseContract
    SignalClosedNotification
    SignalInfoContract
    SignalInfoNotification
    SignalOpenContract
    SignalOpenedNotification
    SignalScheduledNotification
    SignalSyncCloseNotification
    SignalSyncOpenNotification
    StrategyEvent
    StrategyStatisticsModel
    SyncEvent
    SyncStatisticsModel
    TickEvent
    TrailingStopCommit
    TrailingStopCommitNotification
    TrailingTakeCommit
    TrailingTakeCommitNotification
    ValidationErrorNotification
    WalkerCompleteContract
    WalkerContract
    WalkerSignalData
    WalkerStatisticsModel

    Type Aliases

    BreakevenData
    BrokerAverageBuyPayload
    BrokerBreakevenPayload
    BrokerPartialLossPayload
    BrokerPartialProfitPayload
    BrokerSignalClosePayload
    BrokerSignalOpenPayload
    BrokerTrailingStopPayload
    BrokerTrailingTakePayload
    CandleData
    CandleInterval
    ColumnConfig
    CommitPayload
    CronCallback
    EntityId
    FrameInterval
    GlobalConfig
    ICommitRow
    IntervalData
    IPublicAction
    ISizingCalculateParams
    ISizingParams
    ISizingSchema
    IStorageSignalRow
    IStrategyTickResult
    LogData
    MarkdownName
    MeasureData
    MemoryData
    MessageRole
    MessageToolCall
    NotificationData
    NotificationModel
    PartialData
    PerformanceMetricType
    RecentData
    ReportName
    RiskData
    ScheduleData
    SessionData
    SignalData
    SignalInterval
    SignalSyncContract
    StateData
    StorageData
    StrategyActionType
    StrategyCancelReason
    StrategyCloseReason
    StrategyCommitContract
    TBrokerCtor
    TDumpInstanceCtor
    TLogCtor
    TMarkdownBase
    TMemoryInstanceCtor
    TNotificationUtilsCtor
    TPersistBase
    TPersistBaseCtor
    TPersistBreakevenInstanceCtor
    TPersistCandleInstanceCtor
    TPersistIntervalInstanceCtor
    TPersistLogInstanceCtor
    TPersistMeasureInstanceCtor
    TPersistMemoryInstanceCtor
    TPersistNotificationInstanceCtor
    TPersistPartialInstanceCtor
    TPersistRecentInstanceCtor
    TPersistRiskInstanceCtor
    TPersistScheduleInstanceCtor
    TPersistSessionInstanceCtor
    TPersistSignalInstanceCtor
    TPersistStateInstanceCtor
    TPersistStorageInstanceCtor
    TRecentUtilsCtor
    TReportBase
    TSessionInstanceCtor
    TStateInstanceCtor
    TStorageUtilsCtor
    WalkerMetric

    Variables

    Backtest
    Breakeven
    Broker
    Cache
    Constant
    Cron
    Dump
    Exchange
    ExecutionContextService
    Heat
    HighestProfit
    Interval
    lib
    Live
    Log
    Lookup
    Markdown
    MarkdownWriter
    MaxDrawdown
    Memory
    MemoryBacktest
    MemoryLive
    MethodContextService
    Notification
    NotificationBacktest
    NotificationLive
    Partial
    PersistBreakevenAdapter
    PersistCandleAdapter
    PersistIntervalAdapter
    PersistLogAdapter
    PersistMeasureAdapter
    PersistMemoryAdapter
    PersistNotificationAdapter
    PersistPartialAdapter
    PersistRecentAdapter
    PersistRiskAdapter
    PersistScheduleAdapter
    PersistSessionAdapter
    PersistSignalAdapter
    PersistStateAdapter
    PersistStorageAdapter
    PositionSize
    Recent
    RecentBacktest
    RecentLive
    Reflect
    Report
    ReportWriter
    Risk
    Schedule
    Session
    SessionBacktest
    SessionLive
    State
    StateBacktest
    StateLive
    Storage
    StorageBacktest
    StorageLive
    Strategy
    Sync
    System
    Walker

    Functions

    addActionSchema
    addExchangeSchema
    addFrameSchema
    addRiskSchema
    addSizingSchema
    addStrategySchema
    addWalkerSchema
    alignToInterval
    beginContext
    beginTime
    cacheCandles
    checkCandles
    commitActivateScheduled
    commitAverageBuy
    commitBreakeven
    commitCancelScheduled
    commitClosePending
    commitPartialLoss
    commitPartialLossCost
    commitPartialProfit
    commitPartialProfitCost
    commitSignalNotify
    commitTrailingStop
    commitTrailingStopCost
    commitTrailingTake
    commitTrailingTakeCost
    createSignalState
    dumpAgentAnswer
    dumpError
    dumpJson
    dumpRecord
    dumpTable
    dumpText
    formatPrice
    formatQuantity
    get
    getActionSchema
    getAggregatedTrades
    getAveragePrice
    getBacktestTimeframe
    getBreakeven
    getCandles
    getClosePrice
    getColumns
    getConfig
    getContext
    getDate
    getDefaultColumns
    getDefaultConfig
    getEffectivePriceOpen
    getExchangeSchema
    getFrameSchema
    getLatestSignal
    getMaxDrawdownDistancePnlCost
    getMaxDrawdownDistancePnlPercentage
    getMinutesSinceLatestSignalCreated
    getMode
    getNextCandles
    getOrderBook
    getPendingSignal
    getPositionActiveMinutes
    getPositionCountdownMinutes
    getPositionDrawdownMinutes
    getPositionEffectivePrice
    getPositionEntries
    getPositionEntryOverlap
    getPositionEstimateMinutes
    getPositionHighestMaxDrawdownPnlCost
    getPositionHighestMaxDrawdownPnlPercentage
    getPositionHighestPnlCost
    getPositionHighestPnlPercentage
    getPositionHighestProfitBreakeven
    getPositionHighestProfitDistancePnlCost
    getPositionHighestProfitDistancePnlPercentage
    getPositionHighestProfitMinutes
    getPositionHighestProfitPrice
    getPositionHighestProfitTimestamp
    getPositionInvestedCost
    getPositionInvestedCount
    getPositionLevels
    getPositionMaxDrawdownMinutes
    getPositionMaxDrawdownPnlCost
    getPositionMaxDrawdownPnlPercentage
    getPositionMaxDrawdownPrice
    getPositionMaxDrawdownTimestamp
    getPositionPartialOverlap
    getPositionPartials
    getPositionPnlCost
    getPositionPnlPercent
    getPositionWaitingMinutes
    getRawCandles
    getRiskSchema
    getScheduledSignal
    getSessionData
    getSignalState
    getSizingSchema
    getStrategySchema
    getSymbol
    getTimestamp
    getTotalClosed
    getTotalCostClosed
    getTotalPercentClosed
    getWalkerSchema
    hasNoPendingSignal
    hasNoScheduledSignal
    hasTradeContext
    intervalStepMs
    investedCostToPercent
    listenActivePing
    listenActivePingOnce
    listenAfterEnd
    listenAfterEndOnce
    listenBacktestProgress
    listenBeforeStart
    listenBeforeStartOnce
    listenBreakevenAvailable
    listenBreakevenAvailableOnce
    listenDoneBacktest
    listenDoneBacktestOnce
    listenDoneLive
    listenDoneLiveOnce
    listenDoneWalker
    listenDoneWalkerOnce
    listenError
    listenExit
    listenHighestProfit
    listenHighestProfitOnce
    listenIdlePing
    listenIdlePingOnce
    listenMaxDrawdown
    listenMaxDrawdownOnce
    listenPartialLossAvailable
    listenPartialLossAvailableOnce
    listenPartialProfitAvailable
    listenPartialProfitAvailableOnce
    listenPerformance
    listenRisk
    listenRiskOnce
    listenSchedulePing
    listenSchedulePingOnce
    listenSignal
    listenSignalBacktest
    listenSignalBacktestOnce
    listenSignalLive
    listenSignalLiveOnce
    listenSignalNotify
    listenSignalNotifyOnce
    listenSignalOnce
    listenStrategyCommit
    listenStrategyCommitOnce
    listenSync
    listenSyncOnce
    listenValidation
    listenWalker
    listenWalkerComplete
    listenWalkerOnce
    listenWalkerProgress
    listExchangeSchema
    listFrameSchema
    listMemory
    listRiskSchema
    listSizingSchema
    listStrategySchema
    listWalkerSchema
    overrideActionSchema
    overrideExchangeSchema
    overrideFrameSchema
    overrideRiskSchema
    overrideSizingSchema
    overrideStrategySchema
    overrideWalkerSchema
    parseArgs
    percentDiff
    percentToCloseCost
    percentValue
    readMemory
    removeMemory
    roundTicks
    runInMockContext
    searchMemory
    set
    setColumns
    setConfig
    setLogger
    setSessionData
    setSignalState
    shutdown
    slPercentShiftToPrice
    slPriceToPercentShift
    stopStrategy
    toPlainString
    toProfitLossDto
    tpPercentShiftToPrice
    tpPriceToPercentShift
    validate
    validateCommonSignal
    validatePendingSignal
    validateScheduledSignal
    validateSignal
    waitForCandle
    waitForReady
    warmCandles
    writeMemory

    Type Alias BreakevenData

    BreakevenData: Record<string, IBreakevenData>

    Type for persisted breakeven data. Stores breakeven state (reached flag) for each signal ID.

    -
    +

    Type Alias CandleData

    CandleData: ICandleData

    Type for persisted candle cache data. Each candle is stored as a separate JSON file.

    -
    +

    Type Alias CandleInterval

    CandleInterval:
        | "1m"
        | "3m"
        | "5m"
        | "15m"
        | "30m"
        | "1h"
        | "2h"
        | "4h"
        | "6h"
        | "8h"
        | "1d"

    Candle time interval for fetching historical data.

    -
    +

    Type Alias ColumnConfig

    ColumnConfig: typeof COLUMN_CONFIG

    Type for the column configuration object.

    -
    +

    Type Alias CronCallback

    CronCallback: (
        symbol: string,
        when: Date,
        backtest: boolean,
    ) => void | Promise<void>

    Callback signature for a cron entry handler.

    +

    Invocation cardinality depends on entry.symbols (see CronEntry):

    +
      +
    • Global mode (symbols empty/undefined): invoked once per aligned +boundary across all parallel backtests. The first symbol to reach the +boundary opens the slot and runs the handler; others await the same +promise.
    • +
    • Fan-out mode (symbols non-empty): invoked once per aligned +boundary per whitelisted symbol. Each symbol has its own slot.
    • +
    +

    Type declaration

      • (symbol: string, when: Date, backtest: boolean): void | Promise<void>
      • Parameters

        • symbol: string

          In global mode: the symbol of the backtest that first +reached the boundary (the singleshot "winner"). In fan-out mode: the +whitelisted symbol whose tick produced this invocation.

          +
        • when: Date

          The aligned virtual time at which the entry fires. +Already aligned to the entry's interval boundary (e.g. for 1h, +minutes/seconds/ms are zero). In fire-once mode this is the tick time +aligned to the 1-minute boundary (the base alignment _tick applies +to every incoming tick), not raw wall-clock with sub-second precision.

          +
        • backtest: boolean

          Execution-mode flag taken from the originating lifecycle +event (beforeStart / idlePing / activePing / schedulePing, +wired by Cron.enable()). true for backtest runs, false for live. +The value reflects the opening tick that won the singleshot for +this slot — all parallel awaiters of the same slot observe the same +value, even if a later concurrent tick carried a different one.

          +

        Returns void | Promise<void>

    + + + + + + + + + diff --git a/types/types.EntityId.html b/types/types.EntityId.html index 29a2c3931ac932be64804f741c521b8ef7477bda..3af6d0353ed0d62a72949a6e51423e46f77cf725 100644 --- a/types/types.EntityId.html +++ b/types/types.EntityId.html @@ -1,5 +1,5 @@ EntityId | backtest-kit

    Type Alias EntityId

    EntityId: string | number

    Entity identifier - string or number.

    -
    +

    Type Alias GlobalConfig

    GlobalConfig: typeof GLOBAL_CONFIG

    Type for global configuration object.

    -
    +

    Type Alias ICommitRow

    ICommitRow:
        | IPartialProfitCommitRow
        | IPartialLossCommitRow
        | IBreakevenCommitRow
        | IAverageBuyCommitRow
        | ITrailingStopCommitRow
        | ITrailingTakeCommitRow
        | IActivateScheduledCommitRow

    Discriminated union of all queued commit events. These are stored in _commitQueue and processed in tick()/backtest().

    -
    +

    Type Alias ISizingCalculateParams

    Discriminated union for position size calculation parameters. Type-safe parameters based on sizing method.

    -
    +

    Type Alias ISizingParams

    ISizingParams:
        | ISizingParamsFixedPercentage
        | ISizingParamsKelly
        | ISizingParamsATR

    Discriminated union for sizing parameters passed to ClientSizing constructor. Extends ISizingSchema with logger instance for internal logging.

    -
    +

    Type Alias ISizingSchema

    ISizingSchema:
        | ISizingSchemaFixedPercentage
        | ISizingSchemaKelly
        | ISizingSchemaATR

    Discriminated union for sizing schemas. Type-safe configuration based on sizing method.

    -
    +

    Type Alias IStorageSignalRow

    IStorageSignalRow:
        | IStorageSignalRowOpened
        | IStorageSignalRowScheduled
        | IStorageSignalRowClosed
        | IStorageSignalRowCancelled

    Discriminated union of storage signal rows. Use type guards: row.status === "closed" for type-safe access to pnl.

    -
    +

    Type Alias IStrategyTickResult

    Discriminated union of all tick results. Use type guards: result.action === "closed" for type safety.

    -
    +

    Type Alias IntervalData

    IntervalData: { data: unknown; id: string; removed: boolean; when: Date }

    Interval.file data type stored in persistence layer.

    -

    Type declaration

    • data: unknown
    • id: string
    • removed: boolean
    • when: Date
    +

    Type declaration

    • data: unknown
    • id: string
    • removed: boolean
    • when: Date

    Type Alias LogData

    LogData: ILogEntry[]

    Type for persisted log data. Each log entry is stored as a separate file keyed by its id.

    -
    +

    Type Alias MarkdownName

    MarkdownName: keyof IMarkdownTarget

    Union type of all valid markdown report names. Used for type-safe identification of markdown services.

    -
    +

    Type Alias MeasureData

    MeasureData: { data: unknown; id: string; removed: boolean }

    Cache.file data type stored in persistence layer.

    -

    Type declaration

    • data: unknown
    • id: string
    • removed: boolean
    +

    Type declaration

    • data: unknown
    • id: string
    • removed: boolean

    Type Alias MemoryData

    MemoryData: {
        data: object;
        index: string;
        priority: number;
        removed: boolean;
        when: number;
    }

    Type for persisted memory entry data. Each memory entry is an arbitrary JSON-serializable object.

    -

    Type declaration

    • data: object
    • index: string
    • priority: number
    • removed: boolean
    • when: number
    +

    Type declaration

    • data: object
    • index: string
    • priority: number
    • removed: boolean
    • when: number

    Type Alias MessageRole

    MessageRole: "assistant" | "system" | "tool" | "user"

    Role of the message sender in an LLM chat history.

    -
    +

    Type Alias NotificationData

    NotificationData: NotificationModel[]

    Type for persisted notification data. Each notification is stored as a separate file keyed by its id.

    -
    +

    Type Alias PartialData

    PartialData: Record<string, IPartialData>

    Type for persisted partial data. Stores profit and loss levels as arrays for JSON serialization.

    -
    +

    Type Alias RecentData

    RecentData: IPublicSignalRow | null

    Type for persisted recent signal data. Stores the latest active signal per context key.

    -
    +

    Type Alias ReportName

    ReportName: keyof IReportTarget

    Union type of all valid report names. Used for type-safe identification of report services.

    -
    +

    Type Alias RiskData

    RiskData: [string, IRiskActivePosition][]

    Type for persisted risk positions data. Stores Map entries as array of [key, value] tuples for JSON serialization.

    -
    +

    Type Alias ScheduleData

    ScheduleData: IScheduledSignalRow | null

    Type for persisted scheduled signal data. Contains nullable scheduled signal for atomic updates.

    -
    +

    Type Alias SessionData

    SessionData: { data: object | null; id: string; when: number }

    Session data structure for session persistence. Each session is identified by a unique id and contains an arbitrary JSON-serializable data object.

    -

    Type declaration

    • data: object | null
    • id: string
    • when: number
    +

    Type declaration

    • data: object | null
    • id: string
    • when: number

    Type Alias SignalData

    SignalData: ISignalRow | null

    Signal data stored in persistence layer. Contains nullable signal for atomic updates.

    -
    +

    Type Alias SignalInterval

    SignalInterval: "1m" | "3m" | "5m" | "15m" | "30m" | "1h"

    Signal generation interval for throttling. Enforces minimum time between getSignal calls.

    -
    +

    Type Alias StateData

    StateData: { data: object; id: string; when: number }

    Type for persisted state entry data. Wraps an arbitrary JSON-serializable object with a unique id.

    -

    Type declaration

    • data: object
    • id: string
    • when: number
    +

    Type declaration

    • data: object
    • id: string
    • when: number

    Type Alias StorageData

    StorageData: IStorageSignalRow[]

    Type for persisted signal storage data. Each signal is stored as a separate file keyed by its id.

    -
    +

    Type Alias StrategyActionType

    StrategyActionType:
        | "cancel-scheduled"
        | "close-pending"
        | "partial-profit"
        | "partial-loss"
        | "trailing-stop"
        | "trailing-take"
        | "breakeven"
        | "activate-scheduled"
        | "average-buy"

    Action types for strategy events. Represents all possible strategy management actions.

    -
    +

    Type Alias StrategyCancelReason

    StrategyCancelReason: "timeout" | "price_reject" | "user"

    Reason why scheduled signal was cancelled. Used in discriminated union for type-safe handling.

    -
    +

    Type Alias StrategyCloseReason

    StrategyCloseReason: "time_expired" | "take_profit" | "stop_loss" | "closed"

    Reason why signal was closed. Used in discriminated union for type-safe handling.

    -
    +

    Type Alias TDumpInstanceCtor

    TDumpInstanceCtor: new (
        signalId: string,
        bucketName: string,
        backtest: boolean,
    ) => IDumpInstance

    Constructor type for dump instance implementations. Used for swapping backends via DumpAdapter.useDumpAdapter().

    -
    +

    Type Alias TLogCtor

    TLogCtor: new () => Partial<ILog>

    Constructor type for log adapters. Used for custom log implementations.

    -
    +

    Type Alias TMemoryInstanceCtor

    TMemoryInstanceCtor: new (
        signalId: string,
        bucketName: string,
    ) => IMemoryInstance

    Constructor type for memory instance implementations. Used for swapping backends via MemoryBacktestAdapter / MemoryLiveAdapter.

    -
    +

    Type Alias TNotificationUtilsCtor

    TNotificationUtilsCtor: new () => INotificationUtils

    Constructor type for notification adapters. Used for custom notification implementations.

    -
    +

    Type Alias TPersistBase

    TPersistBase: InstanceType<typeof PersistBase>

    Type helper for PersistBase instance.

    -
    +

    Type Alias TPersistBaseCtor<EntityName, Entity>

    TPersistBaseCtor: new (
        entityName: EntityName,
        baseDir: string,
    ) => IPersistBase<Entity>

    Constructor type for PersistBase. Used for custom persistence adapters.

    -

    Type Parameters

    • EntityName extends string = string
    • Entity extends IEntity | null = IEntity
    +

    Type Parameters

    • EntityName extends string = string
    • Entity extends IEntity | null = IEntity

    Type Alias TPersistBreakevenInstanceCtor

    TPersistBreakevenInstanceCtor: new (
        symbol: string,
        strategyName: StrategyName,
        exchangeName: ExchangeName,
    ) => IPersistBreakevenInstance

    Constructor type for IPersistBreakevenInstance. Used by PersistBreakevenUtils.usePersistBreakevenAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistCandleInstanceCtor

    TPersistCandleInstanceCtor: new (
        symbol: string,
        interval: CandleInterval,
        exchangeName: ExchangeName,
    ) => IPersistCandleInstance

    Constructor type for IPersistCandleInstance. Used by PersistCandleUtils.usePersistCandleAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistIntervalInstanceCtor

    TPersistIntervalInstanceCtor: new (bucket: string) => IPersistIntervalInstance

    Constructor type for IPersistIntervalInstance. Used by PersistIntervalUtils.usePersistIntervalAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistLogInstanceCtor

    TPersistLogInstanceCtor: new () => IPersistLogInstance

    Constructor type for IPersistLogInstance. Used by PersistLogUtils.usePersistLogAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistMeasureInstanceCtor

    TPersistMeasureInstanceCtor: new (bucket: string) => IPersistMeasureInstance

    Constructor type for IPersistMeasureInstance. Used by PersistMeasureUtils.usePersistMeasureAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistMemoryInstanceCtor

    TPersistMemoryInstanceCtor: new (
        signalId: string,
        bucketName: string,
    ) => IPersistMemoryInstance

    Constructor type for IPersistMemoryInstance. Used by PersistMemoryUtils.usePersistMemoryAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistNotificationInstanceCtor

    TPersistNotificationInstanceCtor: new (
        backtest: boolean,
    ) => IPersistNotificationInstance

    Constructor type for IPersistNotificationInstance. Used by PersistNotificationUtils.usePersistNotificationAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistPartialInstanceCtor

    TPersistPartialInstanceCtor: new (
        symbol: string,
        strategyName: StrategyName,
        exchangeName: ExchangeName,
    ) => IPersistPartialInstance

    Constructor type for IPersistPartialInstance. Used by PersistPartialUtils.usePersistPartialAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistRecentInstanceCtor

    TPersistRecentInstanceCtor: new (
        symbol: string,
        strategyName: StrategyName,
        exchangeName: ExchangeName,
        frameName: FrameName,
        backtest: boolean,
    ) => IPersistRecentInstance

    Constructor type for IPersistRecentInstance. Used by PersistRecentUtils.usePersistRecentAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistRiskInstanceCtor

    TPersistRiskInstanceCtor: new (
        riskName: RiskName,
        exchangeName: ExchangeName,
    ) => IPersistRiskInstance

    Constructor type for IPersistRiskInstance. Used by PersistRiskUtils.usePersistRiskAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistScheduleInstanceCtor

    TPersistScheduleInstanceCtor: new (
        symbol: string,
        strategyName: StrategyName,
        exchangeName: ExchangeName,
    ) => IPersistScheduleInstance

    Constructor type for IPersistScheduleInstance. Used by PersistScheduleUtils.usePersistScheduleAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistSessionInstanceCtor

    TPersistSessionInstanceCtor: new (
        strategyName: string,
        exchangeName: string,
        frameName: string,
    ) => IPersistSessionInstance

    Constructor type for IPersistSessionInstance. Used by PersistSessionUtils.usePersistSessionAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistSignalInstanceCtor

    TPersistSignalInstanceCtor: new (
        symbol: string,
        strategyName: StrategyName,
        exchangeName: ExchangeName,
    ) => IPersistSignalInstance

    Constructor type for IPersistSignalInstance. Used by PersistSignalUtils.usePersistSignalAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistStateInstanceCtor

    TPersistStateInstanceCtor: new (
        signalId: string,
        bucketName: string,
    ) => IPersistStateInstance

    Constructor type for IPersistStateInstance. Used by PersistStateUtils.usePersistStateAdapter() to register custom adapters.

    -
    +

    Type Alias TPersistStorageInstanceCtor

    TPersistStorageInstanceCtor: new (backtest: boolean) => IPersistStorageInstance

    Constructor type for IPersistStorageInstance. Used by PersistStorageUtils.usePersistStorageAdapter() to register custom adapters.

    -
    +

    Type Alias TRecentUtilsCtor

    TRecentUtilsCtor: new () => IRecentUtils

    Constructor type for recent signal storage adapters.

    -
    +

    Type Alias TSessionInstanceCtor

    TSessionInstanceCtor: new (
        symbol: string,
        strategyName: StrategyName,
        exchangeName: ExchangeName,
        frameName: FrameName,
        backtest: boolean,
    ) => ISessionInstance

    Constructor type for session instance implementations. Used for swapping backends via SessionBacktestAdapter / SessionLiveAdapter.

    -
    +

    Type Alias TStateInstanceCtor

    TStateInstanceCtor: new (
        initialValue: object,
        signalId: string,
        bucketName: string,
    ) => IStateInstance

    Constructor type for state instance implementations. Used for swapping backends via StateBacktestAdapter / StateLiveAdapter.

    -
    +

    Type Alias TStorageUtilsCtor

    TStorageUtilsCtor: new () => IStorageUtils

    Constructor type for storage adapters. Used for custom storage implementations.

    -
    +

    Type Alias WalkerMetric

    WalkerMetric:
        | "sharpeRatio"
        | "annualizedSharpeRatio"
        | "winRate"
        | "totalPnl"
        | "certaintyRatio"
        | "avgPnl"
        | "expectedYearlyReturns"

    Optimization metric for comparing strategies. Higher values are always better (metric is maximized).

    -
    +

    Variable CronConst

    Cron: CronUtils

    Singleton instance of CronUtils for registering periodic tasks +coordinated across parallel Backtest.background runs.

    +
    import { Cron } from "backtest-kit";

    Cron.register({
    name: "tg-parser",
    interval: "1h",
    handler: async (symbol, when, backtest) => { ... },
    }); +
    + +
    + + + + + + + + + diff --git a/variables/types.Dump.html b/variables/types.Dump.html index 4a269303a908b2074360a6e2f55fcd2babfdcfe8..e8ce57fcfb5941e72072ce33835240a628090061 100644 --- a/variables/types.Dump.html +++ b/variables/types.Dump.html @@ -1,4 +1,4 @@ -Dump | backtest-kit

    Variable DumpConst

    Dump: DumpAdapter
    +Dump | backtest-kit

    Variable DumpConst

    Dump: DumpAdapter

    Variable HighestProfitConst

    HighestProfit: HighestProfitUtils

    Global singleton instance of HighestProfitUtils.

    -
    +

    Variable LogConst

    Log: LogAdapter

    Global singleton instance of LogAdapter. Provides unified log management with pluggable backends.

    -
    +

    Variable LookupConst

    Lookup: LookupUtils

    Process-wide singleton instance of LookupUtils. Imported by Backtest, Live, WalkerLogicPrivateService (registration sites) and by Candle (read-only consumer via isParallel).

    -
    +

    Variable MarkdownConst

    Markdown: MarkdownAdapter

    Global singleton instance of MarkdownAdapter. Provides markdown report generation with pluggable storage backends.

    -
    +

    Variable MarkdownWriterConst

    MarkdownWriter: MarkdownWriterAdapter
    +MarkdownWriter | backtest-kit

    Variable MarkdownWriterConst

    MarkdownWriter: MarkdownWriterAdapter

    Variable MaxDrawdownConst

    MaxDrawdown: MaxDrawdownUtils

    Global singleton instance of MaxDrawdownUtils.

    -
    +

    Variable MemoryConst

    Memory: MemoryAdapter

    Global singleton instance of MemoryAdapter. Provides unified memory management for backtest and live trading.

    -
    +

    Variable MemoryBacktestConst

    MemoryBacktest: MemoryBacktestAdapter

    Global singleton instance of MemoryBacktestAdapter. Provides backtest memory storage with pluggable backends.

    -
    +

    Variable MemoryLiveConst

    MemoryLive: MemoryLiveAdapter

    Global singleton instance of MemoryLiveAdapter. Provides live trading memory storage with pluggable backends.

    -
    +

    Variable NotificationConst

    Notification: NotificationAdapter

    Global singleton instance of NotificationAdapter. Provides unified notification management for backtest and live trading.

    -
    +

    Variable NotificationBacktestConst

    NotificationBacktest: NotificationBacktestAdapter

    Global singleton instance of NotificationBacktestAdapter. Provides backtest notification storage with pluggable backends.

    -
    +

    Variable NotificationLiveConst

    NotificationLive: NotificationLiveAdapter

    Global singleton instance of NotificationLiveAdapter. Provides live trading notification storage with pluggable backends.

    -
    +

    Variable PersistIntervalAdapterConst

    PersistIntervalAdapter: PersistIntervalUtils

    Global singleton instance of PersistIntervalUtils. Used by Interval.file for persistent once-per-interval signal firing.

    -
    +

    Variable PersistLogAdapterConst

    PersistLogAdapter: PersistLogUtils

    Global singleton instance of PersistLogUtils. Used by LogPersistUtils for log entry persistence.

    -
    +

    Variable PersistMeasureAdapterConst

    PersistMeasureAdapter: PersistMeasureUtils

    Global singleton instance of PersistMeasureUtils. Used by Cache.file for persistent caching of external API responses.

    -
    +

    Variable PersistNotificationAdapterConst

    PersistNotificationAdapter: PersistNotificationUtils

    Global singleton instance of PersistNotificationUtils. Used by NotificationPersistLiveUtils/NotificationPersistBacktestUtils for notification persistence.

    -
    +

    Variable PersistRecentAdapterConst

    PersistRecentAdapter: PersistRecentUtils

    Global singleton instance of PersistRecentUtils. Used by RecentPersistBacktestUtils/RecentPersistLiveUtils for recent signal persistence.

    -
    +

    Variable PersistSessionAdapterConst

    PersistSessionAdapter: PersistSessionUtils

    Global singleton instance of PersistSessionUtils. Used by SessionPersistInstance for crash-safe session persistence.

    -
    +

    Variable PersistStateAdapterConst

    PersistStateAdapter: PersistStateUtils

    Global singleton instance of PersistStateUtils. Used by StatePersistInstance for crash-safe state persistence.

    -
    +

    Variable PersistStorageAdapterConst

    PersistStorageAdapter: PersistStorageUtils

    Global singleton instance of PersistStorageUtils. Used by SignalLiveUtils for signal storage persistence.

    -
    +

    Variable PositionSizeConst

    PositionSize: typeof PositionSizeUtils
    +PositionSize | backtest-kit

    Variable PositionSizeConst

    PositionSize: typeof PositionSizeUtils

    Variable RecentConst

    Recent: RecentAdapter

    Global singleton instance of RecentAdapter. Provides unified recent signal management for backtest and live trading.

    -
    +

    Variable RecentBacktestConst

    RecentBacktest: RecentBacktestAdapter

    Global singleton instance of RecentBacktestAdapter. Provides backtest recent signal storage with pluggable backends.

    -
    +

    Variable RecentLiveConst

    RecentLive: RecentLiveAdapter

    Global singleton instance of RecentLiveAdapter. Provides live trading recent signal storage with pluggable backends.

    -
    +

    Variable ReportConst

    Report: ReportAdapter

    Global singleton instance of ReportAdapter. Provides JSONL event logging with pluggable storage backends.

    -
    +

    Variable ReportWriterConst

    ReportWriter: ReportWriterAdapter
    +ReportWriter | backtest-kit

    Variable ReportWriterConst

    ReportWriter: ReportWriterAdapter

    Variable SessionConst

    Session: SessionAdapter

    Global singleton instance of SessionAdapter. Provides unified session management for backtest and live trading.

    -
    +

    Variable SessionBacktestConst

    SessionBacktest: SessionBacktestAdapter

    Global singleton instance of SessionBacktestAdapter. Provides backtest session storage with pluggable backends.

    -
    +

    Variable SessionLiveConst

    SessionLive: SessionLiveAdapter

    Global singleton instance of SessionLiveAdapter. Provides live trading session storage with pluggable backends.

    -
    +

    Variable StateConst

    State: StateAdapter

    Global singleton instance of StateAdapter. Provides unified state management for backtest and live trading.

    -
    +

    Variable StateBacktestConst

    StateBacktest: StateBacktestAdapter

    Global singleton instance of StateBacktestAdapter. Provides backtest state storage with pluggable backends.

    -
    +

    Variable StateLiveConst

    StateLive: StateLiveAdapter

    Global singleton instance of StateLiveAdapter. Provides live trading state storage with pluggable backends.

    -
    +

    Variable StorageConst

    Storage: StorageAdapter

    Global singleton instance of StorageAdapter. Provides unified signal storage management for backtest and live trading.

    -
    +

    Variable StorageBacktestConst

    StorageBacktest: StorageBacktestAdapter

    Global singleton instance of StorageBacktestAdapter. Provides backtest signal storage with pluggable backends.

    -
    +

    Variable StorageLiveConst

    StorageLive: StorageLiveAdapter

    Global singleton instance of StorageLiveAdapter. Provides live trading signal storage with pluggable backends.

    -
    +

    Variable SystemConst

    System: SystemUtils
    +System | backtest-kit

    Variable SystemConst

    System: SystemUtils

    Variable activePingSubjectConst

    activePingSubject: typeof activePingSubject
    +activePingSubject | backtest-kit

    Variable activePingSubjectConst

    activePingSubject: typeof activePingSubject

    Variable afterEndSubjectConst

    afterEndSubject: typeof afterEndSubject
    + + + + + + + + + diff --git a/variables/types.emitters.backtestScheduleOpenSubject.html b/variables/types.emitters.backtestScheduleOpenSubject.html index edb4e1cc7f80fd5f13d1590d8b721290ca59fd58..0765b3435a2d88bcf80e68c256c61009740c9d3a 100644 --- a/variables/types.emitters.backtestScheduleOpenSubject.html +++ b/variables/types.emitters.backtestScheduleOpenSubject.html @@ -1,4 +1,4 @@ -backtestScheduleOpenSubject | backtest-kit

    Variable backtestScheduleOpenSubjectConst

    backtestScheduleOpenSubject: typeof backtestScheduleOpenSubject
    +backtestScheduleOpenSubject | backtest-kit

    Variable backtestScheduleOpenSubjectConst

    backtestScheduleOpenSubject: typeof backtestScheduleOpenSubject

    Variable beforeStartSubjectConst

    beforeStartSubject: typeof beforeStartSubject
    + + + + + + + + + diff --git a/variables/types.emitters.breakevenSubject.html b/variables/types.emitters.breakevenSubject.html index 4c2c315b9233a75ac0261eea5878db2a475daf8d..06979b6eeaf0695fa68776c9b9c53a9d7fda6156 100644 --- a/variables/types.emitters.breakevenSubject.html +++ b/variables/types.emitters.breakevenSubject.html @@ -1,4 +1,4 @@ -breakevenSubject | backtest-kit

    Variable breakevenSubjectConst

    breakevenSubject: typeof breakevenSubject
    +breakevenSubject | backtest-kit

    Variable breakevenSubjectConst

    breakevenSubject: typeof breakevenSubject

    Variable doneBacktestSubjectConst

    doneBacktestSubject: typeof doneBacktestSubject
    +doneBacktestSubject | backtest-kit

    Variable doneBacktestSubjectConst

    doneBacktestSubject: typeof doneBacktestSubject

    Variable doneLiveSubjectConst

    doneLiveSubject: typeof doneLiveSubject
    +doneLiveSubject | backtest-kit

    Variable doneLiveSubjectConst

    doneLiveSubject: typeof doneLiveSubject

    Variable doneWalkerSubjectConst

    doneWalkerSubject: typeof doneWalkerSubject
    +doneWalkerSubject | backtest-kit

    Variable doneWalkerSubjectConst

    doneWalkerSubject: typeof doneWalkerSubject

    Variable entrySubjectConst

    entrySubject: typeof entrySubject
    + + + + + + + + + diff --git a/variables/types.emitters.errorEmitter.html b/variables/types.emitters.errorEmitter.html index 515b7d8a6f0caa4388feeff399d49ece60a95680..436a6948220f9e7c38a91c6546b6064d954e1739 100644 --- a/variables/types.emitters.errorEmitter.html +++ b/variables/types.emitters.errorEmitter.html @@ -1,4 +1,4 @@ -errorEmitter | backtest-kit

    Variable errorEmitterConst

    errorEmitter: typeof errorEmitter
    +errorEmitter | backtest-kit

    Variable errorEmitterConst

    errorEmitter: typeof errorEmitter

    Variable exitEmitterConst

    exitEmitter: typeof exitEmitter
    +exitEmitter | backtest-kit

    Variable exitEmitterConst

    exitEmitter: typeof exitEmitter

    Variable highestProfitSubjectConst

    highestProfitSubject: typeof highestProfitSubject
    +highestProfitSubject | backtest-kit

    Variable highestProfitSubjectConst

    highestProfitSubject: typeof highestProfitSubject

    Variable idlePingSubjectConst

    idlePingSubject: typeof idlePingSubject
    +idlePingSubject | backtest-kit

    Variable idlePingSubjectConst

    idlePingSubject: typeof idlePingSubject

    Variable maxDrawdownSubjectConst

    maxDrawdownSubject: typeof maxDrawdownSubject
    +maxDrawdownSubject | backtest-kit

    Variable maxDrawdownSubjectConst

    maxDrawdownSubject: typeof maxDrawdownSubject

    Variable partialLossSubjectConst

    partialLossSubject: typeof partialLossSubject
    +partialLossSubject | backtest-kit

    Variable partialLossSubjectConst

    partialLossSubject: typeof partialLossSubject

    Variable partialProfitSubjectConst

    partialProfitSubject: typeof partialProfitSubject
    +partialProfitSubject | backtest-kit

    Variable partialProfitSubjectConst

    partialProfitSubject: typeof partialProfitSubject

    Variable performanceEmitterConst

    performanceEmitter: typeof performanceEmitter
    +performanceEmitter | backtest-kit

    Variable performanceEmitterConst

    performanceEmitter: typeof performanceEmitter

    Variable progressBacktestEmitterConst

    progressBacktestEmitter: typeof progressBacktestEmitter
    +progressBacktestEmitter | backtest-kit

    Variable progressBacktestEmitterConst

    progressBacktestEmitter: typeof progressBacktestEmitter

    Variable progressWalkerEmitterConst

    progressWalkerEmitter: typeof progressWalkerEmitter
    +progressWalkerEmitter | backtest-kit

    Variable progressWalkerEmitterConst

    progressWalkerEmitter: typeof progressWalkerEmitter

    Variable riskSubjectConst

    riskSubject: typeof riskSubject
    +riskSubject | backtest-kit

    Variable riskSubjectConst

    riskSubject: typeof riskSubject

    Variable schedulePingSubjectConst

    schedulePingSubject: typeof schedulePingSubject
    +schedulePingSubject | backtest-kit

    Variable schedulePingSubjectConst

    schedulePingSubject: typeof schedulePingSubject

    Variable shutdownEmitterConst

    shutdownEmitter: typeof shutdownEmitter
    +shutdownEmitter | backtest-kit

    Variable shutdownEmitterConst

    shutdownEmitter: typeof shutdownEmitter

    Variable signalBacktestEmitterConst

    signalBacktestEmitter: typeof signalBacktestEmitter
    +signalBacktestEmitter | backtest-kit

    Variable signalBacktestEmitterConst

    signalBacktestEmitter: typeof signalBacktestEmitter

    Variable signalEmitterConst

    signalEmitter: typeof signalEmitter
    +signalEmitter | backtest-kit

    Variable signalEmitterConst

    signalEmitter: typeof signalEmitter

    Variable signalLiveEmitterConst

    signalLiveEmitter: typeof signalLiveEmitter
    +signalLiveEmitter | backtest-kit

    Variable signalLiveEmitterConst

    signalLiveEmitter: typeof signalLiveEmitter

    Variable signalNotifySubjectConst

    signalNotifySubject: typeof signalNotifySubject
    +signalNotifySubject | backtest-kit

    Variable signalNotifySubjectConst

    signalNotifySubject: typeof signalNotifySubject

    Variable strategyCommitSubjectConst

    strategyCommitSubject: typeof strategyCommitSubject
    +strategyCommitSubject | backtest-kit

    Variable strategyCommitSubjectConst

    strategyCommitSubject: typeof strategyCommitSubject

    Variable syncSubjectConst

    syncSubject: typeof syncSubject
    +syncSubject | backtest-kit

    Variable syncSubjectConst

    syncSubject: typeof syncSubject

    Variable validationSubjectConst

    validationSubject: typeof validationSubject
    +validationSubject | backtest-kit

    Variable validationSubjectConst

    validationSubject: typeof validationSubject

    Variable walkerCompleteSubjectConst

    walkerCompleteSubject: typeof walkerCompleteSubject
    +walkerCompleteSubject | backtest-kit

    Variable walkerCompleteSubjectConst

    walkerCompleteSubject: typeof walkerCompleteSubject

    Variable walkerEmitterConst

    walkerEmitter: typeof walkerEmitter
    +walkerEmitter | backtest-kit

    Variable walkerEmitterConst

    walkerEmitter: typeof walkerEmitter

    Variable walkerStopSubjectConst

    walkerStopSubject: typeof walkerStopSubject
    +walkerStopSubject | backtest-kit

    Variable walkerStopSubjectConst

    walkerStopSubject: typeof walkerStopSubject

    Variable libConst

    lib: {
        actionConnectionService: ActionConnectionService;
        actionCoreService: ActionCoreService;
        actionSchemaService: ActionSchemaService;
        actionValidationService: ActionValidationService;
        backtestCommandService: BacktestCommandService;
        backtestLogicPrivateService: BacktestLogicPrivateService;
        backtestLogicPublicService: BacktestLogicPublicService;
        backtestMarkdownService: BacktestMarkdownService;
        backtestReportService: BacktestReportService;
        breakevenConnectionService: BreakevenConnectionService;
        breakevenGlobalService: BreakevenGlobalService;
        breakevenMarkdownService: BreakevenMarkdownService;
        breakevenReportService: BreakevenReportService;
        columnValidationService: ColumnValidationService;
        configValidationService: ConfigValidationService;
        contextMetaService: {
            executionContextService: { context: IExecutionContext };
            getContextTimestamp: () => number;
            loggerService: {
                _commonLogger: ILogger;
                _executionContext: {};
                _methodContext: {};
                debug: (topic: string, ...args: any[]) => Promise<void>;
                executionContextService: { context: IExecutionContext };
                info: (topic: string, ...args: any[]) => Promise<void>;
                log: (topic: string, ...args: any[]) => Promise<void>;
                methodContextService: { context: IMethodContext };
                setLogger: (logger: ILogger) => void;
                warn: (topic: string, ...args: any[]) => Promise<void>;
            };
        };
        exchangeConnectionService: ExchangeConnectionService;
        exchangeCoreService: ExchangeCoreService;
        exchangeSchemaService: ExchangeSchemaService;
        exchangeValidationService: ExchangeValidationService;
        executionContextService: { context: IExecutionContext };
        frameConnectionService: FrameConnectionService;
        frameCoreService: FrameCoreService;
        frameSchemaService: FrameSchemaService;
        frameValidationService: FrameValidationService;
        heatMarkdownService: HeatMarkdownService;
        heatReportService: HeatReportService;
        highestProfitMarkdownService: HighestProfitMarkdownService;
        highestProfitReportService: HighestProfitReportService;
        liveCommandService: LiveCommandService;
        liveLogicPrivateService: LiveLogicPrivateService;
        liveLogicPublicService: LiveLogicPublicService;
        liveMarkdownService: LiveMarkdownService;
        liveReportService: LiveReportService;
        loggerService: {
            _commonLogger: ILogger;
            _executionContext: {};
            _methodContext: {};
            debug: (topic: string, ...args: any[]) => Promise<void>;
            executionContextService: { context: IExecutionContext };
            info: (topic: string, ...args: any[]) => Promise<void>;
            log: (topic: string, ...args: any[]) => Promise<void>;
            methodContextService: { context: IMethodContext };
            setLogger: (logger: ILogger) => void;
            warn: (topic: string, ...args: any[]) => Promise<void>;
        };
        maxDrawdownMarkdownService: MaxDrawdownMarkdownService;
        maxDrawdownReportService: MaxDrawdownReportService;
        methodContextService: { context: IMethodContext };
        notificationHelperService: NotificationHelperService;
        partialConnectionService: PartialConnectionService;
        partialGlobalService: PartialGlobalService;
        partialMarkdownService: PartialMarkdownService;
        partialReportService: PartialReportService;
        performanceMarkdownService: PerformanceMarkdownService;
        performanceReportService: PerformanceReportService;
        priceMetaService: PriceMetaService;
        riskConnectionService: RiskConnectionService;
        riskGlobalService: RiskGlobalService;
        riskMarkdownService: RiskMarkdownService;
        riskReportService: RiskReportService;
        riskSchemaService: RiskSchemaService;
        riskValidationService: RiskValidationService;
        scheduleMarkdownService: ScheduleMarkdownService;
        scheduleReportService: ScheduleReportService;
        sizingConnectionService: SizingConnectionService;
        sizingGlobalService: SizingGlobalService;
        sizingSchemaService: SizingSchemaService;
        sizingValidationService: SizingValidationService;
        strategyConnectionService: StrategyConnectionService;
        strategyCoreService: StrategyCoreService;
        strategyMarkdownService: StrategyMarkdownService;
        strategyReportService: StrategyReportService;
        strategySchemaService: StrategySchemaService;
        strategyValidationService: StrategyValidationService;
        syncMarkdownService: SyncMarkdownService;
        syncReportService: SyncReportService;
        timeMetaService: TimeMetaService;
        walkerCommandService: WalkerCommandService;
        walkerLogicPrivateService: WalkerLogicPrivateService;
        walkerLogicPublicService: WalkerLogicPublicService;
        walkerMarkdownService: WalkerMarkdownService;
        walkerReportService: WalkerReportService;
        walkerSchemaService: WalkerSchemaService;
        walkerValidationService: WalkerValidationService;
    }

    Type declaration

    • actionConnectionService: ActionConnectionService
    • actionCoreService: ActionCoreService
    • actionSchemaService: ActionSchemaService
    • actionValidationService: ActionValidationService
    • backtestCommandService: BacktestCommandService
    • backtestLogicPrivateService: BacktestLogicPrivateService
    • backtestLogicPublicService: BacktestLogicPublicService
    • backtestMarkdownService: BacktestMarkdownService
    • backtestReportService: BacktestReportService
    • breakevenConnectionService: BreakevenConnectionService
    • breakevenGlobalService: BreakevenGlobalService
    • breakevenMarkdownService: BreakevenMarkdownService
    • breakevenReportService: BreakevenReportService
    • columnValidationService: ColumnValidationService
    • configValidationService: ConfigValidationService
    • contextMetaService: {
          executionContextService: { context: IExecutionContext };
          getContextTimestamp: () => number;
          loggerService: {
              _commonLogger: ILogger;
              _executionContext: {};
              _methodContext: {};
              debug: (topic: string, ...args: any[]) => Promise<void>;
              executionContextService: { context: IExecutionContext };
              info: (topic: string, ...args: any[]) => Promise<void>;
              log: (topic: string, ...args: any[]) => Promise<void>;
              methodContextService: { context: IMethodContext };
              setLogger: (logger: ILogger) => void;
              warn: (topic: string, ...args: any[]) => Promise<void>;
          };
      }
    • exchangeConnectionService: ExchangeConnectionService
    • exchangeCoreService: ExchangeCoreService
    • exchangeSchemaService: ExchangeSchemaService
    • exchangeValidationService: ExchangeValidationService
    • executionContextService: { context: IExecutionContext }
    • frameConnectionService: FrameConnectionService
    • frameCoreService: FrameCoreService
    • frameSchemaService: FrameSchemaService
    • frameValidationService: FrameValidationService
    • heatMarkdownService: HeatMarkdownService
    • heatReportService: HeatReportService
    • highestProfitMarkdownService: HighestProfitMarkdownService
    • highestProfitReportService: HighestProfitReportService
    • liveCommandService: LiveCommandService
    • liveLogicPrivateService: LiveLogicPrivateService
    • liveLogicPublicService: LiveLogicPublicService
    • liveMarkdownService: LiveMarkdownService
    • liveReportService: LiveReportService
    • loggerService: {
          _commonLogger: ILogger;
          _executionContext: {};
          _methodContext: {};
          debug: (topic: string, ...args: any[]) => Promise<void>;
          executionContextService: { context: IExecutionContext };
          info: (topic: string, ...args: any[]) => Promise<void>;
          log: (topic: string, ...args: any[]) => Promise<void>;
          methodContextService: { context: IMethodContext };
          setLogger: (logger: ILogger) => void;
          warn: (topic: string, ...args: any[]) => Promise<void>;
      }
    • maxDrawdownMarkdownService: MaxDrawdownMarkdownService
    • maxDrawdownReportService: MaxDrawdownReportService
    • methodContextService: { context: IMethodContext }
    • notificationHelperService: NotificationHelperService
    • partialConnectionService: PartialConnectionService
    • partialGlobalService: PartialGlobalService
    • partialMarkdownService: PartialMarkdownService
    • partialReportService: PartialReportService
    • performanceMarkdownService: PerformanceMarkdownService
    • performanceReportService: PerformanceReportService
    • priceMetaService: PriceMetaService
    • riskConnectionService: RiskConnectionService
    • riskGlobalService: RiskGlobalService
    • riskMarkdownService: RiskMarkdownService
    • riskReportService: RiskReportService
    • riskSchemaService: RiskSchemaService
    • riskValidationService: RiskValidationService
    • scheduleMarkdownService: ScheduleMarkdownService
    • scheduleReportService: ScheduleReportService
    • sizingConnectionService: SizingConnectionService
    • sizingGlobalService: SizingGlobalService
    • sizingSchemaService: SizingSchemaService
    • sizingValidationService: SizingValidationService
    • strategyConnectionService: StrategyConnectionService
    • strategyCoreService: StrategyCoreService
    • strategyMarkdownService: StrategyMarkdownService
    • strategyReportService: StrategyReportService
    • strategySchemaService: StrategySchemaService
    • strategyValidationService: StrategyValidationService
    • syncMarkdownService: SyncMarkdownService
    • syncReportService: SyncReportService
    • timeMetaService: TimeMetaService
    • walkerCommandService: WalkerCommandService
    • walkerLogicPrivateService: WalkerLogicPrivateService
    • walkerLogicPublicService: WalkerLogicPublicService
    • walkerMarkdownService: WalkerMarkdownService
    • walkerReportService: WalkerReportService
    • walkerSchemaService: WalkerSchemaService
    • walkerValidationService: WalkerValidationService
    +lib | backtest-kit

    Variable libConst

    lib: {
        actionConnectionService: ActionConnectionService;
        actionCoreService: ActionCoreService;
        actionSchemaService: ActionSchemaService;
        actionValidationService: ActionValidationService;
        backtestCommandService: BacktestCommandService;
        backtestLogicPrivateService: BacktestLogicPrivateService;
        backtestLogicPublicService: BacktestLogicPublicService;
        backtestMarkdownService: BacktestMarkdownService;
        backtestReportService: BacktestReportService;
        breakevenConnectionService: BreakevenConnectionService;
        breakevenGlobalService: BreakevenGlobalService;
        breakevenMarkdownService: BreakevenMarkdownService;
        breakevenReportService: BreakevenReportService;
        columnValidationService: ColumnValidationService;
        configValidationService: ConfigValidationService;
        contextMetaService: {
            executionContextService: { context: IExecutionContext };
            getContextTimestamp: () => number;
            loggerService: {
                _commonLogger: ILogger;
                _executionContext: {};
                _methodContext: {};
                debug: (topic: string, ...args: any[]) => Promise<void>;
                executionContextService: { context: IExecutionContext };
                info: (topic: string, ...args: any[]) => Promise<void>;
                log: (topic: string, ...args: any[]) => Promise<void>;
                methodContextService: { context: IMethodContext };
                setLogger: (logger: ILogger) => void;
                warn: (topic: string, ...args: any[]) => Promise<void>;
            };
        };
        exchangeConnectionService: ExchangeConnectionService;
        exchangeCoreService: ExchangeCoreService;
        exchangeSchemaService: ExchangeSchemaService;
        exchangeValidationService: ExchangeValidationService;
        executionContextService: { context: IExecutionContext };
        frameConnectionService: FrameConnectionService;
        frameCoreService: FrameCoreService;
        frameSchemaService: FrameSchemaService;
        frameValidationService: FrameValidationService;
        heatMarkdownService: HeatMarkdownService;
        heatReportService: HeatReportService;
        highestProfitMarkdownService: HighestProfitMarkdownService;
        highestProfitReportService: HighestProfitReportService;
        liveCommandService: LiveCommandService;
        liveLogicPrivateService: LiveLogicPrivateService;
        liveLogicPublicService: LiveLogicPublicService;
        liveMarkdownService: LiveMarkdownService;
        liveReportService: LiveReportService;
        loggerService: {
            _commonLogger: ILogger;
            _executionContext: {};
            _methodContext: {};
            debug: (topic: string, ...args: any[]) => Promise<void>;
            executionContextService: { context: IExecutionContext };
            info: (topic: string, ...args: any[]) => Promise<void>;
            log: (topic: string, ...args: any[]) => Promise<void>;
            methodContextService: { context: IMethodContext };
            setLogger: (logger: ILogger) => void;
            warn: (topic: string, ...args: any[]) => Promise<void>;
        };
        maxDrawdownMarkdownService: MaxDrawdownMarkdownService;
        maxDrawdownReportService: MaxDrawdownReportService;
        methodContextService: { context: IMethodContext };
        notificationHelperService: NotificationHelperService;
        partialConnectionService: PartialConnectionService;
        partialGlobalService: PartialGlobalService;
        partialMarkdownService: PartialMarkdownService;
        partialReportService: PartialReportService;
        performanceMarkdownService: PerformanceMarkdownService;
        performanceReportService: PerformanceReportService;
        priceMetaService: PriceMetaService;
        riskConnectionService: RiskConnectionService;
        riskGlobalService: RiskGlobalService;
        riskMarkdownService: RiskMarkdownService;
        riskReportService: RiskReportService;
        riskSchemaService: RiskSchemaService;
        riskValidationService: RiskValidationService;
        scheduleMarkdownService: ScheduleMarkdownService;
        scheduleReportService: ScheduleReportService;
        sizingConnectionService: SizingConnectionService;
        sizingGlobalService: SizingGlobalService;
        sizingSchemaService: SizingSchemaService;
        sizingValidationService: SizingValidationService;
        strategyConnectionService: StrategyConnectionService;
        strategyCoreService: StrategyCoreService;
        strategyMarkdownService: StrategyMarkdownService;
        strategyReportService: StrategyReportService;
        strategySchemaService: StrategySchemaService;
        strategyValidationService: StrategyValidationService;
        syncMarkdownService: SyncMarkdownService;
        syncReportService: SyncReportService;
        timeMetaService: TimeMetaService;
        walkerCommandService: WalkerCommandService;
        walkerLogicPrivateService: WalkerLogicPrivateService;
        walkerLogicPublicService: WalkerLogicPublicService;
        walkerMarkdownService: WalkerMarkdownService;
        walkerReportService: WalkerReportService;
        walkerSchemaService: WalkerSchemaService;
        walkerValidationService: WalkerValidationService;
    }

    Type declaration

    • actionConnectionService: ActionConnectionService
    • actionCoreService: ActionCoreService
    • actionSchemaService: ActionSchemaService
    • actionValidationService: ActionValidationService
    • backtestCommandService: BacktestCommandService
    • backtestLogicPrivateService: BacktestLogicPrivateService
    • backtestLogicPublicService: BacktestLogicPublicService
    • backtestMarkdownService: BacktestMarkdownService
    • backtestReportService: BacktestReportService
    • breakevenConnectionService: BreakevenConnectionService
    • breakevenGlobalService: BreakevenGlobalService
    • breakevenMarkdownService: BreakevenMarkdownService
    • breakevenReportService: BreakevenReportService
    • columnValidationService: ColumnValidationService
    • configValidationService: ConfigValidationService
    • contextMetaService: {
          executionContextService: { context: IExecutionContext };
          getContextTimestamp: () => number;
          loggerService: {
              _commonLogger: ILogger;
              _executionContext: {};
              _methodContext: {};
              debug: (topic: string, ...args: any[]) => Promise<void>;
              executionContextService: { context: IExecutionContext };
              info: (topic: string, ...args: any[]) => Promise<void>;
              log: (topic: string, ...args: any[]) => Promise<void>;
              methodContextService: { context: IMethodContext };
              setLogger: (logger: ILogger) => void;
              warn: (topic: string, ...args: any[]) => Promise<void>;
          };
      }
    • exchangeConnectionService: ExchangeConnectionService
    • exchangeCoreService: ExchangeCoreService
    • exchangeSchemaService: ExchangeSchemaService
    • exchangeValidationService: ExchangeValidationService
    • executionContextService: { context: IExecutionContext }
    • frameConnectionService: FrameConnectionService
    • frameCoreService: FrameCoreService
    • frameSchemaService: FrameSchemaService
    • frameValidationService: FrameValidationService
    • heatMarkdownService: HeatMarkdownService
    • heatReportService: HeatReportService
    • highestProfitMarkdownService: HighestProfitMarkdownService
    • highestProfitReportService: HighestProfitReportService
    • liveCommandService: LiveCommandService
    • liveLogicPrivateService: LiveLogicPrivateService
    • liveLogicPublicService: LiveLogicPublicService
    • liveMarkdownService: LiveMarkdownService
    • liveReportService: LiveReportService
    • loggerService: {
          _commonLogger: ILogger;
          _executionContext: {};
          _methodContext: {};
          debug: (topic: string, ...args: any[]) => Promise<void>;
          executionContextService: { context: IExecutionContext };
          info: (topic: string, ...args: any[]) => Promise<void>;
          log: (topic: string, ...args: any[]) => Promise<void>;
          methodContextService: { context: IMethodContext };
          setLogger: (logger: ILogger) => void;
          warn: (topic: string, ...args: any[]) => Promise<void>;
      }
    • maxDrawdownMarkdownService: MaxDrawdownMarkdownService
    • maxDrawdownReportService: MaxDrawdownReportService
    • methodContextService: { context: IMethodContext }
    • notificationHelperService: NotificationHelperService
    • partialConnectionService: PartialConnectionService
    • partialGlobalService: PartialGlobalService
    • partialMarkdownService: PartialMarkdownService
    • partialReportService: PartialReportService
    • performanceMarkdownService: PerformanceMarkdownService
    • performanceReportService: PerformanceReportService
    • priceMetaService: PriceMetaService
    • riskConnectionService: RiskConnectionService
    • riskGlobalService: RiskGlobalService
    • riskMarkdownService: RiskMarkdownService
    • riskReportService: RiskReportService
    • riskSchemaService: RiskSchemaService
    • riskValidationService: RiskValidationService
    • scheduleMarkdownService: ScheduleMarkdownService
    • scheduleReportService: ScheduleReportService
    • sizingConnectionService: SizingConnectionService
    • sizingGlobalService: SizingGlobalService
    • sizingSchemaService: SizingSchemaService
    • sizingValidationService: SizingValidationService
    • strategyConnectionService: StrategyConnectionService
    • strategyCoreService: StrategyCoreService
    • strategyMarkdownService: StrategyMarkdownService
    • strategyReportService: StrategyReportService
    • strategySchemaService: StrategySchemaService
    • strategyValidationService: StrategyValidationService
    • syncMarkdownService: SyncMarkdownService
    • syncReportService: SyncReportService
    • timeMetaService: TimeMetaService
    • walkerCommandService: WalkerCommandService
    • walkerLogicPrivateService: WalkerLogicPrivateService
    • walkerLogicPublicService: WalkerLogicPublicService
    • walkerMarkdownService: WalkerMarkdownService
    • walkerReportService: WalkerReportService
    • walkerSchemaService: WalkerSchemaService
    • walkerValidationService: WalkerValidationService