← Alle Insights

Observability für Trading-Systeme: Logs, Metrics, Traces.

Ein Trading-System ohne Observability ist eine Blackbox mit Echtgeld-Risiko. Wenn der Bot um 03:14 Uhr keine Order mehr abschickt, wollen Sie nicht raten — Sie wollen die Zeile sehen, in der es passiert ist.

Die drei Säulen.

Die drei sind komplementär. Logs allein reichen, bis Ihr System ein einzelnes Skript ist. Sobald mehrere Services beteiligt sind, brauchen Sie Metrics für Trends und Traces für Korrelation.

Metrics: Prometheus + Grafana.

Prometheus ist der De-facto-Standard für Metrics im Open-Source-Umfeld: Pull-basiert, Time-Series-Datenbank, einfache Client-Libraries in allen relevanten Sprachen. Grafana ist das Frontend, das man mit Tabs aufrufen will.

from prometheus_client import Counter, Histogram, Gauge

orders_submitted = Counter(
    'orders_submitted_total', 'Anzahl eingereichter Orders',
    ['strategy', 'symbol', 'side'])

order_latency = Histogram(
    'order_latency_seconds', 'Latenz Order-Submit bis Acknowledgement',
    ['venue'],
    buckets=(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5))

open_position = Gauge(
    'open_position_qty', 'Aktuelle Position pro Symbol',
    ['strategy', 'symbol'])

Diese drei Primitive — Counter, Histogram, Gauge — decken 90 % der Bedürfnisse ab. Für Trading-Systeme empfehle ich mindestens: P&L pro Strategie (Gauge), Anzahl Orders pro Stunde (Counter), Order-Latenz (Histogram), Anzahl offener Positionen (Gauge), API-Fehler nach Typ (Counter).

Logs: Loki oder Elasticsearch.

Loki von Grafana Labs ist das schlanke Pendant zu Elasticsearch: indiziert nur Labels, nicht den vollen Text, deutlich günstiger im Betrieb. Für Setups bis ~50 GB Logs/Tag ist Loki meine Standard-Wahl. Ab da wird Elasticsearch durch volle Volltextsuche relevant.

Wichtig: strukturierte Logs, nicht print. JSON pro Zeile, mit Feldern wie strategy, symbol, order_id, trace_id. Das macht die Korrelation mit Traces und das Filtern in Grafana erst möglich.

import structlog
log = structlog.get_logger()

log.info("order.submit",
         strategy="mean_reversion_v3",
         symbol="AAPL",
         side="buy",
         qty=120,
         limit=187.42,
         trace_id=current_trace_id())

Traces: OpenTelemetry.

OpenTelemetry (OTel) ist der Standard für Distributed-Tracing. Sie instrumentieren Ihre Services einmal mit dem OTel-SDK, der Collector schickt die Traces an Tempo, Jaeger oder einen Cloud-Provider. Für Trading-Systeme besonders wertvoll: End-to-End-Latenz von Marktdatum bis Order ist nur über Traces sauber messbar.

from opentelemetry import trace
tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("strategy.evaluate") as span:
    span.set_attribute("strategy", "mean_reversion_v3")
    signal = strategy.evaluate(bar)
    with tracer.start_as_current_span("risk.check"):
        ok = risk.allow(signal)
    if ok:
        with tracer.start_as_current_span("order.submit"):
            broker.submit(signal.to_order())

Was Sie unbedingt loggen sollten.

Alerts: PagerDuty oder Opsgenie.

Alertmanager (Teil des Prometheus-Stacks) routet Alerts an PagerDuty oder Opsgenie. Drei Tiers, die ich konsequent unterscheide:

Wichtigste Regel: Jeder Critical-Alert muss eine Runbook-Verlinkung haben. Wenn der Pager um 04:00 Uhr klingelt, wollen Sie nicht erst überlegen, was zu tun ist.

SLOs für Trading-Systeme.

Service-Level-Objectives sind das Bindeglied zwischen Metrics und Geschäft. Für ein Live-Trading-System sinnvolle SLOs:

Wer keine SLOs definiert, kann auch nicht entscheiden, ob ein Incident relevant war oder Rauschen.

Konkretes Docker-Compose-Setup.

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prom_data:/prometheus
    ports: ["9090:9090"]

  grafana:
    image: grafana/grafana:latest
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=__changeme__
    volumes:
      - grafana_data:/var/lib/grafana
    ports: ["3000:3000"]

  loki:
    image: grafana/loki:latest
    ports: ["3100:3100"]

  tempo:
    image: grafana/tempo:latest
    command: -config.file=/etc/tempo.yml
    volumes:
      - ./tempo.yml:/etc/tempo.yml:ro
    ports: ["3200:3200", "4317:4317"]   # OTLP gRPC

  alertmanager:
    image: prom/alertmanager:latest
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
    ports: ["9093:9093"]

volumes:
  prom_data:
  grafana_data:

Dieses Setup läuft bei mir auf einem dedizierten Monitoring-VPS — getrennt vom Trading-VPS, damit ein Crash der Trading-Maschine nicht den Monitoring-Stack mitnimmt.

Meine Praxis.

Für die Mandanten, mit denen ich arbeite, läuft der komplette Observability-Stack (Prometheus, Grafana, Loki, Tempo, Alertmanager) auf einem zentralen VPS. Jeder Mandant bekommt einen eigenen Grafana-Tenant mit Read-Only-Dashboards: P&L, offene Positionen, Strategie-Status, Order-Latenz. Alerts werden zentral kuratiert, der Mandant bekommt nur die Critical-Eskalationen.

Aufwand für das Initial-Setup: 1–2 Tage. Aufwand für das Instrumentieren der Trading-Codebasis: weitere 1–3 Tage je nach Größe. Ergebnis: Sie sehen ein Problem, bevor der Mandant es sieht — und das ist die einzige Position, in der Sie sein wollen.

Sie wollen Ihr Trading-System aus dem Blindflug holen? Erstgespräch buchen — wir bauen einen schlanken Observability-Stack, der zu Ihrem Setup passt.