AUTOFINANZ FRAMEWORK

// PRODUKTIONSREIFE BÖRSENDATEN-PLATTFORM // STAND 2025 //
$ SYSTEM_INIT --build-plan

Ablaufplan für dein Docker-natives Trading-Framework — von der ersten Zeile Code bis zur Enterprise-Skalierung.

Du baust hier keine Wegwerf-App. Dieser Plan folgt einer klaren Regel: Starte monolithisch mit sauberen Service-Grenzen, extrahiere Microservices erst wenn die Last es erzwingt. Jede Phase liefert ein lauffähiges System — kein "erst fertig wenn alles fertig ist".

⚡ Nächste Schritte:
  • Phase 1 starten: Finnhub Free Tier registrieren (60 Calls/Min) und Docker-Compose-Grundgerüst hochziehen
  • Deine bestehende AutoFinanz-Basis (FastAPI + Streamlit + Celery + Postgres + Redis) gegen den Plan mappen — du bist schon bei Phase 3-4, nicht bei Null
1
MVP Setup
2
Daten-APIs
3
Backtesting
4
TimescaleDB
5
Hardening
6
Microservices
7
Enterprise

1 MVP — Vom Zero zum ersten Prototyp

📊 Warum du hier startest

Bevor du über Latenz und Skalierung nachdenkst: Du brauchst ein System, das überhaupt Kurse zieht, speichert und anzeigt. Der Monolith ist hier kein Kompromiss, sondern die richtige Wahl — solange du unter 10.000 Orders/Tag und ~100 Strategien bleibst, ist alles andere Over-Engineering.

LIVE DATA STREAM ACTIVE

🎯 Zielbild Phase 1

FastAPI (Backend) + PostgreSQL (Storage) + Streamlit (Frontend), alles in einem Docker-Compose-Stack auf einem einzelnen Server (z.B. AWS EC2 t3.medium). Datenquelle: Finnhub Free Tier.

Aufwand: 2-3 Tage Budget: $0-50/Monat Nutzer: 1-10
⚠️ Anti-Pattern: Fang NICHT mit Microservices an. Der häufigste Fehler ist, Kafka und Kubernetes am Tag 1 einzuführen. Modularer Monolith zuerst — Services extrahierst du später chirurgisch.

🐳 Docker-Compose Grundgerüst

Das minimale, lauffähige Setup. Drei Services, ein Netzwerk, ein Volume.

docker-compose.yml (MVP)
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: trading
    volumes:
      - pg_data:/var/lib/postgresql/data

  api:
    build: ./backend
    environment:
      DATABASE_URL: postgresql://admin:${DB_PASSWORD}@postgres/trading
      FINNHUB_KEY: ${FINNHUB_KEY}
    ports: ["8000:8000"]
    depends_on: [postgres]

  frontend:
    build: ./frontend
    environment:
      API_URL: http://api:8000
    ports: ["8501:8501"]
    depends_on: [api]

volumes:
  pg_data:
Secrets-Handling (kein Key im Code!)

API-Keys gehören niemals in den Quellcode oder ins Git-Repo. Lokal: .streamlit/secrets.toml (in .gitignore). In Docker: als ENV-Variablen aus einer .env-Datei injizieren. Streamlit liest ENV-Variablen automatisch als Teil von st.secrets.

Das deckt sich exakt mit deiner AutoFinanz-Secrets-Architektur: master.env → setup_secrets.sh → bind-mounted secret files.

✅ Definition of Done

  • Container starten mit einem docker compose up
  • Streamlit zeigt Live-Quote für mindestens ein Symbol (z.B. AAPL)
  • Kurse landen persistent in Postgres
  • Kein Key im Repo — git log ist sauber

2 Daten-Schicht — API-Auswahl & Rate-Limit-Diktat

📊 Die zentrale Erkenntnis

Das API-Rate-Limit ist nicht eine Einstellung — es ist der Grundstein deines gesamten Systemdesigns. Ein Limit von 5 Calls/Min bedeutet: Eine naive App, die bei jedem Klick direkt die API ruft, stirbt sofort am 429 Too Many Requests. Genau das erzwingt später die asynchrone Architektur mit Celery (die du schon hast).

LIVE DATA STREAM ACTIVE

💰 API-Vergleich: Free Tier Realität 2025

