A canonical, well-specified, cross-language (Python + TypeScript) reference implementation of index divisor initialization. The divisor is the only state an index carries from one day to the next, and every later level is computed from the divisor as published — not the true one. This module sets the divisor in exact decimal arithmetic, then answers the questions that decide whether it was set well: how many decimals to publish, which divisors a run of published levels is consistent with, and how far a rounded divisor drifts as the index grows.
📖 Full article (canonical): Index Divisor Initialization — The Fintech Builder
This repository is the runnable, production-oriented companion to that article. The article teaches the concept; this repo is the code you install and build on.
🧭 Browse all algorithms: Awesome FinTech Algorithms — the full index of the library.
🗂️ This algorithm's domain: Index and Benchmark Engineering › Index Initialization and Continuity
📥 Just want to call it? It also ships in the fintech-algorithms npm package — see Two ways to use this.
| Catalog topic | D03-F01-A02 |
| Domain | D03 — Index and Benchmark Engineering |
| Family | D03-F01 — Index Initialization and Continuity |
| Difficulty | 2 / 5 |
| Languages | Python, TypeScript |
- The one number an index remembers
- What the reference got wrong
- Two ways to use this
- Install
- Quickstart
- Views: the analysis surface
- Input shape
- API reference
- Edge cases & limitations
- Testing
- Related algorithms
- License
level = market value / divisor
divisor = market value / base level (at launch)
At launch the level is the base level by construction. Afterwards the divisor is all the index remembers: prices move the market value and the level follows; non-market changes move the market value too, and the divisor is rescaled so the level does not.
Divisor initialization
market value 125000000
divisor 125000
index level 1000
A divisor of 125,000 is exact. Most are not — and then the number of decimals it is published with becomes part of the index definition.
All confirmed by running it:
- NaN passed.
float("nan") <= 0is false, so a NaN market value came back as a NaN divisor — not even valid JSON. The TypeScript twin refused the same input, so the reference disagreed with itself. Here only finite JSON numbers are accepted. - A divisor of zero was published. A market value of 0.0001 over a base level of 1000 is a true
divisor of 1e-7, which both twins returned as
0. Here it is refused. - Coercion. Strings and booleans were converted silently.
Arithmetic is exact: every JSON number is read as the decimal it spells, all arithmetic runs in exact
fractions, and rounding happens once, at publication, to six decimals, half away from zero. A market
value of 1.0000005 over a base of 1 publishes a divisor of 1.000001; its binary double is just
below the half.
This repo is the production home: the full implementation, the analysis surface below, and 148 tests across two languages.
The fintech-algorithms npm package
ships the same topic as one import among several hundred.
fintech-algorithms/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization
Python
cd python
pip install -e ".[dev]"TypeScript
cd typescript
npm install
npm run buildfrom fintech_index_divisor import calculate, divisor_precision_report
calculate({"marketValue": 125000000, "baseLevel": 1000})
# {'marketValue': 125000000, 'divisor': 125000, 'indexLevel': 1000}
divisor_precision_report({"marketValue": 1234.56789, "baseLevel": 1000})["minimumDecimalsToReproduceBaseLevel"]
# 8TypeScript is the same call:
import { calculate, divisorPrecisionReport } from 'fintech-index-divisor';
calculate({ marketValue: 125000000, baseLevel: 1000 }); // { marketValue: 125000000, divisor: 125000, indexLevel: 1000 }Run the tour in either language:
cd python && python examples/quickstart.py
cd typescript && npm run exampleBoth print byte-identical output.
A small divisor carries the whole level in its last digits:
0 dp divisor 1 level 1234.567890000000 error 2345.6789 bp reproduces false
2 dp divisor 1.23 level 1003.713731707317 error 37.137317073 bp reproduces false
4 dp divisor 1.2346 level 999.973991576219 error -0.260084238 bp reproduces false
6 dp divisor 1.234568 level 999.999910900007 error -0.000891 bp reproduces false
7 dp divisor 1.2345679 level 999.999991900000 error -0.000081 bp reproduces false
8 dp divisor 1.23456789 level 1000.000000000000 error 0 bp reproduces true
minimum decimals to reproduce the base level: 8
The error scales with level / divisor: the same six decimals are more than enough for a divisor of
125,000. Published divisors are returned as strings — 17857142.85714286 and
17857142.8571428571 are the same double.
The reverse problem, from outside the index. A level published to d decimals, rounded half away from
zero, stands for a true level in [L − h, L + h). With the market value known, the divisor lies in
(MV / (L + h), MV / (L − h)]. Intersect over every observation:
consistent true: divisor in (17857141.643350976141, 17857144.074232829487]
claimed 17857142.857143 fits: true
with the third level from a divisor 0.1% higher: consistent false, impossible from observation 2
An empty intersection proves the divisor changed between observations, and
firstInconsistentObservation says where it became impossible — a way to detect an unannounced
adjustment in a vendor's published series. A claimed divisor is checked against every observation.
The drift between the level from the true divisor and from the six-decimal one is
MV × (1/published − 1/true): proportional to the market value.
market value 125000000 level 7 from published divisor 7 drift 0
market value 1250000000000 level 70000 from published divisor 70000 drift -0.00000000056
market value 1250000000000000 level 70000000 from published divisor 69999999.999999 drift -0.00000056
ok theMarketValueIsTheInput
FAIL theDivisorIsMarketValueOverBaseLevel
ok theLevelIsTheBaseLevel
FAIL thePublishedDivisorReproducesTheBaseLevel
That is a file that published the divisor as 17857000 for a base level of 7. A divisor published to
two decimals (17857142.86) fails only the first divisor check: it is not the six-decimal number,
but it still reproduces the level.
implied_divisor_range takes [{"marketValue": ..., "level": ...}], where each level has at most
decimals decimal places.
Python — from fintech_index_divisor import ...
| function | returns |
|---|---|
calculate(data) / initialize_divisor(data) |
marketValue, divisor, indexLevel |
divisor_precision_report(data, decimals=None) |
per precision: published divisor, level, error, reproduction; minimum decimals |
implied_divisor_range(observations, decimals=6, claimed_divisor=None) |
the consistent divisor interval, binding observations, first inconsistency |
level_series(data, market_values) |
levels from the true and published divisor, drift and returns |
verify_divisor_initialization(data, result=None) |
four checks; pass result to audit a supplied answer |
validate_request · to_fraction · render · number · trim · scaled |
validation and exact arithmetic |
TypeScript — import { ... } from 'fintech-index-divisor'
The same functions in camelCase (initializeDivisor, impliedDivisorRange, ...). Exact state is a
Rational with bigint numerator and denominator.
- Interval ends are rendered to 12 decimals. The comparisons behind
consistentandclaimedDivisorare exact; only the displayed bounds are rounded. - Known market values are assumed.
implied_divisor_rangetreats each market value as exact. If your market values are themselves rounded, widen the interval accordingly. - Half away from zero is the assumed publication rule. A vendor that rounds half to even can publish a level one unit different at an exact tie; the interval ends would move by that tie.
- Large published numbers are doubles. Above ~9e9 a six-decimal value is finer than a double can hold; the published number is the nearest double to the correctly rounded decimal.
decimalsaccepts 0–12.6.0is accepted as6, because another language's JSON reader cannot tell them apart.
cd python && pytest -q # 74 tests
cd typescript && npm test # 74 testsBoth suites reproduce the canonical fixture byte for byte.
The two implementations were compared directly across 1,500 scenarios and 7,500 calls — the initialization and all four surfaces, valid and malformed, including 323 consistent implied ranges — and their canonical JSON output is byte-identical. The examples are byte-identical too.
The Python port was differentially tested against the reference engine on 12,000 generated
requests with zero unexplained divergences. An independent Decimal oracle confirmed all 9,607
results the port returned. Every divergence is classified by name:
| divergence | cases | what happened |
|---|---|---|
| coercion | 617 | reference accepted strings and booleans |
| double resolution | 414 | both correct to the decimal; neighbouring doubles above ~9e9 |
| zero published divisor | 299 | reference returned a divisor of 0 |
| non-finite | 161 | reference accepted NaN or infinity |
| rounding rule | 86 | reference rounded a binary float; port rounds the exact decimal half away from zero |
Same family — D03-F01 Index Initialization and Continuity
- Base-Date/Base-Value Initialization — the basket, its float-adjusted market value, and the base date.
- Divisor Continuity Adjustment — rescaling the divisor so a non-market change does not move the level.
- Corporate-Action Divisor Bridge — the divisor across a special dividend, rights issue or spin-off.
- Intraday Index-Level Calculation — the level tick by tick, with a fixed divisor.
MIT — see LICENSE.
{ "marketValue": 125000000, // > 0, finite JSON number "baseLevel": 1000 // > 0, finite JSON number }