Strasmore Research
Lernen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-04

Circuit Breaker für Trading-Bots verstehen

Erfahren Sie, wie Tagesverlustlimits Trading-Bots stoppen, bevor Verluste eskalieren, wie oft sie auslösen und wie Volatilitätsskalierung die Positionsgröße verändert.

Handelsunterbrechungen für Trading-Bots sind Regeln, die eine automatisierte Strategie daran hindern, weitere Orders zu senden, sobald ein festgelegtes Limit erreicht ist. Sie liegen als Risikoschicht zwischen der Strategie und dem Broker und gelten für jede Order, unabhängig davon, ob die Strategie damit einverstanden ist. Die Strategie entscheidet, was gehandelt wird. Die Risikoschicht entscheidet, ob überhaupt gehandelt wird.

Diese Trennung ist der Kern des Designs. Eine Strategie, die sich selbst überwacht, verfügt genau dann über keine unabhängige Kontrolle, wenn ihre eigenen Annahmen nicht mehr gelten. Genau in diesem Moment ist eine solche Kontrolle besonders wichtig.

Was ein Circuit Breaker in einem Trading-Bot bewirkt

Eine Risikoschicht hat vier Bestandteile. Jeder davon verhindert einen bestimmten, unspektakulären Fehler.

  • Harte Obergrenzen für die Positionsgröße, das Nominalengagement je Symbol und die Orderfrequenz. Sie begrenzen den Schaden eines Fehlers, der andernfalls unkontrollierbar wäre.
  • Ein Drawdown-Circuit-Breaker, der neue Orders stoppt, sobald das Konto in der Handelssitzung einen festgelegten Betrag oder seit seinem Höchststand beim Eigenkapital einen festgelegten Betrag verloren hat.
  • Skalierte Ordergrößen, die anhand der jüngsten Volatilität oder als Bruchteil des Kelly-Einsatzes festgelegt werden, statt auf einer festen Stückzahl zu beruhen. Dadurch bleibt das Risiko je Trade ungefähr konstant, während sich die Handelsspanne des Marktes verändert.
  • Ein nur erweiterbares Audit-Log für jede Entscheidung, einschließlich der Orders, die die Risikoschicht abgelehnt hat. Es ist das einzige Protokoll, mit dem sich feststellen lässt, ob die Strategie falsch lag oder die Prüfung überhaupt nicht ausgeführt wurde.

Alles Folgende konkretisiert einen dieser vier Bestandteile.

Was ist ein angemessenes tägliches Verlustlimit für einen Trading-Bot?

Ein tägliches Verlustlimit stoppt neue Orders, sobald der Verlust der Handelssitzung einen Schwellenwert überschreitet. Die Festlegung ist eine Kalibrierungsfrage, keine Geschmacksfrage: Liegt der Wert innerhalb der üblichen Marktbewegungen, bleibt der Bot in den meisten Wochen angehalten. Liegt er deutlich außerhalb, wird er nie ausgelöst. Der Ausgangspunkt ist die Häufigkeit, mit der der Markt selbst einen Verlusttag bestimmter Größe verzeichnet.

AbfrageSPY-Tage mit Kursverlust nach Größe, pro Jahr, 2018 bis Juli 2026
Das exakte SQL hinter jeder Zahl
WITH daily AS (
    SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2017-12-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY d
),
with_prev AS (
    SELECT d,
           close_px,
           any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
    FROM daily
)
SELECT toYear(d) AS year,
       countIf(close_px / prev_close - 1 <= -0.01) AS down_1pct_days,
       countIf(close_px / prev_close - 1 <= -0.02) AS down_2pct_days,
       countIf(close_px / prev_close - 1 <= -0.03) AS down_3pct_days
FROM with_prev
WHERE prev_close > 0
  AND d >= toDate('2018-01-01')
GROUP BY year
ORDER BY year
Run this yourself

Sitzungen mit einem Minus von mindestens 1 % gab es 15 in 2019 und 45 in 2020 – bei ungefähr 250 Handelstagen pro Jahr. Die Zahl der Sitzungen mit einem Minus von mindestens 3 % ist eine andere Größenordnung: 0 in 2019 gegenüber 16 in 2020. Die letzte Zeile von 9 berücksichtigt nur Sitzungen bis zum 31. Juli 2026.

