trading-system-docs/notes/trading/system-docs/phase13_4_trust_gate.md

7.8 KiB
Raw Permalink Blame History

Phase 13.4 — Historical Data Trust Gate (Provenance + Sanity Validation)

Status: FINAL CLOSED (technisch verifiziert, dokumentiert) Datum: 24.08.2026 Autor: Rain Ocampo (Hermes) Freigabe: Christian List (Phase 13.4 Finalisierung / Second-Brain-Sync)


1. Ausgangsproblem (aus Phase 13.3)

Die Phase-13.3-Forensik zeigte: HTTP 200 + erfolgreiches Parsing bedeutet NICHT automatisch vertrauenswürdige Daten.

Die bekannten problematischen November-Tage (11-09, 11-10, 11-12) wurden von Dukascopy mit HTTP 200 geliefert, technisch valide geparst, aber enthielten fachlich unplausible Daten (falsches Preisniveau, Wochenendaktivität). Der source_timestamp war in allen Fällen NULL.

Kernbefund: Ein reiner "Download erfolgreich + Parse erfolgreich"-Check ist unzureichend. Es fehlt eine Schutzschicht, die Provenance und fachliche Plausibilität vor der Persistierung validiert.


2. Neue Pipeline-Reihenfolge

RAW DOWNLOAD
  → PROVENANCE CAPTURE
  → TECHNICAL PARSE
  → SANITY VALIDATION
  → TRUST DECISION
  → SESSION
  → TECHNICAL/MARKET QUALITY
  → EFFECTIVE ELIGIBILITY
  → GAP
  → PERSIST RAW
  → DERIVED
  → DATASET VERSION

Das Trust Gate sitzt nach dem technischen Parse und vor der Persistierung (Schritt 4c in backfill.py). Es klassifiziert, es löscht nicht.


3. Provenance-Modell

HistoricalProvenanceContext (Version provenance_v1) — 16 Felder:

Feld Semantik
provider Datenquelle (Dukascopy, OANDA, FXCM, Polygon, …)
instrument Instrument (EURUSD, …)
timeframe Zeitrahmen (M1, M5, …)
source_url Quelle (Credentials redacted)
http_status HTTP-Statuscode
content_length Rohdatenlänge
raw_file_sha256 SHA-256 der Rohdatei
retrieved_at Abrufzeitpunkt (volatile, nicht im Hash)
source_timestamp Quell-Zeitstempel (kritisch, fail-closed)
adapter_version Adapter-Version
parser_version Parser-Version
normalization_version Normalisierungs-Version
code_version Code-/Commit-Version
raw_source Rohquelle
dataset_identity Dataset-Identität

Keine Secrets in source_urlredact_url() entfernt Credentials; to_dict() wendet Redaction an.


4. Trust States

State Bedeutung Persistierbar?
TRUSTED Provenance vollständig, Sanity plausibel Ja
CONDITIONAL Warnende Hinweise (z. B. Wochenendaktivität) ⚠️ Nur mit expliziter Policy
UNTRUSTED Fachlich unplausible Daten Nein
UNKNOWN Kritische Provenance fehlt Nein (fail-closed)

Version: trust_v1


5. Reason Codes (20, erweiterbar)

PRICE_LEVEL_MISMATCH, WEEKEND_DATA_ANOMALY, STALE_DAY, ZERO_VOLUME_DAY, SOURCE_TIMESTAMP_MISSING, RAW_ARTIFACT_MISSING, PROVENANCE_INCOMPLETE, CROSS_PROVIDER_MISMATCH, NAN_OR_INF, INSTRUMENT_MISMATCH, TIMEFRAME_MISMATCH, TIMESTAMP_DUPLICATE, TIMESTAMP_MISSING_MINUTE, TIMESTAMP_OUT_OF_RANGE, TIMESTAMP_NON_MONOTONIC, REFERENCE_UNAVAILABLE, PROVIDER_OUTAGE, PROVIDER_DATA_ERROR


6. Provider-Outage vs Provider-Data-Error

Strikt getrennte Codepfade:

  • PROVIDER_OUTAGE — technischer Ausfall: HTTP 404/503, Timeout, Connection-Failure
  • PROVIDER_DATA_ERROR — HTTP 200, technisch valide, aber fachlich unplausible Daten

Diese Zustände bekommen nie denselben Status/Codepfad.


7. Sanity-Prüfungen (6 Klassen, providerneutral)

Klasse Prüfung Konfigurierbar
A Price-Level (gegen unabhängige Referenz) asset-class-aware
B Weekend/Session-Anomalie
C Stale-Day (flacher Tag)
D Volume (Zero-Volume-Day)
E Cross-Provider (optional, nur Validierung)
F Timestamp (UTC, Monotonie, Duplikate, Range)

