No description
  • Python 90.7%
  • PLpgSQL 7.4%
  • CSS 0.6%
  • JavaScript 0.5%
  • HTML 0.4%
  • Other 0.3%
Find a file
2026-08-25 09:35:42 +02:00
.forgejo/workflows feat: isolate integration infrastructure 2026-08-24 18:47:35 +02:00
config feat: add causal M8 liquidity domain 2026-08-25 08:44:09 +02:00
datasets docs: adopt five-year preliminary data policy 2026-08-24 18:46:03 +02:00
docs docs: record consolidated ATLAS 0.36 gates 2026-08-25 09:35:42 +02:00
infra fix: align M11 PostgreSQL evidence with M7 2026-08-25 09:34:45 +02:00
src/atlas_system feat: project M8 liquidity queue in M9 2026-08-25 09:07:07 +02:00
stubs/ibapi feat: add authenticated M9 dashboard and frozen holdout workflow 2026-08-17 18:56:31 +02:00
tests test: exercise causal projections in PostgreSQL 2026-08-25 09:35:23 +02:00
.dockerignore feat: establish ATLAS phase 0 foundations 2026-08-15 16:43:14 +02:00
.editorconfig feat: establish ATLAS phase 0 foundations 2026-08-15 16:43:14 +02:00
.env.example feat: add raw-first phase 1 data acquisition 2026-08-24 17:56:05 +02:00
.gitignore feat: add authenticated M9 dashboard and frozen holdout workflow 2026-08-17 18:56:31 +02:00
AGENTS.md docs: record consolidated ATLAS 0.36 gates 2026-08-25 09:35:42 +02:00
compose.ibkr-paper-host.yaml feat: resolve flattened paper dispatches append-only 2026-08-17 22:26:19 +02:00
compose.ibkr-paper.yaml feat: resolve flattened paper dispatches append-only 2026-08-17 22:26:19 +02:00
compose.integration.yaml feat: isolate integration infrastructure 2026-08-24 18:47:35 +02:00
compose.yaml feat: add raw-first phase 1 data acquisition 2026-08-24 17:56:05 +02:00
Dockerfile feat(accounting): integrate operational M7 cycle 2026-08-18 17:35:25 +02:00
Makefile feat: enforce M7 causal execution frontier 2026-08-25 09:05:35 +02:00
pyproject.toml chore: bump ATLAS to 0.36.0 2026-08-25 09:05:35 +02:00
README.md docs: record consolidated ATLAS 0.36 gates 2026-08-25 09:35:42 +02:00

ATLAS

ATLAS es un sistema autónomo de inversión sistemática, multi-estrategia y multi-activo. Su diseño pone el control de riesgo, la trazabilidad y la paridad entre backtest, paper trading y producción por delante de cualquier señal de inversión.