APICalls/MinCalls/TagLatenzEU-MärkteWebSocket
Finnhub60UnlimitedModerat✓ 60+ Börsen
Twelve Data8800~170ms✓ 250+ Börsen
Polygon.io5Unlimited<20ms (Paid)✓ (Paid)
Alpha Vantage525Nur EOD freiBegrenzt
Alpaca200UnlimitedNiedrig
⚠️ Falle yfinance: Erscheint 100% kostenlos, ist aber Web-Scraping von Yahoo — keine offizielle API. Führt zu aggressiver Ratenbegrenzung, IP-Sperren und inkonsistenten Daten. Okay für Jupyter-Prototyping, ein architektonischer Fehler in Produktion.

🔑 Empfehlung nach Anwendungsfall

  • Kostenloser Start / Hochfrequenz: Finnhub (60/Min, beste Free-Option)
  • EU-Märkte breit: Twelve Data (250+ Börsen in 90 Ländern, WebSocket schon im Free-Tier)
  • Low-Latency-Trading: Polygon.io ($199+/Monat, <20ms) — du nutzt Polygon bereits laut Setup
Code: Finnhub Quote + WebSocket
import finnhub
client = finnhub.Client(api_key="YOUR_KEY")
print(client.quote('AAPL'))

# WebSocket für Echtzeit-Streaming
import websocket
ws = websocket.WebSocketApp(
    "wss://ws.finnhub.io?token=YOUR_TOKEN",
    on_message=on_message)
ws.run_forever()
Kritische Marktveränderungen 2024/25

IEX Cloud: Betrieb am 31.08.2024 eingestellt — viele mussten migrieren.

Alpha Vantage: Free-Tier drastisch reduziert von 500 auf nur noch 25 Calls/Tag — für Intraday unbrauchbar.

Lehre: API-Abhängigkeiten sind Risikomanagement. Baue deine Fetch-Logik so, dass ein Provider-Wechsel ein Config-Change ist, kein Rewrite.

3 Analyse-Herzstück — Backtesting-Framework

📊 Warum die Framework-Wahl alles bestimmt

Das Backtesting-Framework entscheidet über Geschwindigkeit, Komplexität und Zukunftsfähigkeit. Zwei Paradigmen konkurrieren: event-gesteuert (Takt für Takt, näher am Live-Handel) vs. vektorisiert (ganze Arrays gleichzeitig, extrem schnell für Parameter-Sweeps).

LIVE DATA STREAM ACTIVE

⚡ Framework-Status Oktober 2025

FrameworkParadigmaPerformanceStatus 2025
vectorbtVektorisiertExtrem hoch✅ Sehr aktiv
BacktraderEvent-drivenMittel⚠️ Feature-complete (2019)
backtesting.pyVektorisiertHoch✅ Aktiv
Zipline-ReloadedEvent-drivenMittel✅ Aktiv
FreqtradeEvent-drivenMittel✅ Sehr aktiv (Crypto)
⚠️ Zombie-Warnung: Das originale Zipline wird nicht mehr gewartet — lockt aber über alte Tutorials weiter Nutzer an. Nimm den gepflegten Fork Zipline-Reloaded. Und: das ursprüngliche pandas-ta wurde closed-source ("Vampir") — nutze den Community-Fork pandas-ta-classic (141 Indikatoren, aktiv gepflegt).

🚀 vectorbt — die Empfehlung

Bis zu 1000x Speedup durch vollständige Vektorisierung + Numba. Simuliert Millionen Trades in unter einer Sekunde, testet 10.000 Strategiekombinationen in Sekunden. Killer-Feature: native Plotly-Ausgabe → direkt interaktiv in Streamlit. Und es spricht out-of-the-box ~99% der Indikatoren aus TA-Lib, Pandas TA & Co. an — du musst dich also nicht auf eine TA-Bibliothek festlegen.

Code: vectorbt MA-Crossover
import vectorbt as vbt

price = vbt.YFData.download('BTC-USD').get('Close')
fast_ma = vbt.MA.run(price, 10)
slow_ma = vbt.MA.run(price, 50)
entries = fast_ma.ma_crossed_above(slow_ma)
exits   = fast_ma.ma_crossed_below(slow_ma)

pf = vbt.Portfolio.from_signals(price, entries, exits, init_cash=100)
print(pf.stats())
pf.plot().show()   # → interaktives Plotly-Objekt für st.plotly_chart
Performance-Benchmark vectorbt
Rolling Mean (1000x1000 DataFrame):
  Pandas:              45.6 ms
  vectorbt (Numba):     5.33 ms  (8.5x schneller)
  vectorbt (Parallel):  1.82 ms  (25x schneller)

Rolling Sortino Ratio:
  QuantStats: ~Sekunden
  vectorbt:   ~Millisekunden  (1000x schneller)

Du nutzt vectorbt bereits Streamlit-Integration nativ Plotly

4 Storage-Schicht — TimescaleDB für Zeitreihen

