# Precisión de cálculos

## TL;DR

La API de AstroWay utiliza **Swiss Ephemeris** (código C oficial de Astrodienst,
creadores de astro.com) — el mismo motor que los astrólogos profesionales han
usado durante más de 30 años en **Solar Fire ($495), Kepler ($995), Astro Gold
($29.99/mes) y Janus**. Lo compilamos a WebAssembly y lo exponemos mediante una
capa REST, sin intermediarios ni sobreprecios. Cada endpoint básico de cálculo
está cubierto por pruebas de regresión *snapshot*; la precisión del motor se
verifica mediante **triangulación** con tres fuentes independientes + frente al
**Catálogo de Eclipses de la NASA de 5 Milenios**:

- **Posiciones planetarias**: `< 0.1 segundos de arco` vs el CGI oficial
  swetest de Astrodienst
- **Cúspides de casas Placidus**: coincidencia exacta `0.000"`
- **Eclipses**: `< 1 minuto` vs NASA Eclipse Catalog
- **Líneas ACG**: `< 1.5 km` en el ecuador vs swetest
- **Amanecer/atardecer**: `< 10 segundos` vs timeanddate.com
- **VOC lunar, ingressos y conjunciones planetarias**: precisión de fracción de
  segundo

## Motor

| Componente | Valor |
|------------|-------|
| Biblioteca | Código C Swiss Ephemeris (aloistr/swisseph) |
| Versión | código C upstream de Astrodienst |
| Bindings | swisseph-wasm (WebAssembly en Node.js) |
| Efemérides | DE431 JPL (vía archivos .se1) |
| Fallback | Analítico Moshier (para fechas fuera de 1800-2399) |
| Compartir código | Shared `@/core` con app.astroway.info — mismo motor, dos transportes |

## Metodología

La precisión se verifica mediante **triangulación**: comparación con tres fuentes
independientes:

### 1. swetest CGI (referencia)

Implementación oficial de referencia de Swiss Ephemeris de Astrodienst — los
mismos creadores de **Astro.com** y que sirve a millones de astrólogos en todo
el mundo. La fuente pública más autorizada. Nuestro motor es **idéntico**
(drift de 0.00–0.07 segundos de arco).

### 2. Kerykeion (Python)

Librería independiente en Python que usa bindings `pyswisseph` en lugar de nuestro
WASM. Confirma que nuestra capa WASM no distorsiona los datos.

### 3. API Prokerala

API remota de Swiss Ephemeris (ayanamsa Lahiri sidéreo). El drift sistemático de
8–17 segundos de arco está relacionado con diferentes versiones de la fórmula
Lahiri ayanamsa, **no** con la precisión del motor.

## Resultados de la triangulación

| Carta | vs swetest (Astrodienst) | vs Kerykeion (Python) | vs API Prokerala |
|-------|--------------------------|-----------------------|------------------|
| Monroe 1926   | **0.00"** | 0.19" | 16.95" (sistemático) |
| Diana 1961    | **0.00"** | 0.69" | 8.18" (sistemático)  |
| Einstein 1879 | 0.07"     | Artefacto LMT de Kerykeion | 14.96" (sistemático) |

## Conjunto de regresión a nivel de endpoints

Cada endpoint básico de cálculo está cubierto por pruebas *snapshot* congeladas
en 3 cartas de referencia (Monroe / Diana / Einstein) = **{siteMeta.snapshotCount} snapshots**.

La suite de snapshots detecta:

- **Errores de mapeo de datos de entrada** — ID de planeta incorrecto, UT,
  sistema de casas
- **Post-procesamiento** — redondeo, conversión de unidades, pérdida de signo
- **Divergencia de valores por defecto** — nodo medio vs nodo verdadero,
  geocéntrico vs topocéntrico
- **Cambios en el esquema** — validación que permitió una forma incorrecta
- **Despliegue obsoleto** — dist de producción no coincide con el código

Tolerancia: `5e-5°` (≈0.18 segundos de arco) por defecto para todos los campos
numéricos.

## Benchmarks detallados

### Posiciones planetarias (trópico, vs swetest)

| Carta | Fecha | Drift máximo |
|-------|-------|--------------|
| Marilyn Monroe  | 1926-06-01 | **0.00"** |
| Princess Diana  | 1961-07-01 | **0.00"** |
| Albert Einstein | 1879-03-14 | 0.07"     |

### Cúspides de casas Placidus (vs swetest)