Keine universelle 1,5%-Regel. Die Forex-Default-Toleranz wurde aus dem Phase-13.3-Befund auf 0,5% kalibriert (die bekannten falschen Tage wichen nur 0,551,07% ab und wurden bei 1,5% fälschlich TRUSTED). Schwellen sind versioniert und konfigurierbar.


8. Fail-Closed-Verhalten

  • TRUSTED: Persistierung zulässig
  • CONDITIONAL: nur mit expliziter Policy (Audit bleibt erhalten)
  • UNTRUSTED: nicht als normaler vertrauenswürdiger Historical-Datensatz persistieren
  • UNKNOWN: fail-closed, sofern kritische Provenance fehlt

9. Raw-Artifact-Retention

  • Content-Hash (SHA-256) + kontrollierter Artifact Store
  • Keine unkontrollierte Datenexplosion
  • Retention-Policy: Hash + Metadaten (Größe, Retrieval-Zeit, Provider, Instrument, Zeitraum, HTTP-Status, URL ohne Credentials)

10. source_timestamp-Regel

  • Semantik: Quell-Zeitstempel des Datenpunkts (UTC)
  • Pflichtgrad: kritisch
  • Range vs Einzelwert: beides unterstützt
  • UTC: zwingend
  • Fail-Closed: fehlt source_timestampSOURCE_TIMESTAMP_MISSINGUNKNOWN (nicht persistierbar)
  • Keine Altbestandsmigration (November-Daten bleiben unverändert)

11. Hash / Reproduzierbarkeit

  • provenance_hash: deterministischer SHA-256 über die Provenance
  • Volatile retrieved_at wird NICHT in den deterministischen Hash aufgenommen
  • Gleiche Raw-Datei + gleiche Modelle + gleiche Konfiguration → gleicher Hash
  • Andere Raw-Datei / andere Trust-Policy → unterscheidbar

12. Ergebnisse

  • Trust-Gate-Tests: 27/27 grün
  • Phase-13.3-Reproduction: 9/9 grün
    • 11-09 (Sa): UNTRUSTED (PRICE_LEVEL_MISMATCH + WEEKEND_DATA_ANOMALY)
    • 11-10 (So): CONDITIONAL (WEEKEND_DATA_ANOMALY)
    • 11-12 (Di): UNTRUSTED (PRICE_LEVEL_MISMATCH)
    • Keiner TRUSTED — Reason Codes folgen aus den Daten, nicht gefittet
  • Relevante Phase-13-Regressionen grün (Provider-Failures, Ingestion-State, Idempotenz, Hash-Konsistenz, Daily-Report)

13. Deploy / Health-Status

  • Container historical-service: Up
  • /health: {"status":"ok","service":"historical-data-service","version":"0.1.0-poc"}
  • /health/ready: {"status":"ready","db":"connected"}
  • Trust-Gate-Code im Container importierbar
  • BackfillOrchestrator.run kennt trust_gate (additiv, Standard None = Gate inaktiv)

14. Bekannte Technical Debt (vorbestehend, NICHT Phase-13.4-Regression)

Die folgenden 4 Fehler sind vorbestehend — mit dem unveränderten Pre-13.4-backfill.py identisch reproduzierbar (definitiv bewiesen):

  1. Aggregation E2ETypeError: float - NoneType (DB-Wahrheit, M5-Aggregation)
  2. Read API E2E/bars M5 liefert 24 statt 12 Bars
  3. Parquet POC — M5-Export/Reimport weicht ab
  4. Test-Fixture-Trennung — operative Daten enthalten Feb-2024-Testbars

Diese sind nicht durch das Trust Gate verursacht und werden nicht in Phase 13.4 behoben.


15. November-Daten

  • Unverändert (5760 Bars für 11-09 bis 11-12, alle source_timestamp NULL)
  • Weiterhin UNTRUSTED — als forensischer Beweis erhalten
  • Nicht gelöscht, nicht überschrieben, nicht reklassifiziert, nicht migriert, nicht repariert

16. Runner / Watchdog / OANDA / Production Gates

  • Runner p13_eurusd: PAUSED (unverändert)
  • Watchdog: unverändert, Recovery-only (Cron fa8ab4da220f, DUKASCOPY_RECOVERY ONLY)
  • OANDA: nicht integriert (keine Credentials, keine API-Calls)
  • Production Gates: unverändert
  • DB-Schema: unverändert (additiv, rückwärtskompatibel)

17. Nächster empfohlener Schritt (NOCH NICHT FREIGEGEBEN)

Ein minimaler kontrollierter End-to-End-Ingest-Test soll später beweisen, dass das Trust Gate nicht nur in Unit-/Reproduction-Tests funktioniert, sondern im echten DOWNLOAD → PROVENANCE → SANITY → TRUST → PERSIST-Pfad UNTRUSTED/UNKNOWN-Daten tatsächlich VOR der Persistierung blockiert.

Dieser Test ist jetzt noch NICHT freigegeben.