Este repositorio contiene la fase 0 — Cimientos, la implementación funcional de la fase 1 — Algoritmo y los trece primeros incrementos de la fase 2 — Operativa:

  • contratos de dominio y eventos inmutables;
  • M1: pipeline de ingesta con validación fail-safe;
  • M2: esquema inicial para TimescaleDB, Redis Streams y almacenamiento de objetos S3 local con SeaweedFS;
  • M10: backtesting orientado a eventos, evidencia segmentada y registro de ensayos append-only con congelación de candidato y holdout único;
  • API mínima con salud, disponibilidad, métricas e ingesta;
  • backfill histórico de acciones/ETFs mediante Massive y cripto mediante Kraken, archivando la respuesta original en S3 antes de normalizarla;
  • calendario XNYS con festivos y cierres anticipados, detección/reparación idempotente de huecos y registro inmutable de splits/dividendos;
  • entorno reproducible con Docker Compose y CI para Forgejo.
  • indicadores y detector de régimen deterministas;
  • construcción automática de características desde barras normalizadas de M2;
  • S1 momentum relativo con ranking, pesos inversos a ATR, trailing stop y explicaciones auditables.
  • S2 Donchian con modo defensivo, S3 reversión de corto plazo y S4 tendencia cripto, todos solo largos, con stops obligatorios y salidas deterministas.
  • M4 con ensemble adaptativo acotado, gating por régimen, sizing por riesgo, volatilidad y ¼-Kelly, bandas y límites de concentración.
  • M5 como proceso HTTP independiente y fail-safe, con drawdowns, cooldown, recuperación gradual, circuit breakers, HALT y kill switch.
  • validador obligatorio esquema 2.1 para roles development_core, regime_warmup y frozen_holdout, fronteras de proveedor, walk-forward 3+1, elegibilidad explícita de artefactos, métricas OOS separadas, perturbaciones ±20% y Monte Carlo determinista de 1.000 remuestreos.
  • núcleo M6 broker-neutral con planificación sell-first, límites ±0,2%, TWAP, stops obligatorios y simulador determinista e idempotente sin acceso a red.
  • journal M6 append-only en PostgreSQL: reserva previa del plan, persistencia atómica de resultados/fills/stops/reconciliaciones y replay durable de informes terminados tras reinicio.
  • proceso M6 independiente con comando causal M4→M5→M6, heartbeat auditable, readiness sobre sus dependencias y latch fail-closed que comunica incidentes a HALT en M5.
  • scheduler M6 durable: acciones en la siguiente apertura XNYS, cripto inmediata, separación TWAP real, dispatch append-only antes de cada efecto y recuperación por client_order_id sin reenvío ambiguo; cancelación durable antes del primer dispatch y modo paper controlado de una sola acción configurada durante una sesión XNYS activa, ambos cerrados por defecto.
  • máquina de estados IBKR paper detrás de un gateway SDK: orderRef causal, estados parciales/terminales explícitos, comisión observada, reprecio y cancelación confirmada, recuperación y stops broker-resident fail-closed.
  • ciclo durable de stops: target causal por posición, alta, redimensionado y cancelación broker-neutral, persist-before-effect, recuperación sin reenvío y reconciliación exacta antes de cerrar un plan.
  • transporte oficial IBKR paper opcional: callbacks de cuenta, instrumentos, órdenes, ejecuciones, comisiones y stops; selección explícita en M6, Gateway gráfico en el host y M6 aislado en Docker sin incorporar artefactos licenciados a las imágenes.
  • núcleo M7 broker-neutral: caja y posiciones multimoneda, lotes y exportación FIFO, NAV con precios/FX explícitos, P&L, costes, reconciliación fail-closed y persistencia append-only del último RiskState.
  • ciclo M7 operativo en proceso independiente: recupera informes terminales del journal M6, reserva cada comando antes de contabilizar, exige caja/contextos de fill/precios/FX explícitos, persiste NAV intradía y un cierre diario único, y activa HALT M5 antes de publicar si la reconciliación es insegura.
  • frontera contable causal entre planes M6: compara únicamente caja nativa y posiciones iniciales contra el último plan MATCHED; una base obsoleta con fills termina en CAUSAL_CONFLICT/HALT sin NAV ni avance, y los reintentos no duplican fills ni el acuse M5.
  • replay vertical causal y ejecutable S4→M4→M5→M6→M7: compone el dominio real contra un fixture BTC/USD sintético fijado por hash, conserva la traza append-only y recupera tras reinicio sin duplicar fills, caja, stops o NAV. Su recibo siempre es audit_only, passed=false: no es un backtest, una puerta cuantitativa ni una prueba paper.
  • M9 como API y dashboard responsive autenticado con contraseña scrypt, TOTP, sesión segura, CSRF y WebSocket; proyecta NAV, valoración, P&L/costes y RiskState oficiales M7, mantiene M6 para actividad y fallback degradado, y consume la cola durable M8 mediante una proyección PostgreSQL M9-owned estrictamente read-only. Los hechos futuros o contradictorios no se muestran parcialmente: la cola queda UNAVAILABLE. No inventa métricas de retornos.
  • M8 contra simulador: cola append-only de aportaciones y retiradas, reservas atómicas por moneda, cinco tramos exactos de 20%, buffer 3/5/10, constraints monetarios aplicados por M4 y validados por M5 antes de cualquier plan M6, recovery por identidad y settlement final solo tras el hecho M7 exacto. El snapshot de caja, el target causal M4, las posiciones y la evidencia de salida declaran source=simulator_injected; su validación contra M7 no los convierte en una proyección productiva.
  • núcleo M11 broker-neutral y append-only para incidentes M5/M6/M7 y la futura M8, watchdog estricto de heartbeats M5/M6, veto M5 y alertas recuperables por identidad, liberación auditada que nunca reabre riesgo y API exclusivamente read-only. Los adaptadores/verificador productivos siguen pendientes.
  • auditoría SEC EDGAR raw-first de submissions y CompanyFacts, con CIK, acceptance time y enmiendas point-in-time; el piloto rechazó Stooq antes de descargar precios por licencia y semántica de ajustes incompletas.
  • catálogo append-only de adquisiciones, procedencia raw, identidades FIGI y universos point-in-time; orquestadores de Fase 1 para Massive, SEC, Kraken Archive y la auditoría cerrada de rankings cripto.
  • D1 raw-first de index-constitution, siempre audit-only, y D2 source-neutral para incorporar evidencia local de autoridad/corroboración, reconstruir membresía bitemporal con FIGI y publicar atómicamente solo un derivado revisado. Incluso PROMOTED/validation_eligible conserva passed=false.

