7.8 KiB
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_url — redact_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-FailurePROVIDER_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,55–1,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_timestamp→SOURCE_TIMESTAMP_MISSING→UNKNOWN(nicht persistierbar) - Keine Altbestandsmigration (November-Daten bleiben unverändert)
11. Hash / Reproduzierbarkeit
provenance_hash: deterministischer SHA-256 über die Provenance- Volatile
retrieved_atwird 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.runkennttrust_gate(additiv, StandardNone= 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):
- Aggregation E2E —
TypeError: float - NoneType(DB-Wahrheit, M5-Aggregation) - Read API E2E —
/bars M5liefert 24 statt 12 Bars - Parquet POC — M5-Export/Reimport weicht ab
- 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_timestampNULL) - 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.