Skip to content

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Fintech Index Divisor Initialization — Index Engineering Algorithm

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.

Python TypeScript License Tests

📖 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

Table of contents


The one number an index remembers

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.


What the reference got wrong

All confirmed by running it:

  • NaN passed. float("nan") <= 0 is 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.


Two ways to use this

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

Install

Python

cd python
pip install -e ".[dev]"

TypeScript

cd typescript
npm install
npm run build

Quickstart

from 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"]
# 8

TypeScript 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 example

Both print byte-identical output.


Views: the analysis surface

divisor_precision_report — how many decimals is enough?

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.

implied_divisor_range — which divisors fit what was published?

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.

level_series — drift from a rounded divisor

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

verify_divisor_initialization — four checks, and an audit mode

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.


Input shape

{
  "marketValue": 125000000,   // > 0, finite JSON number
  "baseLevel": 1000           // > 0, finite JSON number
}

implied_divisor_range takes [{"marketValue": ..., "level": ...}], where each level has at most decimals decimal places.


API reference

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.


Edge cases & limitations

  • Interval ends are rendered to 12 decimals. The comparisons behind consistent and claimedDivisor are exact; only the displayed bounds are rounded.
  • Known market values are assumed. implied_divisor_range treats 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.
  • decimals accepts 0–12. 6.0 is accepted as 6, because another language's JSON reader cannot tell them apart.

Testing

cd python && pytest -q          # 74 tests
cd typescript && npm test       # 74 tests

Both 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

Related algorithms

Same family — D03-F01 Index Initialization and Continuity

🧭 Browse all algorithms →


License

MIT — see LICENSE.