ATLAS no garantiza beneficios y todavía no está autorizado para operar con dinero real. Las puertas de validación de la especificación son obligatorias.

Requisitos

  • Python 3.12
  • Docker con Docker Compose

Puesta en marcha

python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -e '.[dev]'
cp .env.example .env
make check
make smoke
make up
make migrate  # aplica migraciones repetibles a volúmenes existentes
make integration-up
make integration
make integration-down

La API queda en http://localhost:8000, Prometheus en http://localhost:9090, Grafana en http://localhost:3000, el endpoint S3 de SeaweedFS en http://localhost:8333 y su interfaz de master en http://localhost:9333. Los procesos internos M5, M6 y M7 escuchan únicamente en loopback en http://localhost:8001, http://localhost:8002 y http://localhost:8004, respectivamente. El dashboard M9 se sirve en http://localhost:8003 y permanece cerrado hasta configurar contraseña y TOTP.

Endpoints iniciales:

  • GET /health: vida del proceso.
  • GET /ready: conectividad con TimescaleDB y Redis.
  • POST /v1/market-bars: valida y almacena un lote de barras.
  • GET /metrics: métricas Prometheus.

Endpoints internos de M5:

  • GET :8001/health: vida del proceso independiente de riesgo.
  • POST :8001/v1/risk/evaluate: evalúa un objetivo M4 junto con el snapshot y el estado anterior; devuelve el estado siguiente y la cartera aprobada, recortada o vetada.
  • POST :8001/v1/risk/execution-incidents: convierte un incidente M6 en una decisión HALT que conserva las posiciones protegidas por el broker.

Endpoints internos de M6:

  • GET :8002/health: vida del proceso independiente de ejecución.
  • GET :8002/ready: heartbeat vigente, journal sin planes inciertos y disponibilidad de PostgreSQL, Redis y M5.
  • GET :8002/heartbeat: estado y edad del último heartbeat de M6.
  • POST :8002/v1/execution/commands: acepta un paquete causal completo ya aprobado por M5, persiste su plan y schedule y devuelve 202 Accepted.
  • GET :8002/v1/execution/schedules/{plan_id}: consulta estado, dispatches y el informe terminal cuando esté disponible.
  • GET :8002/metrics: métricas Prometheus del proceso.

Endpoints internos de M7:

  • GET :8004/ready: disponibilidad de journals M6/M7, tablas operativas y M5.
  • POST :8004/v1/accounting/cycles: contabiliza un ciclo explícito contra un informe M6 terminal durable, valora, reconcilia y persiste su recibo.
  • GET :8004/v1/accounting/nav/latest?kind=intraday|daily_close: recupera el último punto NAV oficial publicado para el libro configurado.
  • GET :8004/metrics: métricas Prometheus del proceso.