| Carta | drift ASC | drift MC | Drift máximo de cúspide |
|-------|-----------|----------|-------------------------|
| Monroe | 0.000" | 0.000" | 0.000" |
| Diana  | 0.000" | 0.000" | 0.000" |

### Eclipses (vs Catálogo de Eclipses de la NASA de 5 Milenios)

| Evento | Máximo NASA | Máximo nuestro | Drift |
|--------|-------------|----------------|-------|
| Eclipse total lunar 2025-03-14  | 06:58 UT | 06:58 UT | 0.8 min |
| Eclipse parcial solar 2025-03-29 | 10:47 UT | 10:47 UT | 0.5 min |
| Eclipse total lunar 2025-09-07  | 18:11 UT | 18:11 UT | 0.8 min |
| Eclipse parcial solar 2025-09-21 | 19:41 UT | 19:42 UT | 1.0 min |

### Astrocartografía (vs fórmula RA de swetest)

Todas las líneas MC/IC/ASC/DSC usan la fórmula correcta
`longitude = RA − GMST` (estándar de Kenneth Bowser). Drift frente al
referente: **< 1.5 km** en el ecuador para todos los planetas.

### Amanecer / Atardecer (vs timeanddate.com)

| Ubicación | Fecha | Parámetro | Drift |
|-----------|-------|-----------|-------|
| Londres | 2026-04-15 | Amanecer | 0.6 s |
| Londres | 2026-04-15 | Atardecer | 9 s   |

**Ubicaciones polares** (|lat| > 66.5°) devuelven automáticamente `polarState` +
una advertencia de que las horas planetarias normales no están definidas.

### Órbitas de aspectos

AstroWay usa **órbitas variables** por planeta (regla MIN de dos planetas),
como en ZET9 y astro.com. Órbitas por defecto (para carta natal):

| Aspecto | Sol | Luna | Interior | Júpiter | Exterior |
|---------|-----|------|----------|---------|----------|
| Conjunción | 12°  | 10° | 5° | 8° | 5° |
| Sextil     | 6.5° | 6°  | 5° | 5° | 5° |
| Cuadratura | 10°  | 8°  | 5° | 7° | 5° |
| Trígono    | 12°  | 8°  | 5° | 5° | 5° |
| Oposición  | 12°  | 10° | 5° | 8° | 5° |

Los aspectos menores (36°, 40°, 45°, 72°, 108°, 135°, 144°) están **desactivados
por defecto**. Se activan explícitamente mediante `ALL_ASPECTS`.

## Latitudes polares

Para |lat| > 66.5° los sistemas Placidus / Koch / Regiomontanus no están
matemáticamente definidos. En estos casos, Swiss Ephemeris devuelve
automáticamente Porphyry, y nuestra API añade una advertencia:

```json
{
  "system": "P",
  "warning": "El sistema Placidus no está definido para lat=68.96° (> 66.5°). Swiss Ephemeris ha sustituido Porphyry..."
}
```

## Verificación continua

La regresión se verifica **en cada PR** mediante CI:

- `api-calc/tests/endpoints/` — {siteMeta.snapshotCount} snapshots frente a cartas
  de referencia (Monroe / Diana / Einstein) + sinastría / composite / Davison
- `.github/workflows/api-accuracy.yml` — ejecución automática en PR
- Triangulación frente a swetest CGI + Kerykeion — semanalmente
- Monitoreo upstream de Swiss Ephemeris mediante Dependabot

## Limitaciones conocidas

- **Fechas fuera de rango** (antes de 1800 y después de 2399): se usa el
  analítico Moshier, precisión ~0.1" (frente a < 0.01" para SWIEPH con archivos
  DE431)
- **Lilith verdadera (id=13) vs Lilith media (id=12)**: diferencia de hasta 12° —
  por defecto se usa Lilith media (comportamiento estable), Lilith verdadera
  disponible mediante `planetIds: [13]`
- **Topocéntrico vs geocéntrico**: por defecto geocéntrico

## Enlaces

- Swiss Ephemeris: https://www.astro.com/swisseph/
- swetest CGI: https://www.astro.com/swisseph/swetest.htm
- Catálogo de eclipses de la NASA: https://eclipse.gsfc.nasa.gov/
- Kerykeion: https://github.com/g-battaglia/kerykeion
- Astrodienst: https://www.astro.com/

## Contacto

Para preguntas sobre precisión: escribe a support@astroway.info con los datos de
la carta y la fuente de referencia esperada (astro.com u otra fuente
autorizada).
