Documentation 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.
parser-items is the raw ingestion collection. The crawler upserts messages here; the signal job reads unvisited rows and processes them through the LLM. Each document is a fully-parsed trading signal extracted from a Telegram channel message, ready for risk evaluation. The visited boolean is the state-machine flag that separates the ingestion stage from the enrichment stage — once SignalJobService successfully produces a screen-items document, it flips visited to true so the row is never reprocessed.
Schema Definition
FullIParserDto interface and ParserSchema from packages/core/src/schema/Parser.schema.ts:
Fields
Message Identity
Telegram channel name from which the message was scraped (e.g.,
"crypto_yoda_channel"). Part of the unique compound index with messageId. Indexed for channel-scoped queries.Source identifier for the channel. Set equal to
channel by the current crawler implementation. Indexed separately to support potential future multi-source setups.Telegram’s numeric message ID within the channel. Combined with
channel in a unique compound index to ensure idempotent upserts — scraping the same message twice produces a single document.The timestamp at which the original Telegram message was published. Used as the time axis for 4-hour window queries and backtest frame filtering. Indexed.
Full original message text preserved verbatim. Used for audit, replay, and to populate the
note field of the resulting screen-items document.Parsed Signal
Trading symbol with USDT suffix, e.g.,
"SOLUSDT", "BTCUSDT". The crawler appends "USDT" to the raw symbol extracted from the message. Indexed and used as the primary dimension in compound time-range queries.Trade direction parsed from Russian keywords in the original message (
ЛОНГ → "long", ШОРТ → "short").Lower bound of the entry price zone extracted from the message.
Upper bound of the entry price zone extracted from the message.
Array of take-profit target prices in ascending order as parsed from the message. Passed directly to
RiskOutlineContract as the targets argument.Stop-loss price level parsed from the message. Passed directly to
RiskOutlineContract as the stoploss argument.Processing State
Tracks whether this row has been processed by
SignalJobService. Defaults to false on insert. Flipped to true by ParserDbService.markVisited() after a successful screen-items document has been created. Indexed to allow O(1) scans for unprocessed rows.Raw parsed data object produced by the screen parser (
CryptoYodaScreenService). Stored as Schema.Types.Mixed and propagated to screen-items.content unchanged.Auto-managed by Mongoose
timestamps. Set once at document creation. Mapped from the default createdAt via { createdAt: "createDate" }.Auto-managed by Mongoose
timestamps. Updated on every write. Mapped from the default updatedAt via { updatedAt: "updatedDate" }.Indexes
| Index | Type | Purpose |
|---|---|---|
{ channel: 1, messageId: 1 } | Unique | Idempotent upserts — same Telegram message is never stored twice |
{ symbol: 1, publishedAt: -1 } | Compound | Efficient findLast4HourRow queries sorted by recency |
{ channel: 1 } | Single-field | Channel-scoped filtering |
{ source: 1 } | Single-field | Source-scoped filtering |
{ messageId: 1 } | Single-field | Direct message-ID lookup |
{ publishedAt: 1 } | Single-field | Time-range scans (backtest frame queries) |
{ symbol: 1 } | Single-field | Symbol equality filter |
{ visited: 1 } | Single-field | Fast scan for unprocessed rows in live mode |
The unique compound index on
{ channel: 1, messageId: 1 } is the crawler’s primary idempotency guard. ParserDbService.create() uses findOneAndUpdate with $setOnInsert, so re-crawling the same channel day returns existing documents without overwriting any data.State Machine
Thevisited flag governs the two-stage pipeline lifecycle for every parser row:
- Ingestion — The crawler upserts new messages with
visited: false(the schema default). - Job pickup —
SignalJobServicequeriesparserDbService.findAllByVisited(false)to find all pending rows. - Deduplication check — Before calling the LLM,
screenDbService.findByParserItem(row.id)is checked. If ascreen-itemsdocument already exists, the row is skipped even ifvisitedis stillfalse. - Enrichment —
SignalLogicService.execute(row)runs theRiskOutlineoutline and returns anIScreenDto. - Persistence — The
IScreenDtois written toscreen-itemsandmarkVisited(row.id)setsvisited: true. - Idempotency — Re-running the job skips all rows where
visited: true, making repeated cron triggers safe.