Superficie M9:

  • GET :8003/: aplicación web responsive.
  • POST :8003/v1/auth/login: login con contraseña y TOTP obligatorio.
  • GET :8003/v1/dashboard/snapshot: snapshot autenticado con procedencia por bloque; NAV/cartera/riesgo usan M7 oficial y liquidez lee la cola append-only M8 al mismo cutoff, o cada bloque declara su indisponibilidad.
  • WS :8003/v1/dashboard/live: actualizaciones en vivo autenticadas.
  • POST :8003/v1/dashboard/controls: frontera sensible con CSRF, TOTP y texto de confirmación; permanece fail-closed. Las conexiones read-only de M7 y M8 no habilitan controles, mutaciones de liquidez ni transferencias.

M9 consulta directamente, con SELECT, las tablas append-only de la migración 016 para el libro configurado y el generated_at del snapshot. Valida la coherencia entre columnas, payload, identidades, secuencia y estado; excluye hechos futuros y declara siempre transfer_initiated_by_atlas=false. Esta lectura no convierte las fuentes simulator_injected de M8 en productivas.

Frontera HTTP propia de M8 (todavía no montada en el Compose base ni conectada a controles M9):

  • GET /health y GET /ready: vida y disponibilidad del journal 016.
  • GET /v1/liquidity/books/{book_id}/queue?as_of=<UTC>: estado, importe y reserva activa por request; siempre declara transfer_initiated_by_atlas=false.
  • No existe endpoint POST ni otra mutación de aportación, retirada, reserva o settlement en esta frontera.

Superficie M11 inicial (factoría implementada, todavía no desplegada en Compose ni asignada a un puerto operativo):

  • GET /health y GET /ready: vida, journal y latch global; una resolución no rearma readiness.
  • GET /v1/incidents y GET /v1/incidents/{incident_id}: lista y detalle append-only.
  • GET /metrics: métricas del proceso.

M11 no expone POST de release, resolve, re-arm ni control. La implementación actual solo incluye puertos para un ACK M5 durable, una fuente autoritativa de not_applied, alertas y verificación de operador; sus adaptadores productivos no existen todavía. Los UUID opacos no son una prueba autovalidada y nunca se persiste un código TOTP o secreto.

Genera el alta inicial sin guardar secretos en Git:

atlas dashboard-credentials --username atlas

Ejecuta el smoke vertical completamente offline y en memoria:

atlas replay-vertical-s4

La variante durable solo admite el entorno PostgreSQL físicamente aislado:

atlas replay-vertical-s4 --backend isolated-postgres --run-id <uuid>

Consulta el runbook del replay vertical antes de usar esa variante. Nunca conecta con proveedores, IBKR ni cuentas paper/live.

Backfill histórico (requiere el stack levantado y ATLAS_MASSIVE_API_KEY para acciones/ETFs):

docker compose run --rm ingestion-api atlas backfill \
  --provider massive --symbol SPY --asset-class etf \
  --from 2025-01-01 --to 2025-12-31 --summary

docker compose run --rm ingestion-api atlas backfill \
  --provider kraken --symbol BTC/USD --asset-class crypto \
  --from 2026-05-01 --to 2026-08-15

Para construir el artefacto Kraken de Fase 1, descarga su ZIP OHLCVT oficial, colócalo en data/archive y calcula su SHA-256:

atlas ingest-kraken-archive \
  --archive /data/archive/Kraken_OHLCVT.zip \
  --archive-sha256 <sha256-del-zip>

ATLAS archiva y verifica el ZIP entero, captura AssetPairs, fija el inventario por hash y procesa en bulk los miembros USD resolubles de 240 y 1.440 minutos. No rellena intervalos sin operaciones y clasifica cada serie como complete, incomplete o unresolved. El backfill de un miembro individual continúa disponible para diagnóstico, pero no sustituye esta adquisición de Fase 1.

Cada respuesta se guarda bajo raw/<proveedor>/.../<sha256>.json en el bucket configurado y se registra en raw_data_manifest antes de crear barras. El comando compara después el rango con el calendario esperado, repara huecos y falla si el proveedor no entrega una serie completa. Para Massive sincroniza además splits y dividendos antes de procesar los precios. --summary conserva los manifiestos raw y los conteos de auditoría en la salida, pero evita imprimir miles de fechas cuando se carga un rango amplio.

La auditoría SEC es opt-in y exige una identificación real conforme a Fair Access solo por entorno. No añade factores a M3 ni sustituye OHLCV o constituyentes históricos:

