fintech-algorithms
Using a coding agent? Give it the skill: npx skills add IslamBaraka90/Fintech-Algorithms-Library What it does →

Market-Wide Candlestick Pattern Scanner

Install and import#

bash
npm install fintech-algorithms
ts
import { scanMarket } from "fintech-algorithms/price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner";

Signature#

scanMarket(data)

dispatch a frozen registry across injected detector candidates and emit only causal occurrence records with explicit rejection reasons.

Parameters#

NameTypeNotes
data{ as_of: string; minimum_geometry_score: number; registry: { pattern_id: string; name: string; direction: string; window: number; detector: string; version: string; enabled: boolean; priority: number }[]; candidates: { instrument_id: string; interval: string; price_basis: string; session: string; pattern_id: string; pattern_name: string; direction: string; start_index: number; end_index: number; start_time: string; end_time: string; detected_at: string; available_at: string; bar_closed: boolean; detector_version: string; geometry_score: number; reason_codes: string[] }[] }Topic input record; the required fields are fixed by this topic data-contract.

Returns#

{ state, as_of, candidate_count, occurrence_count, skipped_count, occurrences, skipped }

One ready scan record containing deterministically ordered causal occurrences and reason-coded skipped candidates, with counts for both.

Complexity: time O(n log n) worst case; see README for topic-specific n, space O(n).

Worked example#

verified This is the worked example published in the article, replayed by the test suite on every run. The output cannot drift.

Input#

data
{
  "as_of": "2026-01-05T10:06:00Z",
  "minimum_geometry_score": 0.8,
  "registry": [
    {
      "pattern_id": "D06-F03-A01",
      "name": "Bullish Engulfing",
      "direction": "bullish",
      "window": 2,
      "detector": "bullish_engulfing",
      "version": "v1",
      "enabled": true,
      "priority": 2
    }
  ],
  "candidates": [
    {
      "instrument_id": "SYNTH:AAA",
      "interval": "5m",
      "price_basis": "raw-trades",
      "session": "synthetic-utc",
      "pattern_id": "D06-F03-A01",
      "pattern_name": "Bullish Engulfing",
      "direction": "bullish",
      "start_index": 10,
      "end_index": 11,
      "start_time": "2026-01-05T10:00:00Z",
      "end_time": "2026-01-05T10:05:00Z",
      "detected_at": "2026-01-05T10:05:01Z",
      "available_at": "2026-01-05T10:05:01Z",
      "bar_closed": true
    },
    {
      "instrument_id": "SYNTH:LIVE",
      "interval": "5m",
      "price_basis": "raw-trades",
      "session": "synthetic-utc",
      "pattern_id": "D06-F03-A01",
      "pattern_name": "Bullish Engulfing",
      "direction": "bullish",
      "start_index": 10,
      "end_index": 11,
      "start_time": "2026-01-05T10:00:00Z",
      "end_time": "2026-01-05T10:05:00Z",
      "detected_at": "2026-01-05T10:05:01Z",
      "available_at": "2026-01-05T10:05:01Z",
      "bar_closed": false
    },
    {
      "instrument_id": "SYNTH:WEAK",
      "interval": "5m",
      "price_basis": "raw-trades",
      "session": "synthetic-utc",
      "pattern_id": "D06-F03-A01",
      "pattern_name": "Bullish Engulfing",
      "direction": "bullish",
      "start_index": 10,
      "end_index": 11,
      "start_time": "2026-01-05T10:00:00Z",
      "end_time": "2026-01-05T10:05:00Z",
      "detected_at": "2026-01-05T10:05:01Z",
      "available_at": "2026-01-05T10:05:01Z",
      "bar_closed": true
    }
  ]
}

Call#

scanMarket(data)

Returns#

object with 4 fields: state, candidate_count, occurrence_count, skipped_count

{
  "state": "ready",
  "candidate_count": 3,
  "occurrence_count": 1,
  "skipped_count": 2
}

Diagrams#

Market-Wide Candlestick Pattern Scanner — decision

Calculation flow#

Decision flow
flowchart LR
    A["Validated point-in-time input"] --> B["Freeze scan cut-off"]
    B --> C["Resolve enabled detector"]
    C --> D{"Boundary satisfied?"}
    D -->|"Yes"| E["Reason-coded ready output"]
    D -->|"No"| F["Explicit rejected or unavailable state"]

How it works#

This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.

Read the article →

References#

The rest of the Candlestick Scanning and Context family#