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

Zweig Breadth Thrust

Install and import#

bash
npm install fintech-algorithms
ts
import { calculate } from "fintech-algorithms/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust";

Signature#

calculate(rows, emaLength, lowThreshold, highThreshold, maxSessions)

Detects the rare initiation signal: the advance ratio moving from below a low threshold to above a high one inside a bounded number of sessions. It fires a handful of times in a generation, which is the point — and also why it cannot be validated on a short sample.

Parameters#

NameTypeNotes
rowsRow[]Sessions carrying advances and declines. Rows carry a ready flag; a row that is not ready is excluded rather than treated as zero, because a missing count and a count of zero mean opposite things about market breadth.
emaLengthnumberEMA length applied to the advance ratio. Zweig's original is 10.
min: 1 · integer: true
lowThresholdnumberThe ratio the EMA must fall below to arm the signal. Conventionally 0.40.
min: 0
highThresholdnumberThe ratio it must then exceed. Conventionally 0.615.
min: 0
maxSessionsnumberMaximum sessions permitted between the two crossings; beyond it the move is not a thrust.
min: 1 · integer: true

Returns#

{ status, trigger_date, ema, sessions, series }

The trigger date if one occurred, with the EMA path and session count so a near-miss can be seen rather than merely absent.

Errors#

  • When lowThreshold ≥ highThreshold — throws

Complexity: time O(n), space O(n).

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#

rows
[
  {
    "session_date": "2026-01-05",
    "advances": 520,
    "declines": 480,
    "ready": true
  },
  {
    "session_date": "2026-01-06",
    "advances": 500,
    "declines": 500,
    "ready": true
  },
  {
    "session_date": "2026-01-07",
    "advances": 480,
    "declines": 520,
    "ready": true
  }
]

Showing 3 of 24 elements.

emaLength
10
lowThreshold
0.4
highThreshold
0.615
maxSessions
10

Call#

calculate(rows, emaLength, lowThreshold, highThreshold, maxSessions)

Returns#

object with 5 fields: status, trigger_date, ema, sessions, series

{
  "status": "thrust",
  "trigger_date": "2026-01-28",
  "ema": 0.6648021169863199,
  "sessions": 6,
  "series": [
    {
      "date": "2026-01-05",
      "ratio": 0.52,
      "ema": 0.52,
      "state": "idle"
    },
    {
      "date": "2026-01-06",
      "ratio": 0.5,
      "ema": 0.5163636363636364,
      "state": "idle"
    },
    {
      "date": "2026-01-07",
      "ratio": 0.48,
      "ema": 0.5097520661157025,
      "state": "idle"
    }
  ]
}

Diagrams#

Zweig Breadth Thrust — decision boundary
Zweig Breadth Thrust — family map

Calculation flow#

Calculation Flow — Zweig Breadth Thrust
flowchart LR
    A["Ordered A and D counts"] --> B["Breadth ratio A/(A+D)"]
    B --> C["Update EMA10"]
    C --> D{"EMA < 0.400?"}
    D -->|"Yes"| E["Arm or refresh clock"]
    D -->|"No"| F{"Armed and EMA > 0.615?"}
    E --> G["Advance session age"]
    G --> F
    F -->|"Yes, age ≤ 10"| H["Publish thrust now"]
    F -->|"No, age > 10"| I["Expire"]
    F -->|"No, age ≤ 10"| G

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#

  • Claim-to-source map
  • Advance-Decline Indicators — StockCharts ChartSchool
  • Advance Decline Ratio Indicators, Chapter 5 — Greg Morris, StockCharts
  • Historical-example decision

The rest of the Thrust and Pressure family#