📊 Warum nicht einfach Postgres

Minutendaten summieren sich brutal schnell. Ein normaler Postgres-Table wird bei Millionen von Ticks pro Symbol zäh. TimescaleDB ist Postgres mit automatischer zeitbasierter Partitionierung (Hypertables), Kompression und kontinuierlichen Aggregaten — die optimale Zeitreihen-DB für Trading. Der Umstieg ist ein Extension-Load, kein DB-Wechsel.

LIVE DATA STREAM ACTIVE

🗄️ Hypertable + Kompression + Retention

Der komplette Setup-Flow: Hypertable anlegen, Composite-Index für schnelle Symbol-Abfragen, kontinuierliche 5-Min-Aggregation, Auto-Kompression nach 7 Tagen, Retention nach 2 Jahren.

SQL: Hypertable + Aggregation
CREATE EXTENSION IF NOT EXISTS timescaledb;

CREATE TABLE stock_prices (
    time TIMESTAMPTZ NOT NULL,
    symbol TEXT NOT NULL,
    open NUMERIC, high NUMERIC, low NUMERIC,
    close NUMERIC, volume BIGINT
);

SELECT create_hypertable('stock_prices', 'time');
CREATE INDEX idx_symbol_time ON stock_prices (symbol, time DESC);

-- Kontinuierliche 5-Minuten-Bars
CREATE MATERIALIZED VIEW stock_prices_5min
WITH (timescaledb.continuous) AS
SELECT time_bucket('5 minutes', time) AS bucket, symbol,
       first(open, time) AS open, max(high) AS high,
       min(low) AS low, last(close, time) AS close,
       sum(volume) AS volume
FROM stock_prices
GROUP BY bucket, symbol;
SQL: Kompression & Retention
ALTER TABLE stock_prices SET (
    timescaledb.compress,
    timescaledb.compress_segmentby = 'symbol'
);

-- Auto-Kompression nach 7 Tagen
SELECT add_compression_policy('stock_prices', INTERVAL '7 days');

-- Retention: Daten > 2 Jahre löschen
SELECT add_retention_policy('stock_prices', INTERVAL '2 years');

🔴 Redis als Caching-Layer

Redis reduziert API-Calls um 80-90% und dient gleichzeitig als Pub/Sub-Bus für Echtzeit-Updates. Essentiell, nicht optional. TTL-basiertes Caching pro API-Call, Pub/Sub für Fan-Out an mehrere Clients.

⚠️ Kernprinzip: Jeder API-Call bekommt einen Redis-Cache mit TTL. Ohne Caching-Strategie brennst du dein Rate-Limit sinnlos ab und die App fühlt sich langsam an.

5 Production Hardening — Monitoring & CI/CD

📊 Der Unterschied zwischen Prototyp und Produkt

Ab hier trennt sich Bastelei von Betrieb. Monitoring, Health Checks, Non-Root-Container und automatisierte Deployments baust du von Anfang an ein — nicht nachträglich. Genau hier lebt deine AutoFinanz-Erkenntnis: Deploy-Drift ist real. Committeter Code wirkt erst nach Image-Rebuild und Container-Recreate.

LIVE DATA STREAM ACTIVE

🛡️ Sicheres Dockerfile (Non-Root + Health Check)

Standard-Dockerfiles laufen als root — ein Sicherheitsrisiko. Dedizierter Non-Root-User plus Health Check.

Dockerfile (Production, Streamlit)
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

RUN groupadd -g 1005 appgroup && \
    useradd -u 1005 -g appgroup appuser && \
    chown -R appuser:appgroup /app
USER appuser

EXPOSE 8501
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
ENTRYPOINT ["streamlit", "run", "app.py", \
    "--server.port=8501", "--server.address=0.0.0.0"]
TA-Lib im Docker-Build (C-Kompilierung)

Wenn TA-Lib (oder vectorbt mit TA-Lib-Support) in requirements.txt steht, schlägt pip install fehl — die C-Bibliothek fehlt. Lösung: C-Lib im Dockerfile aus Quellcode bauen bevor pip läuft.

RUN apt-get update && apt-get install -y build-essential wget \
    && wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz \
    && tar -xzf ta-lib-0.4.0-src.tar.gz && cd ta-lib/ \
    && ./configure --prefix=/usr && make && make install \
    && cd .. && rm -rf ta-lib*

📈 Monitoring & CI/CD

  • Prometheus + Grafana von Anfang an — Metriken, nicht Rätselraten
  • GitHub Actions: Build → Test (pytest im Container) → Push Registry → SSH-Deploy
  • Health Checks in jedem Service, damit Compose kranke Container erkennt
