⚠ Trading ist mit einem erheblichen Verlustrisiko verbunden. Alle Inhalte dieser Website dienen ausschließlich der Bildung und stellen keine Finanzberatung dar.
Lektion 7 von 13 · Kostenlos

Ein vektorisierter Backtest: Signale, Positionen, Verschiebung gegen Look-Ahead, Transaktionskosten und die Equity-Kurve

Bauen Sie in pandas einen vollständigen vektorisierten Backtest einer Regel mit gleitendem Durchschnitt, einschließlich der Positionsverschiebung, Kosten pro Trade, der Equity-Kurve und eines Benchmark-Vergleichs.

Autor: Moustafa HijaziInhalt geprüft: 2026-10-306 Min. LesezeitSelbstlernkurs

Was Sie lernen werden

  • Die Struktur eines vektorisierten Backtests aus fünf Spalten: Signal, Position, Rendite des Basiswerts, Kosten und Strategierendite.
  • Warum shift(1) auf der Positionsspalte die eine Zeile ist, die einen ehrlichen Test von einer Look-Ahead-Fantasie trennt.
  • Wie Sie proportionale Transaktionskosten auf Positionsänderungen berechnen und eine Equity-Kurve in Euro aufbauen.
  • Was ein vektorisierter Test modellieren kann und was nicht, und wann die ereignisgesteuerte Engine aus Lektion 8 nötig ist.

Erklärung

Ein vektorisierter Backtest berechnet die gesamte Historie auf einmal mit Spaltenoperationen, statt Balken für Balken in einer Schleife vorzugehen. Der Tabellenkalkulations-Backtest aus dem Kurs „Systematisches Trading“ hatte diese Struktur; pandas führt ihn über Jahrzehnte in Millisekunden aus. Er eignet sich für Long-Flat- oder Always-in-Regeln, die auf den Schlusskurs reagieren; Intrabar-Stops und konkrete Ausführungskurse sind Aufgabe von Lektion 8.

Schritt 1, Signal. signal = (close > sma(close, 50)).astype(int) ergibt 1, wenn der Schlusskurs über seinem 50-Tage-Durchschnitt liegt, sonst 0. Es beschreibt, was Sie zum Schlusskurs von Balken t wissen.

Schritt 2, Position. Sie können nicht auf einen Schlusskurs handeln, den Sie noch nicht gesehen haben; frühestens in Balken t + 1 können Sie das Signal von Balken t halten, also position = signal.shift(1).fillna(0). Zeile t der Positionsspalte bedeutet nun „das während Balken t gehaltene Exposure“, entschieden am Ende von Balken t − 1. Lässt man die Verschiebung weg, verdient die Strategie die Rendite von Balken t mithilfe des Schlusskurses von Balken t; das ist Look-Ahead-Bias: die Nutzung von Informationen, die zum Entscheidungszeitpunkt nicht verfügbar waren.

Schritt 3, Rendite des Basiswerts. ret = close.pct_change().fillna(0) (Lektion 5). Da die Position während Balken t zum Schlusskurs von Balken t − 1 festgelegt wurde, ist position * ret die Bruttorendite der Strategie für Balken t. Die implizite Annahme ist eine Ausführung zum Schlusskurs von Balken t − 1; Lektion 8 behandelt Ausführungen zur nächsten Eröffnung.

Schritt 4, Kosten. Provision, Spread und Slippage werden als proportionaler Satz pro geänderter Positionseinheit modelliert: turnover = position.diff().abs().fillna(0) ist 1 beim Wechsel von flat zu long oder zurück und 2 bei einer Umkehr. cost = turnover * c, wobei c die einfachen Kosten (pro Richtung) als Bruchteil sind (0.001 für 0.1%). Die Kosten gehen in die Renditespalte des Balkens ein, in dem sich die Position ändert.