atlas audit-sec-edgar --cik 0000320193

ATLAS usa como máximo 5 peticiones/segundo, conserva accession y aceptación UTC y archiva antes de extraer. Para cargas grandes el adaptador expone los ZIP bulk oficiales. Consulta el informe del piloto antes de evaluar un proveedor de precios.

Los cuatro frentes de proveedor y la semilla de constituyentes de Fase 1 se ejecutan después de make migrate:

atlas ingest-index-constitution-seed \
  --archive /ruta/privada/index_constitution-1.0.0.tar.gz \
  --sha256 b214777e37b4d80f9e8484d7d4256eafa6b4e99752da23cc5de4dd83b1a1552c \
  --upstream-version 1.0.0 \
  --upstream-commit dd1604c5176176f6cf6418c2a4bab0277b51d4ff \
  --source-uri https://github.com/unliftedq/index-constitution \
  --package-license-id MIT
atlas acquire-massive-core \
  --profile stocks-starter-five-calendar-years-v1 \
  --end-session 2026-08-21 \
  --seed-run-id <uuid-del-run-D1>
atlas audit-sec-edgar --cik 0000320193
atlas ingest-kraken-archive \
  --archive /data/archive/Kraken_OHLCVT.zip \
  --archive-sha256 <sha256-del-zip>
atlas audit-crypto-rankings
atlas audit-phase1-data

--end-session es una elección explícita del operador: debe ser la última sesión XNYS ya cerrada que quiera capturar. ATLAS deriva de forma pura la primera sesión en o después de cinco años naturales antes, conserva el calendario y el hash de sesiones en el run y rechaza reintentos con otra ventana. El run_id D1 solo aporta intervalos de captura audit-only; Massive no crea ni promueve universos. La ruta Stocks Starter rechaza siempre /etf-global, archiva referencia, eventos de ticker, barras y acciones antes de normalizar y devuelve código 2 con PRELIMINARY o PARTIAL, nunca una puerta oficial superada. Véase el ADR 0034.

audit-crypto-rankings no llama a CoinMarketCap: valida la frontera y devuelve PARTIAL mientras no exista suscripción y confirmación de retención. El informe conjunto mantiene missing_artifact=crypto_universe; nunca reconstruye el pasado con rankings actuales. El procedimiento completo está en el runbook paralelo de datos.

La ingesta index-constitution devuelve deliberadamente PARTIAL (código 2): solo acepta el CSV hijo después de archivar el sdist padre, no importa el paquete ni pickles y persiste los intervalos en tablas audit-only separadas. El SPDX MIT describe el paquete fijado, no demuestra derechos ni procedencia de cada fila y no cambia su inelegibilidad. El procedimiento y sus conteos de auditoría están en el runbook de la semilla y la frontera se fija en el ADR 0032.

La ruta D2 no usa esa semilla como autoridad y no realiza descargas. Exige CSV operator-supplied fijados por hash para baseline, feed completo de cambios, corroboración de otra familia y bindings FIGI. Sus tres comandos son:

atlas ingest-equity-constituent-evidence --help
atlas evaluate-equity-constituent-promotion --help
atlas review-equity-constituent-promotion --help

Los derechos insuficientes fallan antes de leer bytes; un known_at tardío no se retropropaga; una aprobación publica snapshots, miembros y receipt dentro de una sola transacción. Los esquemas, argumentos obligatorios y códigos de salida están en el runbook D2 y la decisión en el ADR 0036.

Las barras de acciones/ETFs deben declarar adjustment_status como split_adjusted o total_return_adjusted; una serie unadjusted se rechaza y marca el activo como no operable. Las barras cripto usan not_applicable. Las barras diarias se identifican por la fecha de sesión y siempre se almacenan a las 00:00 UTC, independientemente de la hora que utilice el proveedor.

El replay dorado de M10 verifica tanto el CSV como el resultado esperado:

atlas golden-benchmark --manifest datasets/golden/btcusd_4h_v1.json

