Calculation evidence / November 1, 2026

Birth chart calculation accuracy and evidence

LunarOtter calculates astronomical positions with astronomy-engine 2.1.19. We compare those positions with NASA JPL Horizons, check chart angles separately, and test repeatability. These checks describe numerical calculations. They do not measure the accuracy of astrological interpretations.

Engine, coordinates, and time

Our MIT-licensed engine is astronomy-engine 2.1.19, using conventions v2: Western tropical zodiac, geocentric apparent positions, and Whole Sign houses. The Ascendant and Midheaven are calculated separately. The Midheaven is not assumed to be the tenth-house boundary.

Historical civil-time conversion uses bundled IANA time-zone database 2026f. We resolve the local birth time with the rules for that date, rather than today’s offset. Repeated or nonexistent local times require an explicit choice. Pre-1970 records receive a historical-rules notice.

UTC approximates UT1; the engine’s Espenak-Meeus Delta T model supplies terrestrial time (TT). The comparisons below use shared explicit TT to isolate position and frame differences.

NASA JPL Horizons: fixed-epoch comparison

24 fixed instants from 1900 through 2025, with ten bodies at each instant, give 240 longitude/latitude pairs. Horizons queries use observer quantity 31, geocenter 500@399, AIRLESS, ICRF, and apparent ecliptic/equinox of date. No topocentric parallax or refraction is applied.

Absolute differences below are in degrees. Each body has 24 samples. Nearest-rank p99 equals the maximum with this sample size; it is not evidence that the error is constant. The acceptance bound is 0.01° for each coordinate, not a guarantee about an individual birth time.

Fixed-epoch JPL comparison, degrees
BodyLongitude maxLongitude p99Latitude maxLatitude p99
Sun0.0004183750.0004183750.0003272120.000327212
Moon0.0006203770.0006203770.0002016560.000201656
Mercury0.0033618900.0033618900.0011456810.001145681
Venus0.0017897220.0017897220.0016430260.001643026
Mars0.0017104700.0017104700.0019860730.001986073
Jupiter0.0016524270.0016524270.0024852990.002485299
Saturn0.0021416560.0021416560.0053666310.005366631
Uranus0.0030631730.0030631730.0044026150.004402615
Neptune0.0047805560.0047805560.0026626370.002662637
Pluto0.0010112970.0010112970.0003024950.000302495

Reference: NASA JPL Horizons manual and Horizons API. The small residuals include analytical orbital and lunar approximations, aberration and frame-model differences.

Independent release check: new dates and places

A separate audit used 50 newly seeded instants across 10 places, producing 500 charts. The earliest instant was 1901-05-29T08:56:00.000Z and the latest was 2022-08-04T19:16:00.000Z. These inputs do not overlap the frozen development charts. The city-center coordinates are approximate synthetic inputs, rather than verified Amazon Location results.

Places: Reykjanesbaer, Valparaiso, Dunedin, Antananarivo, Thimphu, Tashkent, Porto, Juneau, Hobart, Accra.

Fresh Horizons requests compared 100 longitude/latitude pairs at ten of these epochs, with zero sign disagreements. This is a separate sample from the fixed-epoch table above.

Independent release JPL comparison, degrees, ten samples per body
BodyLongitude maxLatitude max
Sun0.0002017350.000242314
Moon0.0005363510.000145901
Mercury0.0009669380.000572313
Venus0.0011041680.001386495
Mars0.0009142680.000514995
Jupiter0.0022087550.001907321
Saturn0.0025105800.005055561
Uranus0.0014649190.004927462
Neptune0.0049328930.002578242
Pluto0.0009214810.000274348

Ascendant and Midheaven checks

Horizons body positions do not validate a rising sign. We check angles with a separate Meeus GMST, equation-of-equinoxes, and vector-plane-intersection path. This shares nutation and obliquity with the engine, so it is an independent geometry check, not an independent astronomical model.

304 development charts, degrees
ComparisonMaxp99
Recorded development Ascendant, including time-model change0.0051403280.003070275
Recorded development MC, including time-model change0.0028316780.002573351
Recorded Ascendant, shared time0.0001657290.000068868
Recorded MC, shared time0.0000610020.000051843
Independent formula Ascendant0.0001916260.000143578
Independent formula MC0.0000838170.000080181

The recorded development positions came from Swiss Ephemeris 2.10.03 and remain reference numbers only. Shared-time and independent checks use a 0.002° tolerance. The full migration allows 0.03° because it includes the time-model change. Five mean-obliquity textbook fixtures are checked separately within 0.03°.

Across the 500 new charts, the independent path’s maximum Ascendant difference was 0.0002411556766901413° and MC difference was 0.0000852884290907241°, both below 0.002°.

Repeatable inputs, repeatable output

Identical normalized inputs, settings, and versions produce identical canonical chart and reading content. Two fresh processes using different host time zones produced 3,638,200 identical canonical bytes for the 500-chart audit. Random identifiers, timestamps, and PDF metadata sit outside this content contract.

SHA-256: 405ff5334eea6c41648f24564bc5108865cad0f6c4c02d265afa38cf02451504

Three committed full-chart snapshots from 1900, 1984, and 2025 also run at startup. Missing, nonfinite, or changed output fails the engine self-test; numeric tolerance is 1e-9, with exact labels and structure.

Supported range and limits

Supported birth dates run from January 1, 1900 through today in the birth time zone. A complete chart requires latitude within 66° north or south. Beyond that range, we provide supported Sun and Moon information without rising or houses.

Known time uses the stated minute. Approximate time checks a chosen ±15-minute, ±30-minute, ±1-hour, or ±2-hour interval. Purchase requires stable signs, houses, retrograde flags, angles, and aspect memberships throughout that interval. Matching endpoints alone is insufficient.

Unknown time checks the entire local birth day, including short or long clock-change days. We show stable Sun and Moon signs, or possible signs when they change, without guessing rising or houses. A complete reading is unavailable for an unknown time.

Numerical agreement cannot fix an incorrect birth record or uncertain historical civil-time rules. Astrology provides a symbolic framework for reflection; these tests validate calculation behavior.

How to reproduce

The checked-in evidence sources are docs/reference/calculation-evidence.json and docs/reference/verify/results.json, described in docs/CALCULATION-EVIDENCE.md and docs/VERIFICATION.md. A test compares this page’s data with those files so the published numbers cannot silently drift.

npm ci
npm run verify:calculations
npx tsx scripts/verify-independent.ts
npx tsx scripts/verify-edge-cases.ts
npm test

These checks use committed references offline. To deliberately refresh the independent NASA reference, run npx tsx scripts/verify-independent.ts --prepare, then python3 scripts/verify-horizons.py, then npx tsx scripts/verify-independent.ts. Retain the raw responses, exact query URLs, and access timestamps, and review evidence changes before updating the public figures.

Versioned calculation conventions · Methodology · Find your Big Three free