Die Entwicklung verläuft eher unregelmäßig als gleichmäßig. Genau das ist der entscheidende Punkt. Schwierige Handelstage treten in Clustern auf. Ein Bot, der am ersten Tag eines Clusters stoppt und am zweiten Tag wieder startet, war faktisch nicht wirklich angehalten.

Zwei Schwellenwerte erfüllen unterschiedliche Aufgaben. Ein tägliches Verlustlimit von üblicherweise 2 % des Kontokapitals beendet die Handelssitzung. Ein nachlaufendes Drawdown-Limit, gemessen vom Höchststand des Kontokapitals und üblicherweise bei etwa 10 %, beendet die Strategie bis zur Prüfung durch einen Menschen. Das erste Limit ist für den normalen Betrieb gedacht, das zweite soll selten erreicht werden. Ein Bot, der nur über das erste Limit verfügt, kann ein Konto schrittweise um jeweils 2 % reduzieren, ohne jemals eine weitere Schutzmaßnahme auszulösen.

Wie verändert die Volatilitätsskalierung die Positionsgröße?

Beim Volatilitäts-Targeting wird eine Position umgekehrt proportional zur jüngsten realisierten Volatilität dimensioniert: Verdoppelt sich die Tagesschwankungsbreite, wird die Position ungefähr halbiert. Dadurch bleibt das Dollar-Risiko je Trade annähernd konstant. Die realisierte Volatilität ist hier die annualisierte Standardabweichung der Tagesrenditen. Sie schwankt stärker, als die meisten Anleger erwarten.

AbfrageRealisierte Volatilität von SPY pro Monat und die Position bei einem Volatilitätsziel von 12 %
Das exakte SQL hinter jeder Zahl
WITH daily AS (
    SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2023-12-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY d
),
rets AS (
    SELECT d,
           close_px / any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) - 1 AS ret
    FROM daily
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
       round(stddevSamp(ret) * sqrt(252) * 100, 1) AS realized_vol_pct,
       round(least(100.0, 1200.0 / (stddevSamp(ret) * sqrt(252) * 100)), 1) AS vol_target_size_pct
FROM rets
WHERE d >= toDate('2024-01-01')
  AND isFinite(ret)
GROUP BY toStartOfMonth(d)
HAVING count() >= 15
ORDER BY toStartOfMonth(d)
Run this yourself

Die realisierte Volatilität, gemessen 11.1% annualisiert in 2024-01 und 12% in 2026-07, über 31 Monate. Die zweite Spalte übersetzt jeden Messwert in die Position, die ein Volatilitätsziel von 12 % erlauben würde, begrenzt auf die vollständige Zeile: 100% in 2024-01 gegenüber 99.7% in 2026-07. Dieselbe Strategie, dieselbe Überzeugung, eine sehr unterschiedliche Aktienanzahl.

Das Kelly-Kriterium nähert sich demselben Problem von der anderen Seite. Die Positionsgröße wird aus dem geschätzten Vorteil und der Varianz abgeleitet, nicht allein aus der Volatilität. Die meisten systematischen Anleger setzen nur einen Bruchteil davon ein, etwa halbes oder viertel Kelly. Beide Eingangsgrößen sind Schätzungen auf Basis einer begrenzten Stichprobe. Positionsgrößenbestimmung nach dem Kelly-Kriterium erläutert diese Berechnung.

Warum steigt ein Trading-Bot nach einem Stop immer wieder ein?

Ein Stop wird ausgelöst. Die Position wird geschlossen. Neunzig Sekunden später ist die Einstiegbedingung erneut erfüllt. Der Bot steigt wieder ein, erleidet denselben Verlust und wiederholt den Vorgang. Keine einzelne Komponente ist defekt. Die Strategie hat genau das getan, wofür sie programmiert wurde. Der Stop hat ebenfalls wie vorgesehen funktioniert. Trotzdem verliert das Konto eine Roundtrip-Position nach der anderen.

Die Häufigkeit ergibt sich direkt aus dem Kursverlauf. Dieses Panel zählt je Handelssitzung, wie oft sich SPY von mehr als 0,1 % über seinem Eröffnungskurs auf mehr als 0,1 % darunter bewegt hat oder umgekehrt.