Schritt 5, Strategierendite und Equity. strat = position * ret - cost und equity = capital * (1 + strat).cumprod(). Die Buy-and-Hold-Benchmark ist capital * (1 + ret).cumprod(). Vergleichen Sie beide immer mit denselben Kennzahlen (Lektion 9); Buy-and-Hold bloß mit Cash zu verdünnen senkt Drawdown und Rendite gleichermaßen, und das ist kein Können.

Nennen Sie die Annahmen: Das Exposure ist ein täglich reinvestierter Anteil der Equity, Ausführung zum Schlusskurs, proportionale Kosten, keine Zinsen auf Cash, Dividenden nur über adjustierte Daten, Steuern werden ignoriert. Der Test beantwortet dann eine eng gefasste Frage: Hat die Timing-Regel nach Kosten etwas gegenüber dem Halten des Basiswerts gebracht?

Prüfungen, bevor Sie der Ausgabe vertrauen. (1) Setzen Sie die Kosten auf null und das Signal konstant auf 1; die Equity muss exakt Buy-and-Hold entsprechen. (2) Zählen Sie die Round Trips mit turnover.sum() / 2 und prüfen Sie die Plausibilität. (3) Stellen Sie sicher, dass die NaN-Zeilen der Aufwärmphase des Indikators eine Position von null ergeben und keinen falschen Trade.

Durchgerechnetes Beispiel

Hypothetisches Beispiel: acht Schlusskurse in Euro, 100, 101, 103, 102, 104, 103, 101, 100; long, wenn der Schlusskurs strikt über seinem 3-Tage-SMA liegt, sonst flat; einfache Kosten 0.1%; Kapital €10,000; keine Zinsen, Dividenden oder Steuern.

Balken Schluss SMA3 Signal Position Rendite Umschlag Strategie Equity €
0 100 – 0 0 0 0 0 10,000.00
1 101 – 0 0 +1.000% 0 0 10,000.00
2 103 101.33 1 0 +1.980% 0 0 10,000.00
3 102 102.00 0 1 −0.971% 1 −1.071% 9,892.91
4 104 103.00 1 0 +1.961% 1 −0.100% 9,883.02
5 103 103.00 0 1 −0.962% 1 −1.062% 9,778.11
6 101 102.67 0 0 −1.942% 1 −0.100% 9,768.33
7 100 101.33 0 0 −0.990% 0 0 9,768.33

Balken 3: Das Signal in Balken 2 war 1 (103 > 101.33), also ist die Position während Balken 3 gleich 1. Der Basiswert fiel von 103 auf 102 (−0.971%), der Umschlag von 1 kostet 0.1%, die Strategierendite beträgt −1.071%, die Equity 10,000 × (1 − 0.01071) = €9,892.91. In Balken 3 entspricht der Schlusskurs dem SMA, die strikte Regel ergibt also 0, und die Position wird während Balken 4 geschlossen (Kosten 0.1%, kein Exposure). End-Equity €9,768.33 (−2.32%) gegenüber Buy-and-Hold von exakt €10,000. Die Kosten beliefen sich auf €39.36 über vier einfache Transaktionen.

Nun die Look-Ahead-Version, die signal statt der verschobenen position verwendet: Die Strategie „hält“ während der Balken 2 und 4, der beiden Aufwärtstage, die sie erst nach deren Schluss erkennen konnte, und endet bei €10,356.65 (+3.57%). Ein einziges fehlendes shift(1) hat aus −2.32% ein Ergebnis von +3.57% gemacht.

Häufiger Fehler

Das Falsche verschieben oder doppelt verschiebenWird der Kurs statt der Position verschoben, oder werden sowohl Signal als auch Renditen verschoben, wird entweder wieder Look-Ahead eingeführt oder werden Einstiege um einen Tag verzögert. Halten Sie sich an eine Konvention: Indikatoren und Signale werden auf dem Schlusskurs von Balken t berechnet; position = signal.shift(1); Renditen sind einfaches pct_change().

Übungsaufgabe

