Markdown Services

This document describes the Markdown Services subsystem, which provides automated report generation and performance analytics for backtesting and live trading operations. These services subscribe to execution events, accumulate statistical data, and generate markdown-formatted reports with comprehensive trading metrics.

For information about the event system that feeds these services, see Event System. For details on the execution modes that generate events, see Execution Modes.


The Markdown Services subsystem consists of three specialized service classes, each responsible for reporting on a specific execution mode:

Mermaid Diagram

Service Event Source Data Stored Primary Purpose
BacktestMarkdownService signalBacktestEmitter Closed signals only Historical backtest performance analysis
LiveMarkdownService signalLiveEmitter All events (idle, opened, active, closed) Real-time trading activity monitoring
ScheduleMarkdownService signalEmitter, signalLiveEmitter Scheduled and cancelled signals Limit order execution tracking

The following diagram illustrates how trading events flow from execution contexts through emitters to markdown services, and finally to persistent reports:

Mermaid Diagram


BacktestMarkdownService generates performance reports for historical backtesting by accumulating closed signals and calculating trading statistics. It only processes closed action events, ignoring intermediate states.

The service subscribes to signalBacktestEmitter during initialization using the singleshot pattern to ensure one-time setup:

Mermaid Diagram

Each strategy gets an isolated ReportStorage instance via memoization:

Mermaid Diagram

interface BacktestStatistics {
signalList: IStrategyTickResultClosed[];
totalSignals: number;
winCount: number;
lossCount: number;
winRate: number | null; // 0-100%, null if unsafe
avgPnl: number | null; // Average PNL %
totalPnl: number | null; // Cumulative PNL %
stdDev: number | null; // Volatility
sharpeRatio: number | null; // avgPnl / stdDev
annualizedSharpeRatio: number | null; // sharpeRatio × √365
certaintyRatio: number | null; // avgWin / |avgLoss|
expectedYearlyReturns: number | null; // Projected annual return
}

All numeric metrics use the isUnsafe() function to guard against NaN, Infinity, and invalid calculations:


LiveMarkdownService tracks real-time trading activity by accumulating all tick events (idle, opened, active, closed) and provides comprehensive live trading analytics.

Event Type Stored As Update Strategy
idle TickEvent Replaces last idle if no open/active signals follow
opened TickEvent Appends to event list
active TickEvent Replaces existing event with same signalId
closed TickEvent Replaces existing event with same signalId

Mermaid Diagram

The service maintains a bounded queue of 250 events to prevent memory leaks in long-running live trading sessions:


ScheduleMarkdownService tracks scheduled limit orders and their lifecycle outcomes (activated vs. cancelled), providing cancellation rate analytics.

Unlike the other services, ScheduleMarkdownService subscribes to both signalLiveEmitter and the global signalEmitter to capture scheduled signals from live trading:

interface ScheduleStatistics {
eventList: ScheduledEvent[];
totalEvents: number;
totalScheduled: number;
totalCancelled: number;
cancellationRate: number | null; // 0-100%, null if no scheduled
avgWaitTime: number | null; // Minutes, null if no cancelled
}

The cancellation rate metric indicates what percentage of scheduled limit orders were cancelled without execution:

cancellationRate = (totalCancelled / totalScheduled) × 100

Each markdown service contains an internal ReportStorage class that implements the Controller-View pattern for data management:

Mermaid Diagram

Services use functools-kit memoization to create one ReportStorage instance per strategy:


Mermaid Diagram

Metric Formula Interpretation
Win Rate (winCount / totalSignals) × 100 Percentage of profitable trades
Sharpe Ratio avgPnl / stdDev Risk-adjusted return (higher is better)
Annualized Sharpe sharpeRatio × √365 Annual risk-adjusted return
Certainty Ratio `avgWin / avgLoss
Expected Yearly Returns avgPnl × (365 / avgDurationDays) Projected annual profit %

All services generate markdown reports with column-based tables for event data:

Mermaid Diagram

Columns are defined as arrays of objects with key, label, and format properties:

The dump() method writes reports to disk with the following structure:

./logs/
backtest/
{strategyName}.md
live/
{strategyName}.md
schedule/
{strategyName}.md

Public API classes (Backtest, Live, Schedule) delegate to markdown services through the dependency injection container:

Mermaid Diagram

Public Method Service Method Return Type
Backtest.getData(strategyName) backtestMarkdownService.getData(strategyName) BacktestStatistics
Backtest.getReport(strategyName) backtestMarkdownService.getReport(strategyName) string
Backtest.dump(strategyName, path?) backtestMarkdownService.dump(strategyName, path) void
Live.getData(strategyName) liveMarkdownService.getData(strategyName) LiveStatistics
Live.getReport(strategyName) liveMarkdownService.getReport(strategyName) string
Live.dump(strategyName, path?) liveMarkdownService.dump(strategyName, path) void
Schedule.getData(strategyName) scheduleMarkdownService.getData(strategyName) ScheduleStatistics
Schedule.getReport(strategyName) scheduleMarkdownService.getReport(strategyName) string
Schedule.dump(strategyName, path?) scheduleMarkdownService.dump(strategyName, path) void

Mermaid Diagram


All markdown services implement a clear() method to reset accumulated data:

Mermaid Diagram