Negative Volume Index
Install and import#
npm install fintech-algorithmsimport { negativeVolumeIndex } from "fintech-algorithms/technical-indicators/volume-indicators/negative-volume-index";Signature#
negativeVolumeIndex(input)Tracks a cumulative index seeded at 1000 that compounds the close-to-close return only on bars whose volume fell against the prior bar.
Parameters#
| Name | Type | Notes |
|---|---|---|
input | TopicInput | bars needs timestamp, close and volume. This topic reads no parameters of its own; the family reads period (default 14), fast_period (default 3) and slow_period (default 10, minimum fast_period + 1) for every volume topic, so a non-integer or out-of-range value throws even when this topic ignores it. |
Returns#
TopicResult
series holds a single value, and latest its last element. The first bar is 1000; each later bar multiplies the running level by close / prior close when volume fell, and otherwise carries the previous level forward unchanged (as it also does when the prior close is 0). No element is ever null, so there is no warm-up.
Warm-up#
The first none positions are 1000 on the first bar. ready_at is 0. The series is a level, not a signal, so the seed is a real value rather than a placeholder.
Errors#
- When a bar carries a negative
volume— throws Error - When a
closeis not a finite number — throws Error - When two bars share a timestamp, or the bars are out of order — throws Error
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#
{
"bars": [
{
"timestamp": "2024-01-02",
"basis": "synthetic-unadjusted",
"open": 100,
"high": 101.45,
"low": 98.695,
"close": 100,
"volume": 750000,
"benchmark": 200
},
{
"timestamp": "2024-01-03",
"basis": "synthetic-unadjusted",
"open": 101.49111452,
"high": 103.38381693,
"low": 100.05480022,
"close": 101.78791214,
"volume": 795117,
"benchmark": 200.56326135
},
{
"timestamp": "2024-01-04",
"basis": "synthetic-unadjusted",
"open": 102.45519048,
"high": 104.6701838,
"low": 100.91147007,
"close": 102.9549389,
"volume": 840234,
"benchmark": 201.11020913
}
],
"parameters": {}
}Call#
negativeVolumeIndex(input)Returns#
object with 9 fields: topic_id, title, state, ready, ready_at, series, latest, parameters, …
{
"topic_id": "D07-F05-A10",
"title": "Negative Volume Index",
"state": "calculated",
"ready": true,
"ready_at": 0,
"series": {
"value": [1000, 1000, 1000, 1000, 1000, 1000]
},
"latest": {
"value": 991.0425084378836
},
"parameters": {},
"diagnostics": {
"causal": true,
"input_count": 96
}
}Diagrams#
Calculation flow#
Negative Volume Index calculation flow
flowchart LR
A["basis-consistent OHLCV observations with venue/session cov"] --> B["Validate order, basis, and finite values"]
B --> C["Apply the selected Negative Volume Index convention"]
C --> D["Emit value, readiness, and diagnostics"]
D --> E["Interpret descriptively; test outcomes separately"]
B -->|invalid or insufficient| X["Withhold output with a reason"]
Negative Volume Index readiness and evidence states
stateDiagram-v2
[*] --> Waiting
Waiting --> Ready: enough valid causal observations
Waiting --> Rejected: malformed or unsupported input
Ready --> Calculated: selected formula applied
Calculated --> Interpreted: diagnostic and limitation retained
Interpreted --> Ready: next observation arrives
Rejected --> Waiting: corrected input and deterministic reset
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.
References#
- TA-Lib function groups — see linked primary or authoritative record
- TA-Lib C/C++ API — see linked primary or authoritative record
- TA-Lib maintained source — see linked primary or authoritative record
- Evidence decision
- Level 1 evidence map