The parser is the second stage of the signal pipeline. AfterDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-ollama-crontab/llms.txt
Use this file to discover all available pages before exploring further.
ScraperService retrieves raw Telegram message text, CryptoYodaScreenService passes each message through a set of regex-based extraction rules that produce a structured trading signal. Any message that fails a required extraction or fails a field-level validation receives a null data payload and is skipped by the crawler — only fully-formed signals reach the database.
Signal Format
The channel posts signals in Russian. A typical message looks like this (translated for illustration):The original messages are written in Russian. The regex patterns in
SIGNAL_FORMAT match Russian keywords (e.g. ШОРТ, ЛОНГ, зоне, Закрыть, СТОП-ЛОСС). The translated example above is provided for readability only.SIGNAL_FORMAT
CryptoYodaScreenService defines a SIGNAL_FORMAT constant that maps each field name to an ExtractConfig descriptor. This is the complete definition from the source:
num(s) normalises decimal separators ("," → "."), and isNum(v) checks that the result is a finite positive number.
Field breakdown
| Field | Pattern | Output type | Notes |
|---|---|---|---|
symbol | /#([A-Z0-9]+)\/USDT/ | string | Capture group 1 — ticker without /USDT. CrawlerService appends USDT when storing. |
direction | /(ШОРТ|ЛОНГ)/i | "short" | "long" | Russian keyword transformed to lowercase English. |
entry | Zone price range regex | { from: number; to: number } | Validates from < to and both positive. |
targets | Global TP regex | number[] | multi: true — collects all matches. Requires the global flag (g). |
stoploss | СТОП-ЛОСС regex | number | Validates positive finite number. |
ParseFormat Type
Each field in aParseFormat object maps to an ExtractConfig<T> with the following interface:
EXTRACT_DATA_FN inside ParserService iterates over each key in the format object and applies these rules in order:
Single vs. multi match
If
multi is true, text.matchAll(pattern) collects all matches. If the result is empty and the field is not optional, the entire message returns null.Group extraction
The raw value is taken from
match[cfg.group ?? 1], falling back to match[0] if the indexed group is undefined.ParserService
ParserService (packages/core/src/lib/services/core/ParserService.ts) provides a single public method: parseDay. It accepts a list of raw ScraperMessage objects and a FieldMapping format, runs EXTRACT_DATA_FN against each message’s content, and returns an array of ParserMessageBase records:
EXTRACT_DATA_FN returns null (any required field failed), the record has data: null. The crawler checks if (!msg.data) and skips those records without writing them to MongoDB.
Custom Channel Parsers
To add support for a different Telegram channel, follow these steps:Define SIGNAL_FORMAT
Create a new
ParseFormat object with ExtractConfig entries that match the new channel’s message structure. Test each regex against real sample messages before integrating.Create a ScreenService
Create a new class (e.g.
MyChannelScreenService) with screenDay(date) and parseDay(messages) methods following the pattern of CryptoYodaScreenService. Set CHANNEL_NAME to the new channel’s Telegram identifier.