# Reactive Pipeline Architecture & Bootstrapping Dieses Dokument beschreibt die Architektur der reaktiven Datenverarbeitung innerhalb des MYC AST Compilers in Rust. Es konkretisiert das "Dual Series Architecture"-Konzept um die Aspekte der Initialisierung, Ausführung und Synchronisation. ## 1. Das Phasen-Modell (Bootstrapping vs. Pumping) Das wichtigste Designprinzip der Pipeline ist die strikte zeitliche und logische Trennung zwischen dem **Aufbau des Datenflussgraphen** und der **tatsächlichen Datenverarbeitung**. ### Phase 1: Bootstrapping (Skript-Evaluation) Wenn das MYC-Skript von der VM ausgeführt wird, fließen **keine echten Zeitreihen-Daten**. Das Skript fungiert als reiner *Graph-Builder*: * Aufrufe wie `(create-random-ohlc ...)` erzeugen Quell-Knoten (`RootStream` + Daten-Generator) und registrieren diese im Host-System (z.B. dem `Environment`). * Das `(pipe ...)` Statement nimmt existierende Streams, erzeugt eine Transformation (`PipeStream` mit einer Lambda-Funktion) und hängt sich als `Observer` an die Eingangs-Streams an. * Als Rückgabewert liefert `pipe` eine leere `SharedSeries` (bzw. `SharedRecordSeries`), die als Referenz für weitere Pipes genutzt werden kann. Das Resultat der Skriptausführung ist ein gerichteter azyklischer Graph (DAG) aus Observern, der bereit für die Datenaufnahme ist. ### Phase 2: Pumping (Host-Execution) Nachdem das Skript vollständig durchlaufen ist, übernimmt die Rust-Host-Applikation (z.B. eine Backtesting-Engine oder ein Live-Trading-Loop). * Der Host iteriert über die registrierten Daten-Generatoren. * Er ruft deren `tick()` Methoden auf. * Dies löst Kettenreaktionen aus: Jeder `tick` treibt die Daten durch die angemeldeten `PipeStreams`, führt dort die Lambdas aus und speichert die Ergebnisse in den `SharedSeries`. ## 2. Mehrere Root-Streams Die Architektur erlaubt ausdrücklich die Existenz mehrerer unabhängiger `RootStreams` (z.B. `BTCUSD-M1`, `ETHUSD-M5`). Ein `RootStream` ist lediglich die Quelle von Signalen (`cycle_id` + `Value`). ### Synchronisations-Szenarien & Barrieren * **Szenario A (Unabhängige Graphen):** Mehrere Streams fließen durch völlig getrennte Pipe-Äste. Dies funktioniert out-of-the-box ohne Konflikte. * **Szenario B (Synchrone Zusammenführung):** Mehrere Streams (z.B. zwei Indikatoren basierend auf dem gleichen `RootStream`) fließen in eine gemeinsame `pipe`. * *Lösung:* Die `PipeStream` besitzt eine integrierte **Barrier-Synchronisation**. Sie wartet, bis alle konfigurierten Eingänge dieselbe `cycle_id` geliefert haben, bevor sie ihr Lambda ausführt und das kombinierte Ergebnis weitergibt. * **Szenario C (Asynchrone Zusammenführung / Mixed Timeframes):** Zwei unterschiedliche `RootStreams` (mit unterschiedlichen Taktfrequenzen) sollen in einer Pipe kombiniert werden. * *Achtung:* Die aktuelle `cycle_id`-basierte Barriere würde hier blockieren. * *Lösung (Zukünftig):* Für dieses Szenario wird eine spezialisierte Form der Pipe oder ein dedizierter `JoinStream` benötigt, der Signale anhand ihres `DateTime`-Stempels synchronisiert statt über den monotonen Index, oder ein "Hold"-Verhalten für den langsameren Stream implementiert. ## 3. Test-Infrastruktur: Pseudo-Random Streams Da echte Datenserver als `RootStreams` oft extern angebunden werden müssen, stellt die RTL (Runtime Library) Mechanismen für reproduzierbare Tests bereit. Die Funktion `(create-random-ohlc seed limit)` ist der Blueprint für solche Test-Quellen: 1. Erzeugt einen neuen `RootStream`. 2. Instanziiert einen deterministischen Zufallsgenerator (via Seed). 3. Registriert ein Generator-Objekt im Environment, welches das Limit (Anzahl der Ticks) kennt. 4. Gibt den Stream-Knoten an das Skript zurück, damit dieser an eine `pipe` angeschlossen werden kann. Die Methode `Environment::run_pipeline()` kann später von Rust aus aufgerufen werden, um alle generierten Test-Streams bis zu ihrem jeweiligen Limit durchlaufen zu lassen.