Documentation Index
Fetch the complete documentation index at: https://mintlify.com/theonetrade/backtest-ollama-crontab/llms.txt
Use this file to discover all available pages before exploring further.
SignalJobService is the bridge between the crawler ingestion layer and the LLM risk-screening layer. It listens on the signalJobSubject observable subject, and each time the subject fires it runs a queued job that reads unprocessed rows from parser-items, wraps each row in a correctly-timed execution context, invokes SignalLogicService.execute to obtain a RiskOutline assessment, writes the result to screen-items, and marks the source row as visited. The queued() wrapper from functools-kit ensures that overlapping crontab ticks do not spawn concurrent job runs — any trigger that arrives while a run is already in progress simply waits in line.
signalJobSubject emitter
Defined in config/emitters.ts. An instance of Subject<void> from functools-kit.
signalJobSubject.next() fires all active subscriptions synchronously. CrawlerMainService calls it at the end of every crawl (crawlLiveFrame and crawlBacktestFrame), ensuring that new parser-items rows are processed immediately after ingestion.
Subject<void> carries no payload. The subscriber (SignalJobService.run)
determines what work to do by inspecting the current execution mode and
database state at the moment of invocation.SignalJobService
SignalJobService is registered under TYPES.signalJobService and is accessible as core.signalJobService.
enable(): () => void
Subscribes to signalJobSubject and starts the queued job runner. Protected by singleshot() from functools-kit so the subscription is created at most once even if enable() is called multiple times.
compose(unJob, unEnable). Calling the returned function:
- Unsubscribes from
signalJobSubject - Clears the
singleshotsentinel soenable()can be called again
disable(): void
Convenience method that calls the dispose function returned by enable() if it has previously been invoked.
this.enable.hasValue() returns true only while the singleshot memo
holds a value (i.e. after enable() has been called and before the returned
dispose has been invoked). If enable() was never called, disable() is a
no-op.Internal Processing Pipeline
run() — queued entry point
queued() wrapper from functools-kit serialises concurrent invocations: if a run is in progress when signalJobSubject.next() fires, the new call is enqueued and executed after the current one resolves. This prevents duplicate LLM calls for the same row when crontab ticks overlap.
RUN_LIVE_FN — live mode processing
Fetch unvisited rows
Calls
parserDbService.findAllByVisited(false) to retrieve all
parser-items documents where visited: false.Dedup check
For each row, checks
screenDbService.findByParserItem(row.id). If a
screen-items document already exists for this parserItemId, the row is
skipped to prevent duplicate LLM invocations.Run LLM in context
Calls
RUN_IN_CONTEXT_FN(self, row, backtest=false) to obtain an
IScreenDto from SignalLogicService.execute.RUN_BACKTEST_FN — backtest mode processing
Resolve frame boundaries
Calls
listFrameSchema() from backtest-kit and finds the frame whose
frameName matches the current context. Extracts startDate and
endDate.Fetch rows in date range
Calls
parserDbService.findAllByPublishedAt(startDate, endDate) to get
all parser-items within the frame window.Run LLM in historical context
Calls
RUN_IN_CONTEXT_FN(self, row, backtest=true). The backtest flag
is forwarded to ExecutionContextService.runInContext so the LLM agent
sees the correct historical market context rather than the current moment.RUN_IN_CONTEXT_FN — execution context wrapper
backtest-kit:
alignToInterval(row.publishedAt, "1m")— snaps the signal’s publication timestamp to the nearest 1-minute candle boundary. This is thewhenvalue the LLM context will see as “now”.ExecutionContextService.runInContext(fn, { symbol, when, backtest })— establishes a scoped execution context so the agent-swarm-kit LLM call insideSignalLogicService.executequeries market data at the correct historical moment rather than wall-clock time.beginTime(...)— wraps the entire function, recording the start timestamp for performance and audit logging.
enable / disable Pattern
enable() returns dispose
The returned function both unsubscribes from
signalJobSubject and resets
the singleshot sentinel so enable() can be safely re-called after a
disable().disable() is safe to call anytime
disable() checks enable.hasValue() before acting. Calling it when
enable() was never invoked is a safe no-op — useful in test teardown
hooks that run unconditionally.Data Flow Summary
SignalLogicService
The LLM execution layer called inside
RUN_IN_CONTEXT_FN — runs the
RiskOutline and maps results to IScreenDto.CrawlerService
Triggers
signalJobSubject.next() after every crawl to kick off this
pipeline.