OHLC Consistency Validator
Install and import
npm install fintech-algorithmsimport { validateBars } from "fintech-algorithms/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator";Signature
validateBars(bars, config)Checks each bar against the invariants an OHLC bar must satisfy — high is the maximum, low is the minimum, open and close lie between them — with a tick-size tolerance so representable rounding is not reported as corruption.
Parameters
| Name | Type | Notes |
|---|---|---|
bars | OhlcRow[] | Bars to check, each carrying bar_id, source, symbol, timestamp and the four prices. |
config | { tickSize: number; toleranceTicks: number; priceScale: number } | tickSize is the instrument's minimum increment and toleranceTicks how many of them a value may be out before it is a violation. priceScale fixes the decimal scale used for comparison so floating-point representation does not create phantom failures. |
Returns
Verdict[] · length same-as-input
One verdict per bar, naming which invariant failed and by how much. Returns one verdict per input row rather than throwing, so a single bad record cannot abort the batch — and cannot pass unnoticed either.
Errors
- When tickSize is not positive — 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
[
{
"bar_id": "B01",
"source": "SYNTHETIC",
"symbol": "DEMO",
"timestamp": "2026-07-20T09:30:00Z",
"open": 100,
"high": 102,
"low": 99,
"close": 101,
"volume": 1000
},
{
"bar_id": "B02",
"source": "SYNTHETIC",
"symbol": "DEMO",
"timestamp": "2026-07-20T09:31:00Z",
"open": 100.01,
"high": 100,
"low": 99.5,
"close": 99.9,
"volume": 900
},
{
"bar_id": "B03",
"source": "SYNTHETIC",
"symbol": "DEMO",
"timestamp": "2026-07-20T09:32:00Z",
"open": 100.0101,
"high": 100,
"low": 99.5,
"close": 99.9,
"volume": 800
}
]Showing 3 of 7 elements.
{
"tickSize": 0.01,
"toleranceTicks": 1,
"priceScale": 1
}Call
validateBars(bars, config)Returns
array of 7 objects
[
{
"index": 0,
"timestamp": "2026-07-20T09:30:00Z",
"valid": true,
"issues": [],
"tolerancePriceUnits": 0.01,
"normalizedPrices": {
"open": 100,
"high": 102,
"low": 99,
"close": 101
},
"provenance": {
"source": "SYNTHETIC",
"symbol": "DEMO",
"bar_id": "B01"
},
"rawBar": {
"bar_id": "B01",
"source": "SYNTHETIC",
"symbol": "DEMO",
"timestamp": "2026-07-20T09:30:00Z",
"open": 100,
"high": 102,
"low": 99,
"close": 101,
"volume": 1000
}
},
{
"index": 1,
"timestamp": "2026-07-20T09:31:00Z",
"valid": true,
"issues": [],
"tolerancePriceUnits": 0.01,
"normalizedPrices": {
"open": 100.01,
"high": 100,
"low": 99.5,
"close": 99.9
},
"provenance": {
"source": "SYNTHETIC",
"symbol": "DEMO",
"bar_id": "B02"
},
"rawBar": {
"bar_id": "B02",
"source": "SYNTHETIC",
"symbol": "DEMO",
"timestamp": "2026-07-20T09:31:00Z",
"open": 100.01,
"high": 100,
"low": 99.5,
"close": 99.9,
"volume": 900
}
},
{
"index": 2,
"timestamp": "2026-07-20T09:32:00Z",
"valid": false,
"issues": ["HIGH_BELOW_BODY"],
"tolerancePriceUnits": 0.01,
"normalizedPrices": {
"open": 100.0101,
"high": 100,
"low": 99.5,
"close": 99.9
},
"provenance": {
"source": "SYNTHETIC",
"symbol": "DEMO",
"bar_id": "B03"
},
"rawBar": {
"bar_id": "B03",
"source": "SYNTHETIC",
"symbol": "DEMO",
"timestamp": "2026-07-20T09:32:00Z",
"open": 100.0101,
"high": 100,
"low": 99.5,
"close": 99.9,
"volume": 800
}
}
]Showing 3 of 7 elements.
Diagrams
Calculation flow
Detection, investigation, and repair flow
flowchart LR
A["Raw bar plus provenance"] --> B{"Configuration valid?"}
B -->|No| X["Reject the validation request"]
B -->|Yes| C{"Required fields valid?"}
C -->|No| D["Record field issues"]
C -->|Yes| E["Normalize price scale"]
E --> F["Evaluate all three OHLC gaps"]
D --> G["Emit detection result and raw row"]
F --> G
G --> H{"Independent evidence confirms cause?"}
H -->|No| I["Quarantine and investigate"]
H -->|Yes| J["Apply an approved versioned repair downstream"]
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
- Closing Prices Client Specification — New York Stock Exchange / Intercontinental Exchange
- Daily TAQ Client Specification — New York Stock Exchange / Intercontinental Exchange
- Final Data Quality Assurance Guidelines — U.S. Securities and Exchange Commission
- Evidence classification