Algorithm Testing Execution Engine
Relevant source files
The following files were used as context for generating this wiki page:
The Algorithm Testing Execution Engine is a backend-driven system designed to evaluate trading strategies against real-time financial data. It integrates with the Tinkoff API to stream market candles, applies user-defined logic through an extensible algorithm interface, and manages the lifecycle of simulated trades. The engine is built using NestJS and GraphQL, providing a subscription-based architecture for real-time performance monitoring.
The core purpose of the engine is to allow developers to verify their trading algorithms before deploying them in live markets. It tracks trade entry and exit points based on technical conditions, calculates live price changes, and persists trade history for post-execution analysis.
Sources: readme.md:5-9, backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:13-25
Core Architecture and Data Flow
The engine operates as a reactive system that listens for market data updates. When a new candle is received via the Tinkoff streaming service, the engine updates its internal candle storage and executes the configured algorithm.
Execution Lifecycle
- Initialization: The resolver fetches the user's watchlist and subscribes to real-time candles for each instrument.
- Streaming: Real-time candle data is mapped and stored in a local cache.
- Signal Processing: The algorithm is invoked with the latest candle and historical data to detect "Long" or "Short" signals.
- Trade Management: If a signal is generated, existing trades for that instrument are closed, and a new trade is opened.
- State Synchronization: All trade updates (status, price changes) are published to the frontend via GraphQL subscriptions.
Sources: backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:35-77
The diagram shows the data flow from the external Tinkoff API through the backend resolver to the frontend.
Sources: backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:35-103
Key Components
AlgorithmTestingResolver
This component serves as the entry point for the execution engine. It manages the lifecycle of market subscriptions and handles the GraphQL communication layer.
init(): Bootstraps the engine by fetching instruments and initiating subscriptions.subscribe(instrument): Sets up the Tinkoff candle stream and defines the callback for signal processing.publish(): Aggregates active and closed trades, calculates current profit/loss percentages, and broadcasts updates.
Sources: backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:35-51, backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:88-115
AlgorithmTestingService
The service layer responsible for data persistence and business logic related to trade objects. It interacts with the database via TypeORM.
Sources: backend/src/modules/algorithmTesting/algorithmTesting.module.ts:10-15
Data Structures
AlgorithmTrade
The primary entity for tracking simulated market actions.
| Field | Type | Description |
|---|---|---|
id | number | Unique identifier for the trade. |
type | TradeType | Indicates if the trade is 'Long' or 'Short'. |
price | number | The entry price of the trade. |
closePrice | number | The price at which the trade was closed. |
closed | boolean | Status indicating if the trade is active or finished. |
interval | string | The timeframe used for the test (e.g., '1min'). |
date | string | Timestamp of the trade initiation. |
pricePercentChange | number | Live or final percentage difference from entry price. |
Sources: frontend/src/graphql.ts:31-41, backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:72-82
GraphQL API Interface
The engine exposes mutations and subscriptions to allow users to interact with running tests.
Mutations
closeTrade(id: Float!): Manually closes an active trade at the current market price.
Sources: frontend/src/graphql.ts:133-135, backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:130-142
Subscriptions
trades: A stream ofAlgorithmTradearrays that updates whenever a trade is opened, closed, or the market price shifts.
Sources: frontend/src/graphql.ts:245-247, backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:144-148
Sequence of events during a single candle update where a new signal is generated.
Sources: backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:53-85
Implementation Details
The engine uses a candlesStorage object to maintain a local buffer of market data. This allows the algorithm to access historical context (the candles map) alongside the current candle object.
// backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:58-69
this.candleUnsubscribe[instrument.id] = this.tinkoffService.instance.candle(
{ figi: instrument.figi, interval: this.interval },
async (streamCandle) => {
const candle = this.tinkoffService.mapToCandle(streamCandle);
const isNewCandle = !Boolean(
this.candlesStorage[instrument.id].result().get(candle.time)
);
this.candlesStorage[instrument.id].update(candle);
const { isShort, isLong } = await algorithm({
isNewCandle,
instrument,
candle,
candles: this.candlesStorage[instrument.id].result(),
});
Sources: backend/src/modules/algorithmTesting/algorithmTesting.resolver.ts:58-69
The engine is highly integrated with the frontend, where the AlgorithmTesting component uses the useTradesSubscription hook to display live results. Users can toggle a filter to show "Only Active" trades, which is processed locally based on the trade's closed property.
Sources: frontend/src/pages/chart/components/AlgorithmTesing.tsx:13-35
Summary
The Algorithm Testing Execution Engine provides a robust framework for real-time strategy validation. By leveraging NestJS resolvers and Tinkoff's streaming capabilities, it creates a reactive environment where trade signals are instantly processed and reflected in the user interface. The engine's architecture ensures that strategy performance is calculated dynamically, providing users with live percentage changes for both active and historical trades.