Las puertas cuantitativas de la Fase 1 se ejecutan únicamente contra un JSON de evidencia esquema 2.1 completo y hash-pinned. Cada artefacto declara evidence_eligibility; un artefacto audit_only impide OFFICIAL_PASSED. Cada retorno, señal y trade queda dentro de un segmento de proveedor; el candidato debe estar sellado en el diario append-only antes de adquirir y ejecutar una sola vez el holdout. La ausencia de cualquiera de esas pruebas o una puerta fallida devuelve un código distinto de cero:

atlas validate-phase1 --evidence /ruta/a/phase1-evidence.json

Consulta datasets/validation/README.md, docs/runbooks/m10-evidence-v2.md y docs/phase-1-data-requirements.md. El repositorio no incluye ni simula históricos licenciados o constituyentes point-in-time.

Consulta docs/phase-0.md para los cimientos, docs/phase-1.md para los criterios del algoritmo y docs/phase-2.md para el alcance exacto de los incrementos M6/M7/M9/M11. El ciclo contable operativo y su recuperación están en docs/runbooks/m7-operational-accounting.md. El alta segura y los límites actuales del dashboard están en docs/runbooks/m9-dashboard.md. La respuesta fail-closed de M11 y sus fronteras todavía no productivas están en docs/runbooks/m11-global-incidents.md y su decisión en ADR 0039. La preparación y las puertas pendientes de IBKR están en docs/runbooks/ibkr-paper.md. La secuencia de desarrollo posterior a M7/M9/M11, independiente de la prueba viva, está en docs/development-roadmap.md. La evaluación gratuita de históricos terminó en FAIL; el procedimiento y el resultado están en docs/runbooks/phase1-free-data-pilot.md y docs/data-audits/stooq-sec-pilot-2026-08-17.md. La secuencia posterior conserva Massive cinco años como núcleo de desarrollo y reserva la historia anterior como holdout de un candidato ya congelado; véanse ADR 0022, el runbook del holdout y la auditoría de los ficheros locales. El contrato raw-first y las decisiones de universos se fijan en ADR 0028; el resultado de implementación y sus bloqueos se separan por proveedor en el informe de Fase 1. La decisión de coste vigente descarta el add-on ETF Global Constituents y limita index-constitution más fuentes abiertas a semillas audit-only hasta su reconstrucción bitemporal y promoción explícita; véase ADR 0029. La implementación D1 de esa decisión permanece separada del universo oficial; véase ADR 0032. La reconstrucción/promoción D2 mantiene D1 inmutable y separa promoción de la puerta cuantitativa; véase ADR 0036.

El Compose base siempre usa el simulador. El camino paper recomendado ejecuta IB Gateway directamente en la sesión gráfica del host y mantiene M6 y el resto de ATLAS en Docker. Requiere los dos artefactos oficiales aceptados por el usuario, versiones compatibles y login humano:

infra/ibkr/install-host-gateway.sh
infra/ibkr/check-host-versions.sh
infra/ibkr/run-host-gateway.sh
docker compose -f compose.yaml -f compose.ibkr-paper-host.yaml build execution-api

No arranques execution-api con ese overlay hasta completar el login paper, autorizar la IP privada fija de M6 en Gateway y superar el snapshot sin órdenes. Ese snapshot requiere datos de mercado en tiempo real habilitados para API; ATLAS no acepta el feed delayed como sustituto de frescura. El overlay que contiene Gateway en Docker se conserva como alternativa no operativa; no es la ruta recomendada actual.

El snapshot vivo ya está validado. La primera orden paper controlada terminó sin exposición porque IBKR rechazó SPY por elegibilidad KID/PRIIPs; consulta el informe operativo.

Flujo de calidad

make format       # aplica formato y correcciones seguras
make check        # formato, lint, mypy estricto y tests
make compose-config
make integration-up    # levanta solo el stack atlas-integration en puertos dedicados
make integration       # round trip aislado; rechaza endpoints operativos e IBKR
make integration-down  # apaga solo atlas-integration y conserva sus volúmenes

La integración no usa el Compose operativo. Su mapa de recursos, interlocks y procedimiento de diagnóstico están en el runbook de integración aislada.

La configuración de negocio se versiona en config/atlas.toml. Los secretos solo se suministran por variables de entorno o por el gestor de secretos del despliegue; nunca se incluyen en Git.