AbfrageWie oft SPY pro Sitzung seinen eigenen Eröffnungskurs wieder kreuzt, nach Monat
Das exakte SQL hinter jeder Zahl
WITH mins AS (
    SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
           window_start AS ts,
           toFloat64(close) AS px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2025-08-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
),
opens AS (
    SELECT d, argMin(px, ts) AS open_px
    FROM mins
    GROUP BY d
),
zoned AS (
    SELECT m.d AS d,
           m.ts AS ts,
           multiIf(m.px >= o.open_px * 1.001, 1,
                   m.px <= o.open_px * 0.999, -1,
                   0) AS zone
    FROM mins AS m
    INNER JOIN opens AS o ON m.d = o.d
),
flips AS (
    SELECT d,
           zone,
           any(zone) OVER (PARTITION BY d ORDER BY ts ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_zone
    FROM zoned
    WHERE zone != 0
),
per_day AS (
    SELECT d, countIf(prev_zone != 0 AND zone != prev_zone) AS crossings
    FROM flips
    GROUP BY d
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
       round(avg(crossings), 1) AS avg_crossings_per_session,
       max(crossings) AS max_crossings_in_a_session
FROM per_day
GROUP BY toStartOfMonth(d)
ORDER BY toStartOfMonth(d)
Run this yourself

SPY durchquerte diese Bandbreite in 2025-08 durchschnittlich 0.7-mal je Sitzung und in 2026-07 1.5-mal. In einer Sitzung im Jahr 2026-07 wurden 5 Durchquerungen verzeichnet. Jede Regel, die auf der einen Seite eines Niveaus eröffnet und auf der anderen Seite den Stop setzt, kann an einem einzigen Tag entsprechend oft ausgelöst werden.

Vier Mechanismen begrenzen dieses Verhalten.

  • Eine Cooldown-Phase nach jedem Stop, gemessen in Minuten oder Bars. Während dieser Zeit wird für das betreffende Symbol keine neue Order von der Risikoschicht freigegeben.
  • Eine tägliche Obergrenze für die Zahl der Trades je Symbol. Sie macht aus einer unbegrenzten Schleife eine begrenzte.
  • Ein Halt-Flag, das einrastet. Sobald das tägliche Verlustlimit ausgelöst wird, bleibt es aktiv, bis eine Person es zurücksetzt.
  • Eine Speicherung dieses Flags außerhalb des Prozessspeichers. Ein Supervisor, der einen abgestürzten Bot neu startet, übergibt ihm andernfalls einen unberührten Status. Genau das soll das Flag verhindern.

Der letzte Punkt wird häufig übersehen, obwohl alle anderen Maßnahmen korrekt umgesetzt wurden. Grid-Trading-Bots platzieren konstruktionsbedingt Orderleitern. Dadurch wird die Obergrenze für die Zahl der Trades zu einer tragenden Risikokontrolle und nicht zu einer bloßen Formalität.

Was passiert, wenn ein Bot mit einem veralteten Preisfeed handelt?

Ein nicht mehr aktualisiertes Kurs- oder Quotierungsdatenfeed sieht weiterhin wie eine Zahl aus. Der Bot liest sie ein, berechnet darauf basierend einen Orderpreis und sendet die Order in einen Markt, der sich inzwischen bewegt hat. Der Fehler bleibt unbemerkt: Es wird keine Ausnahme ausgelöst, kein Fehler protokolliert, und die Ausführungen wirken erst im Nachhinein ungewöhnlich.

Die sauber messbare Variante ist die Übernachtlücke. Dabei bleibt ein bekannter Preis über Stunden unverändert, während sich der handelbare Preis bewegt.

AbfrageÜbernacht-Gap vom vorherigen Schlusskurs zur nächsten Eröffnung: sechs Titel, Jan. 2024 bis Juli 2026
Das exakte SQL hinter jeder Zahl
WITH daily AS (
    SELECT ticker,
           toDate(toTimeZone(window_start, 'America/New_York')) AS d,
           argMin(toFloat64(open), window_start) AS open_px,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('SPY', 'KO', 'MSFT', 'AAPL', 'NVDA', 'TSLA')
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2024-01-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY ticker, d
),
gaps AS (
    SELECT ticker,
           d,
           open_px,
           any(close_px) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
    FROM daily
)
SELECT ticker,
       round(quantileDeterministic(0.5)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS median_gap_pct,
       round(quantileDeterministic(0.95)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS p95_gap_pct,
       round(max(abs(open_px / prev_close - 1) * 100), 2) AS max_gap_pct
FROM gaps
WHERE prev_close > 0
GROUP BY ticker
ORDER BY p95_gap_pct DESC
Run this yourself

Der größte Wert nach dem 95. Perzentil der Lücken entfiel auf TSLA mit 4.41%, gegenüber 1% bei KO. In typischen Nächten waren die Bewegungen deutlich geringer: Die Medianlücken lagen bei 1.01% beziehungsweise 0.24%. Für die Randbereiche wird eine Risikoschicht entwickelt. Die größte einzelne Lücke bei TSLA im Messzeitraum betrug 14.57%. Das sind die Abstände, mit denen ein Bot konfrontiert ist, wenn er auf Grundlage eines Preises handelt, den er einige Zeit zuvor eingelesen hat. Warum Aktien über Nacht Lücken bilden erläutert die Mechanik.

Die Schutzmaßnahmen sind kostengünstig. Legen Sie für jede Quotierung, auf deren Grundlage die Risikoschicht Preise berechnet, ein maximales Alter fest. Bei einer Intraday-Strategie sind häufig wenige Sekunden angemessen. Überwachen Sie zusätzlich zum Datenfeed dessen Heartbeat. So lässt sich eine stumme Socket-Verbindung von einem ruhigen Markt unterscheiden. Behandeln Sie fehlende Daten als Handelsunterbrechung und nicht als unveränderte Kurse. Ein Bot ohne Preise kann auch seine Ausstiege nicht bewerten.

Welche harten Obergrenzen gehören in die Risikoschicht?

  • Maximaler Nominalwert je Symbol als Anteil am Kontoeigenkapital. Eine Obergrenze von 10 % verhindert, dass ein einzelnes problematisches Symbol das gesamte Konto belastet.
  • Maximaler Bruttonominalwert über alle offenen Positionen. Eine Begrenzung auf 100 % des Eigenkapitals bedeutet, dass kein Hebel eingesetzt wird. Diese Entscheidung sollte ausdrücklich getroffen werden, statt sie aus einer Broker-Voreinstellung zu übernehmen.
  • Maximale Orderrate pro Minute und pro Tag. Zehn Orders pro Minute sind für die meisten Strategien von Privatanlegern großzügig bemessen und begrenzen dennoch eine außer Kontrolle geratene Schleife innerhalb einer Minute.
  • Maximale Ordergröße als Anteil am durchschnittlichen Tagesvolumen des Symbols. Eine Obergrenze von 1 % verhindert, dass ein Bot den Kurs bewegt, zu dem er handeln will. Das durchschnittliche Tagesvolumen ist dabei der Nenner.

Jede dieser Obergrenzen gehört in die Risikoschicht und nicht in die Strategie. Jede wird in Backtest, Paper-Trading und Live-Handel über denselben Codepfad ausgeführt. Eine Begrenzung, die nur im Live-Handel existiert, wurde von niemandem getestet.

Was muss ein Audit-Log für einen Trading-Bot enthalten?

Ein Append-only-Log schreibt für jede Entscheidung einen Datensatz und ändert oder löscht ihn nie. Jeder Datensatz enthält den Zeitstempel, den verwendeten Kurs und dessen Alter, jede ausgeführte Limitprüfung mit ihrem Ergebnis, die gesendete Order und die Antwort des Brokers. Abgelehnte Orders werden mit derselben Bedeutung protokolliert wie ausgeführte Orders.

Der Zweck ist die Rekonstruktion. Sechs Wochen nach einer schlechten Handelssitzung lautet die entscheidende Frage nie, wie hoch das P&L war. Entscheidend ist, welche Prüfung mit welchem Input bestanden wurde. Ohne den aufgezeichneten Input müssen Sie den Zustand des Bots aus dem Zustand des Marktes nachträglich ableiten. Das ist derselbe Fehler wie Look-ahead-Bias im Backtesting: Sie verwenden Informationen, über die das System zum Zeitpunkt der Entscheidung noch nicht verfügte.

Das Projekt riskguard ist eine Open-Source-Implementierung dieser Trennung. Die Limitprüfungen liegen dabei in einer Komponente, die von der Strategie aufgerufen wird, statt über die Strategie selbst verstreut zu sein. Es ist eine von mehreren möglichen Gestaltungen und sollte gelesen werden, bevor Sie sie ungeprüft übernehmen. Unabhängig davon, worauf Sie sich stützen, sollten Sie eine getaggte Version statt des Default-Branches festschreiben. Ein Branch kann sich zwischen zwei Durchläufen desselben Backtests ändern. Eine unbemerkt geänderte Risikoschicht ist schlechter als gar keine.

Warum der erste Einsatz über einen Paper-Broker läuft

Der Broker-Adapter ist standardmäßig auf Paper-Trading eingestellt. Für den Live-Handel muss bewusst ein entsprechendes Flag gesetzt werden. Dadurch wird ein alltäglicher Fehler verhindert: Eine kopierte Konfigurationsdatei oder eine Umgebungsvariable, die nicht überschrieben wurde, könnte echte Orders mit echtem Geld auslösen.

Ein Paper-Lauf erzeugt außerdem das entscheidende Artefakt: ein Entscheidungsprotokoll aus derselben Risikoschicht auf Live-Kursen. Es zeigt, welche Limits ausgelöst wurden und welche nicht. Das liefert Erkenntnisse über die Risikoschicht. Ob die Strategie Geld verdient, ist eine davon getrennte Frage. Paper-Trading vor dem Einsatz echten Geldes erläutert, was ein Paper-Protokoll belegt und was nicht. Multi-Agent-AI-Trading-Systeme zeigt, warum die Befugnis zum Anhalten außerhalb jedes einzelnen Agenten liegen muss, sobald mehrere Agenten Orders platzieren können.

FAQ zum Circuit Breaker eines Trading-Bots

Was ist ein Circuit Breaker in einem Trading-Bot?

Eine Regel in der Risikoschicht, die den Bot daran hindert, neue Orders zu senden, sobald ein festgelegtes Limit erreicht ist. Meist handelt es sich um eine tägliche Verlustschwelle oder einen Drawdown vom Eigenkapitalhöchststand des Kontos. Die Regel läuft unabhängig von der Strategie bei jeder Order und bleibt ausgelöst, bis sie zurückgesetzt wird.

Wie oft verzeichnet der Markt einen Handelstag mit einem Minus von zwei Prozent?

SPY verzeichnete 5 Handelstage mit einem Minus von mindestens zwei Prozent in 2019 sowie 25 in 2020. Pro Jahr gibt es ungefähr 250 Handelstage. Diese Differenz zwischen einem ruhigen und einem angespannten Jahr zeigt, warum ein Verlustlimit anhand historischer Daten und nicht nach Gefühl kalibriert werden sollte.

Wie verhindert man, dass ein Bot nach einem Stop erneut einsteigt?

Ein Cooldown-Zeitraum nach jedem Stop und ein tägliches Trade-Limit je Symbol machen aus einer unbeschränkten Schleife eine begrenzte. Das Halt-Flag muss außerdem außerhalb des Prozessspeichers gesetzt und dauerhaft gespeichert werden. Andernfalls gibt ein Supervisor, der einen abgestürzten Bot neu startet, diesem einen neuen, nicht angehaltenen Zustand.

Wie erkennt ein Bot, dass ein Kursfeed veraltet ist?

Indem er vor der Orderpreisermittlung das Alter jedes Kurses prüft und zusätzlich einen Heartbeat des Feeds unabhängig von den Daten überwacht. Übernachtlücken zeigen, welches Ausmaß ein veralteter Kurs verbergen kann: Die Bewegung über Nacht am 95. Perzentil erreichte zwischen Januar 2024 und Juli 2026 4.41% am TSLA.

Braucht ein kleiner Trading-Bot wirklich ein Audit-Log?

Ein Log der Ausführungen hält fest, was geschehen ist. Ein Entscheidungslog hält fest, was der Bot nach seiner Einschätzung tun durfte. Nur damit lässt sich eine fehlerhafte Strategie von einer Risikoprüfung unterscheiden, die nie ausgeführt wurde. Ein unveränderliches Log, das auch Ablehnungen enthält, ist die minimale brauchbare Variante.


Jede oben genannte Zahl stammt aus einer gespeicherten Abfrage auf Basis von Minutenbalken. Über jedes Panel lässt sich die zugrunde liegende SQL-Abfrage öffnen. Richten Sie dieselben Abfragen im Strasmore-Terminal auf Ihre eigene Symbolliste.

#risk-management#trading-bots#drawdown#position-sizing#automation