⚠️ Deploy-Drift Merksatz: Vor jedem "läuft doch"-Moment: Image-Alter gegen letzten Commit prüfen. Bei WSL2 zusätzlich Uhr-Drift beachten — docker ps-Zeitstempel lügen nach System-Sleep. Immer mit echten Log-Timestamps gegenprüfen.

6 Microservices — Kafka & Service-Extraktion

📊 Wann du diese Phase überhaupt brauchst

Erst wenn die Last es erzwingt: >10 Entwickler, Richtung 100.000 Orders/Tag, 1000 Strategien, Multi-Asset. Vorher ist der Monolith überlegen. Der Übergang ist eine Extraktion — du schneidest den ersten Service (meist Market Data oder Order Execution) sauber aus dem Monolithen, nicht ein Big-Bang-Rewrite.

LIVE DATA STREAM ACTIVE

🌊 Real-Time Streaming-Pipeline

Das produktionsreife Muster für Hochfrequenz-Daten:

Market Feed → Kafka Topic → Stream Processor → TimescaleDB
                                             → Redis Cache → WebSocket → Frontend
  • WebSocket-Verbindung zur Exchange (Polygon/Finnhub)
  • Kafka-Producer schreibt alle Ticks (mit lz4-Kompression)
  • Kafka Streams aggregiert zu 1min/5min-Bars
  • Parallel: TimescaleDB (persistent) + Redis (Hot Cache)
  • WebSocket-Server bedient N Clients aus Redis (Fan-Out)
Code: Kafka Producer (Python)
from kafka import KafkaProducer
import websocket, json

producer = KafkaProducer(
    bootstrap_servers=['kafka:9092'],
    value_serializer=lambda v: json.dumps(v).encode('utf-8'),
    compression_type='lz4')

def on_message(ws, message):
    producer.send('market_ticks', json.loads(message))

ws = websocket.WebSocketApp(
    "wss://ws.finnhub.io?token=YOUR_TOKEN",
    on_message=on_message)
ws.run_forever()
⚠️ Bottleneck-Lösung: WebSocket-Überlastung löst du mit Redis Pub/Sub als Fan-Out — 1 WebSocket zur Exchange → Redis → N Client-Verbindungen. Nie N direkte Exchange-Connections.

🏗️ Service-Grenzen

Typischer Schnitt: Auth-Service, Market-Data-Service (gern Go für Durchsatz), Order-Execution (FastAPI), Analytics (Python). Verbunden über einen Kafka Event Bus, davor ein API-Gateway (Kong/Nginx).

7 Enterprise Scale — Multi-Region & Ultra-Low-Latency

📊 Die Endstufe

100K+ Nutzer, $10K+/Monat. Hier geht es um Full Microservices mit Service Mesh, Multi-Region-Redundanz und — für echtes HFT — physische Nähe zur Börse. Das ist aspirationale Roadmap, kein sofortiges Arbeitspaket. Aber es lohnt sich, die Richtung zu kennen, damit frühe Entscheidungen sie nicht verbauen.

LIVE DATA STREAM ACTIVE

🌐 Skalierungs-Roadmap im Überblick

PhaseNutzerBudget/MonatKern-Stack
MVP0-1K$0-100Monolith + Compose
Growth1K-10K$100-1KTimescaleDB + Redis + LB
Scale10K-100K$1K-10KK8s + Kafka + Multi-Region
Enterprise100K+$10K+Service Mesh + Co-Location

💀 Enterprise-Bausteine

  • Full Microservices mit Service Mesh (Istio)
  • Multi-Region Kafka + TimescaleDB für Redundanz
  • CDN für Frontend (Cloudflare)
  • Co-Location bei Exchanges für Ultra-Low-Latency
  • Custom Hardware / FPGAs für echtes HFT
⚠️ Realitätscheck: Die meisten persönlichen und Retail-Plattformen erreichen diese Phase nie — und müssen es auch nicht. AutoFinanz als Personal-Platform ist bei Phase 3-4 optimal aufgehoben. Enterprise nur wenn echte Multi-User-Last dazukommt.

🎯 Kritische Erfolgsfaktoren (phasenübergreifend)

  • TimescaleDB für Zeitreihen — automatische Partitionierung
  • Redis-Caching mit TTL für alle API-Calls (80-90% weniger Calls)
  • API-Strategie: kostenlos starten (Finnhub) → bei Bedarf upgraden
  • Framework: vectorbt für Performance, Backtrader für Einstieg
  • Monitoring von Tag 1, nicht nachträglich
  • Monolith zuerst, Services chirurgisch extrahieren