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

Divergence Confirmation and Invalidation State Machine

Install and import#

bash
npm install fintech-algorithms
ts
import { divergenceConfirmationAndInvalidationStateMachine } from "fintech-algorithms/geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine";

Signature#

divergenceConfirmationAndInvalidationStateMachine(payload)

Advances the first detected divergence through causal confirmation, invalidation, and expiry checks.

Parameters#

NameTypeNotes
payload{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }Topic payload containing divergence inputs, bars, confirmation horizon, and invalidation buffer.

Returns#

{ topic_id, state, event, lifecycle }

One lifecycle record. Without an event, state is searching; otherwise it mirrors the lifecycle state (candidate, confirmed, invalidated, or expired) and includes causal levels and trace.

Errors#

  • When detection input, bar data, confirmation horizon, or invalidation buffer is invalid — throws

Complexity: time , space .

Worked example#

executed Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.

Input#

payload
{
  "topic_id": "D08-F05-A06",
  "data_class": "synthetic-teaching",
  "as_of": "2026-01-08T13:30:00Z",
  "bars": [
    {
      "timestamp": "2026-01-05T14:30:00Z",
      "open": 105.75,
      "high": 107,
      "low": 105,
      "close": 106,
      "finalized": true
    },
    {
      "timestamp": "2026-01-05T15:30:00Z",
      "open": 106.112,
      "high": 107.362,
      "low": 105.362,
      "close": 106.362,
      "finalized": true
    },
    {
      "timestamp": "2026-01-05T16:30:00Z",
      "open": 106.4614,
      "high": 107.7114,
      "low": 105.7114,
      "close": 106.7114,
      "finalized": true
    }
  ],
  "price_pivots": [
    {
      "kind": "low",
      "event_index": 18,
      "confirmation_index": 21,
      "price": 98,
      "prominence": 0.72
    },
    {
      "kind": "low",
      "event_index": 42,
      "confirmation_index": 45,
      "price": 94,
      "prominence": 0.84
    }
  ],
  "indicators": [
    {
      "name": "RSI",
      "family": "bounded-momentum",
      "polarity": 1,
      "scale": 100,
      "pivots": [
        {
          "kind": "low",
          "event_index": 19,
          "confirmation_index": 22,
          "value": 28,
          "prominence": 0.76
        },
        {
          "kind": "low",
          "event_index": 41,
          "confirmation_index": 44,
          "value": 36,
          "prominence": 0.86
        }
      ]
    },
    {
      "name": "MACD-Histogram",
      "family": "moving-average-momentum",
      "polarity": 1,
      "scale": 5,
      "pivots": [
        {
          "kind": "low",
          "event_index": 18,
          "confirmation_index": 21,
          "value": -2.2,
          "prominence": 0.7
        },
        {
          "kind": "low",
          "event_index": 42,
          "confirmation_index": 45,
          "value": -1,
          "prominence": 0.81
        }
      ]
    },
    {
      "name": "Stochastic-K",
      "family": "range-momentum",
      "polarity": 1,
      "scale": 100,
      "pivots": [
        {
          "kind": "low",
          "event_index": 17,
          "confirmation_index": 20,
          "value": 18,
          "prominence": 0.68
        },
        {
          "kind": "low",
          "event_index": 43,
          "confirmation_index": 46,
          "value": 29,
          "prominence": 0.78
        }
      ]
    }
  ],
  "parameters": {
    "max_lag": 3,
    "min_separation": 5,
    "max_separation": 40,
    "min_price_fraction": 0.005,
    "min_indicator_delta": 0.05,
    "confirmation_horizon": 12,
    "invalidation_buffer": 0.005,
    "minimum_indicators": 2
  },
  "weights": {
    "RSI": 0.4,
    "MACD-Histogram": 0.35,
    "Stochastic-K": 0.25
  },
  "as_of_index": 71,
  "universe": [
    {
      "symbol": "SYNTH-A",
      "state": "confirmed",
      "divergence_type": "regular-bullish",
      "confluence_score": 86,
      "freshness": 92,
      "liquidity": 80,
      "data_quality": 98,
      "available_index": 47,
      "eligible": true
    },
    {
      "symbol": "SYNTH-B",
      "state": "candidate",
      "divergence_type": "regular-bearish",
      "confluence_score": 91,
      "freshness": 98,
      "liquidity": 72,
      "data_quality": 94,
      "available_index": 54,
      "eligible": true
    },
    {
      "symbol": "SYNTH-C",
      "state": "confirmed",
      "divergence_type": "hidden-bullish",
      "confluence_score": 74,
      "freshness": 70,
      "liquidity": 96,
      "data_quality": 90,
      "available_index": 39,
      "eligible": true
    }
  ]
}

Call#

divergenceConfirmationAndInvalidationStateMachine(payload)

Returns#

object with 4 fields: topic_id, state, event, lifecycle

{
  "topic_id": "D08-F05-A06",
  "state": "confirmed",
  "event": {
    "type": "regular-bullish",
    "direction": "bullish",
    "kind": "low",
    "indicator": "MACD-Histogram",
    "indicator_family": "moving-average-momentum",
    "price_pair": [18, 42],
    "indicator_pair": [18, 42],
    "price_values": [98, 94],
    "indicator_values": [-0.44000000000000006, -0.2],
    "price_delta_fraction": -0.04081632653061224,
    "indicator_delta": 0.24000000000000005,
    "separation": 24,
    "max_alignment_lag": 0,
    "prominence": 0.7675
  },
  "lifecycle": {
    "state": "confirmed",
    "candidate_index": 45,
    "final_index": 47,
    "confirmation_level": 109.5372,
    "invalidation_level": 93.53,
    "deadline": 57,
    "trace": [
      {
        "index": 45,
        "state": "candidate",
        "close": 99
      },
      {
        "index": 46,
        "state": "candidate",
        "close": 103
      },
      {
        "index": 47,
        "state": "confirmed",
        "close": 112
      }
    ]
  }
}

Other exports#

This module also exports adaptIndicator, alignPivots, detectDivergences, scoreDivergence, advanceState, combineConfluence, rankUniverse, runTopic, priceIndicatorPivotAlignment, regularBullishBearishDivergenceDetection, hiddenBullishBearishDivergenceDetection, multiIndicatorDivergenceAdapters, divergenceStrengthAndQualityScoring, multiIndicatorDivergenceConfluence, marketWideDivergenceScannerAndRanking. Every module additionally exports run as an alias of its primary function, and a meta object carrying its catalog id, domain, family, shape and article URL.

Diagrams#

Divergence Confirmation and Invalidation State Machine — map

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 Indicator Divergence Detection family#