Auf Papier, mit denselben acht Schlusskursen und derselben Regel: (a) Berechnen Sie die End-Equity mit einfachen Kosten von 0.2% neu; (b) geben Sie die Anzahl der Round Trips an; (c) ein Kollege schlägt vor, die ersten NaN-Werte des SMA mit dem Schlusskurs aufzufüllen, damit „der Handel am ersten Tag beginnen kann“; erklären Sie kurz, warum das ein Problem ist.

Lösung anzeigen

(a) Nur die vier Balken mit Umschlag ändern sich. Balken 3: −1.171% → €9,882.91; Balken 4: −0.2% → €9,863.15; Balken 5: −1.162% → €9,748.58; Balken 6: −0.2% → €9,729.09. Endverlust 2.71% gegenüber 2.32% bei 0.1%; die Verdopplung des Kostensatzes kostete zusätzlich €39.24.

(b) Der Umschlag summiert sich auf 4 einfache Änderungen, also 2 Round Trips (Einstieg während Balken 3, Ausstieg in Balken 4; Einstieg in Balken 5, Ausstieg in Balken 6).

(c) Wird der SMA mit dem Schlusskurs aufgefüllt, entstehen Trades aus einem Indikator, den es noch gar nicht gibt, sodass ihre Logik von der getesteten Regel abweicht; halten Sie während der Aufwärmphase eine Position von null und notieren Sie, wie viele Balken ausgeschlossen wurden.

Einschränkungen: Acht Balken belegen die Mechanik, nicht die Regel; proportionale Kosten und Ausführungen zum Schlusskurs unterschätzen die Slippage bei illiquiden Instrumenten.

Kernaussagen

  • Ein vektorisierter Backtest besteht aus fünf Spalten: Signal, Position (verschoben), Rendite des Basiswerts, Kosten auf den Umschlag, Strategierendite; die Equity ist das kumulierte Produkt.
  • position = signal.shift(1) ist nicht verhandelbar; testen Sie das, indem Sie die Zeile entfernen und beobachten, wie sich das Ergebnis aufbläht.
  • Berechnen Sie Kosten auf position.diff().abs() und vergleichen Sie immer mit Buy-and-Hold unter identischen Annahmen.
  • Vektorisierte Tests eignen sich für Regeln von Schlusskurs zu Schlusskurs; Stops, Positionsgrößen und realistische Ausführungen erfordern die ereignisgesteuerte Engine aus Lektion 8.

Nächster Schritt

Lektion 8 baut einen ereignisgesteuerten Backtest: eine Schleife Balken für Balken mit ATR-Stops, Positionsgrößenbestimmung und einer Trade-Liste, gemessen in R-Multiples.

Selbsttest

Beantworten Sie die Fragen und prüfen Sie dann Ihre Antworten. Sie können es so oft wiederholen, wie Sie möchten.

1. Warum wird in einem vektorisierten Backtest die Positionsspalte als signal.shift(1) statt als signal definiert?

2. Eine Strategie ist drei aufeinanderfolgende Balken long, mit Renditen des Basiswerts von +1.0%, −2.0% und +0.5%; der Einstieg erfolgt zu Beginn des ersten Balkens und der Ausstieg am Ende des dritten, bei einfachen Kosten von 0.1%. Wie hoch ist die End-Equity ausgehend von €10,000 (Kosten werden auf den Einstiegs- und den Ausstiegsbalken angerechnet)?

3. Sie setzen die Kosten auf null und erzwingen das Signal 1 auf jedem Balken. Die Equity-Kurve der Strategie endet 4% unter Buy-and-Hold. Was sagt Ihnen das?

Automatischer Selbsttest zur eigenen Wiederholung. Ihre Antworten werden in Ihrem Browser geprüft und von uns weder eingesehen noch bewertet. Es ist keine Prüfung und kein Abschluss.

Ihr Fortschritt

„Erledigt“ bedeutet nur, dass Sie die Lektion als abgeschlossen markiert haben. Es ist kein Test Ihres Verständnisses. Fortschritt und Notizen werden nur in diesem Browser auf diesem Gerät gespeichert — nicht in einem Konto.