Look-ahead-Bias Backtest Fehler vermeiden
Look-ahead-Bias verfälscht Backtests durch zukünftige Daten. Erfahren Sie, wie gleiche Balken, Survivorship und revidierte Zahlen Ergebnisse aufblähen und wie Sie den Fehler erkennen.
Look-ahead-Bias liegt vor, wenn in einem Backtest Informationen verwendet werden, die zum Zeitpunkt der simulierten Transaktion niemand haben konnte. Die Eigenkapitalkurve steigt, die Statistiken sehen hervorragend aus – und nichts davon überlebt den Kontakt mit einem echten Auftrag. Diese Seite definiert den Bias, beschreibt drei Mechanismen, die ihn erzeugen, und misst jeden an echten Marktdaten.
Was Look-ahead-Bias ist
Ein Backtest ist eine Behauptung über eine Entscheidung: Zu diesem Zeitstempel, mit diesen Informationen, hätte die Regel dies getan. Die Behauptung gilt nur, wenn jede Eingabe, die die Regel liest, bereits in ihrer endgültigen Form vor diesem Zeitstempel existierte. Look-ahead-Bias ist jeder Verstoß gegen diese Bedingung – und er ist still. Nichts in einer Tabellenkalkulation oder einem Skript beschwert sich, wenn eine Zeile einen Wert zurückgibt, der später gestempelt wurde als die Entscheidung, die er speist.
Drei Verstöße decken den Großteil dessen ab, was in der Praxis vorkommt: Eine Entscheidung, die einen Preisbalken liest, in dem sie auch handelt. Ein Universum, das aus den Namen zusammengestellt wird, die heute noch notiert sind. Ein Datenfeld, das nach dem Datum, das es trägt, revidiert wurde.
Mechanismus eins: Entscheiden auf einem Balken, den Sie auch handeln
Beginnen wir mit einer Regel, die harmlos klingt. Kaufen auf Stärke, also an Sitzungen, an denen der Fonds über seinem Eröffnungskurs schließt. Schlampig programmiert, steigt der Test zur Eröffnung dieser Sitzung ein und verlässt sie zum Schluss dieser Sitzung, während die Bedingung, nach der er filtert, der Schlusskurs desselben Balkens ist. Niemand kennt einen Schlusskurs zur Eröffnungsglocke.
Das folgende Panel führt beide Versionen auf SPY, dem S&P 500-Tracker, über zehn Kalenderjahre aus. Die erste Spalte ist die unmögliche. Die zweite verzögert die identische Bedingung um eine einzige Sitzung – das ist der früheste Zeitpunkt, zu dem ein finanziertes Konto darauf reagieren könnte.
Das exakte SQL hinter jeder Zahl
WITH bars AS (
SELECT date,
toFloat64(open) AS o,
toFloat64(close) AS c,
toFloat64(close) > toFloat64(open) AS up_day
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= toDate('2015-12-01')
AND date <= toDate('2025-12-31')
),
lagged AS (
SELECT date, o, c, up_day,
any(up_day) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prior_up
FROM bars
)
SELECT toYear(date) AS year,
countIf(up_day) AS signal_days,
round(100 * avgIf(c / o - 1, up_day), 3) AS same_bar_avg_pct,
round(100 * avgIf(c / o - 1, prior_up), 3) AS lagged_avg_pct,
round(100 * (avgIf(c / o - 1, up_day) - avgIf(c / o - 1, prior_up)), 3) AS gap_pp
FROM lagged
WHERE date >= toDate('2016-01-01')
GROUP BY year
ORDER BY yearDer Unterschied ist nicht subtil. In 2016 erzielte die Version mit demselben Balken durchschnittlich 0.447% pro qualifizierender Sitzung, während die verzögerte Version durchschnittlich -0.008% erzielte – eine Spanne von 0.455 Prozentpunkten pro Tag. In 2025 lauten die beiden Werte 0.636% und -0.03%. Bei etwa 140 qualifizierenden Sitzungen pro Jahr summiert sich eine Spanne von einem halben Prozentpunkt pro Sitzung zu einer Eigenkapitalkurve, die kein Live-Konto je gedruckt hat.
Der gesamte Vorteil ist definitionsbedingt. Die Auswahl von Sitzungen, die über ihrem Eröffnungskurs schlossen, und dann die Messung der Eröffnungs-Schluss-Spanne in genau diesen Sitzungen misst eine Größe, die garantiert positiv ist. Die Regel hat ihren eigenen Filter entdeckt.
Varianten davon verstecken sich ständig in Tagesdaten: ein gleitender Durchschnitt, der den heutigen Schlusskurs enthält und zum Handeln heute verwendet wird; ein Signal, das auf Preisen berechnet wird, die bereits für einen Split angepasst wurden, der noch nicht stattgefunden hatte; ein Intraday-Stopp, der auf ein Tageshoch gesetzt wird, das noch nicht gedruckt wurde. Die gemeinsame Form ist ein Entscheidungszeitstempel, der vor einem seiner eigenen Inputs liegt.
Mechanismus zwei: Ein Universum aus den heutigen Überlebenden
Der zweite Mechanismus berührt die Regel nie. Er sitzt in der Liste der Namen, die die Regel sehen darf.
Ziehen Sie eine Tickerliste von einem aktuellen Datenanbieter, lassen Sie sie zehn Jahre zurücklaufen, und die Stichprobe schließt stillschweigend jedes Unternehmen aus, das in der Zwischenzeit bankrottging, übernommen oder dekotiert wurde. Die Regel bekam die Verlierer nie angeboten. Das Panel misst das Ausmaß dieser Auslassung: Jeder in den USA notierte Name, der in einem bestimmten Kalenderjahr mindestens 200 Sitzungen über 1 $ handelte, der Anteil dieser Kohorte, der im Juli 2026 noch Preise druckt, und die mediane Kalenderjahresrendite der gesamten Kohorte neben der Medianrendite der Überlebenden allein.
Das exakte SQL hinter jeder Zahl
WITH recent AS (
SELECT DISTINCT ticker
FROM global_markets.stocks_daily_aggs
WHERE date >= toDate('2026-06-15')
AND date <= toDate('2026-07-28')
),
per_name AS (
SELECT toYear(date) AS year,
ticker,
argMin(toFloat64(close), date) AS first_close,
argMax(toFloat64(close), date) AS last_close,
count() AS sessions
FROM global_markets.stocks_daily_aggs
WHERE date >= toDate('2015-01-01')
AND date <= toDate('2024-12-31')
AND close > 1
GROUP BY year, ticker
HAVING sessions >= 200
)
SELECT year,
uniqExact(ticker) AS names_trading,
round(100 * uniqExactIf(ticker, ticker IN (SELECT ticker FROM recent)) / uniqExact(ticker), 1) AS still_listed_pct,
round(100 * quantileDeterministic(0.5)(last_close / first_close - 1, cityHash64(ticker)), 2) AS median_return_all_pct,
round(100 * quantileDeterministicIf(0.5)(last_close / first_close - 1, cityHash64(ticker), ticker IN (SELECT ticker FROM recent)), 2) AS median_return_survivors_pct,
round(100 * (quantileDeterministicIf(0.5)(last_close / first_close - 1, cityHash64(ticker), ticker IN (SELECT ticker FROM recent))
- quantileDeterministic(0.5)(last_close / first_close - 1, cityHash64(ticker))), 2) AS survivor_gap_pp
FROM per_name
GROUP BY year
ORDER BY yearVon den 7063 Namen, die die Hürde in 2015 nahmen, wurden 52.5% im Juli 2026 noch gehandelt. Für die Kohorte 2024 liegt die Zahl bei 87.5%, was hauptsächlich eine Frage der verstrichenen Zeit ist: Ein Name aus dem Jahr 2024 hatte zwei Jahre Zeit zu verschwinden, einer aus dem Jahr 2015 hatte elf Jahre.
Die Renditespalten tragen den Bias selbst. In 2017 erzielte der Medianname eine Rendite von 7.51%, während der Medianüberlebende 11.32% erzielte – eine Lücke von 3.81 Prozentpunkten, die gratis dazugegeben wird. Die Lücke ist in jedem der 10 dargestellten Jahre positiv. Eine Strategie, die auf Überlebenden getestet wird, erbt sie, bevor sie eine einzige Entscheidung trifft, und Regeln, die auf Schwäche screenen, erben mehr als den Median, da die verschwundenen Namen überproportional in diesem Eimer sitzen.
Die Korrektur ist ein Point-in-Time-Universum: die Liste der Namen, wie sie an jedem Rebalancing-Datum bestand, inklusive Dekotierungen, wobei eine dekotierte Position zu ihrem letzten Ausdruck geschlossen wird, anstatt aus der Aufzeichnung gestrichen zu werden.
Mechanismus drei: Daten, die nach ihrem Datumsstempel revidiert wurden
Preise werden einmal gestempelt. Fundamentaldaten nicht. Eine Quartalszahl trägt das Quartalsendedatum, wird durch eine spätere Einreichung geändert, und eine Datenbank, die nur die aktuelle Version speichert, serviert bereitwillig die geänderte Zahl zum ursprünglichen Datum. Eine Regel, die auf diese Zahl screent, liest eine Korrektur, deren Eintreffen Monate dauerte.
Dasselbe Muster durchzieht Indexmitgliedslisten, die auf aktuelle Bestandteile zurückgebaut wurden, Analystenschätzungsverläufe, die mit dem endgültigen Konsens überschrieben wurden, und Kapitalmaßnahmenanpassungen, die rückwirkend auf eine gesamte Preisserie angewendet wurden. In jedem Fall ist die gespeicherte Aufzeichnung eine Momentaufnahme im Präsens, die ein Datum in der Vergangenheit trägt.
Zwei Praktiken enthalten es. Verwenden Sie eine Quelle, die Jahrgänge führt, also den Wert, wie er an jedem Datum bekannt war, und nicht den Wert, wie er heute bekannt ist. Wo Jahrgänge nicht verfügbar sind, wenden Sie einen Meldungsverzug an, der großzügig genug ist, um den tatsächlichen abzudecken, und behandeln Sie die Länge dieses Verzugs als einen zu testenden Parameter und nicht als ein zu erratendes Detail.
Wie die Kurve aussieht, wenn die Zukunft durchsickert
Look-ahead-Bias hat eine Signatur: eine Performance, die weit über dem liegt, was der zugrunde liegende Markt bot. Ein nützlicher Referenzpunkt ist die Rückschau-Obergrenze, das Wachstum, das eine perfekte Eintages-Vorhersage auf einem einzelnen Instrument erzielt hätte.
Das exakte SQL hinter jeder Zahl
WITH bars AS (
SELECT date,
toFloat64(close) AS c,
any(toFloat64(close)) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_c
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= toDate('2015-12-01')
AND date <= toDate('2025-12-31')
),
rets AS (
SELECT toYear(date) AS year,
c / prev_c - 1 AS r
FROM bars
WHERE date >= toDate('2016-01-01')
AND prev_c > 0
)
SELECT year,
count() AS sessions,
round(100 * (exp(sum(log(1 + r))) - 1), 1) AS buy_and_hold_pct,
round(100 * (exp(sumIf(log(1 + r), r < 0.02)) - 1), 1) AS without_big_up_days_pct,
round(exp(sum(log(1 + abs(r)))), 1) AS hindsight_ceiling_multiple
FROM rets
GROUP BY year
ORDER BY yearDie Obergrenze ist enorm. In 2020 vervielfachte perfekte Eintages-Voraussicht auf SPY das Kapital 27.7-fach über 253 Sitzungen, verglichen mit 16.2% für das bloße Halten des Fonds. Im ruhigsten Jahr der zehn, 2017, brachte dieselbe perfekte Vorhersage das 2.2-fache des Kapitals.
Die mittlere Spalte zeigt, wie konzentriert diese Obergrenze ist. Entfernt man die Sitzungen mit einem Gewinn von mehr als 2%, verwandelt sich 2020 von 16.2% in -44.9%. Ein Leck, das nur eine Handvoll dieser Sitzungen pro Jahr wert ist, bewegt einen Backtest sehr weit. Eine Kurve mit flachen Drawdowns, einer hohen Trefferquote und ihren besten Tagen, die auf den gewalttätigsten Sitzungen des Marktes gehäuft sind, hat eine Prüfung verdient.
Die Kalibrierung ist wichtiger als jeder einzelne Schwellenwert. Eine Regel, die über ein Jahrzehnt hinweg glatte 40% pro Jahr behauptet, beansprucht einen großen Teil der Rückschau-Obergrenze, und die ehrliche Frage ist, welche Eingabe ihr verriet, was gleich passieren würde.
Wie man einen Backtest auf Look-ahead-Bias testet
- Verzögern Sie alles um einen Balken. Verschieben Sie jedes Signal um eine volle Periode nach hinten und führen Sie es erneut aus. Echte Vorteile zerfallen ein wenig. Lecks brechen zusammen, oft bis auf null.
- Stören Sie die Zukunft. Nehmen Sie die Daten nach jedem Entscheidungszeitstempel, ersetzen Sie sie durch Rauschen oder eine Neuanordnung und führen Sie die Entscheidungslogik erneut aus. Jede Entscheidung sollte identisch herauskommen. Jede Entscheidung, die sich bewegt, hat etwas gelesen, das sie nicht wissen konnte.
- Behandeln Sie Zeitstempel als Daten. Speichern Sie für jede Eingabe den Moment, in dem ein Wert verfügbar wurde, neben dem Moment, den er beschreibt. Ein Join, der diese beiden Spalten nie vergleicht, kann die Regel nicht durchsetzen.
- Bauen Sie das Universum zum jeweiligen Datum neu auf. Schließen Sie dekotierte und übernommene Namen ein, schließen Sie sie zu ihrem letzten Ausdruck und führen Sie dieselbe Regel auf beiden Universen aus, um den Survivorship-Beitrag zu bemessen.
- Messen Sie gegen die Obergrenze. Setzen Sie die Rendite der Strategie neben eine Buy-and-Hold-Zahl und eine Perfekte-Voraussicht-Zahl für dasselbe Fenster. Der Abstand zur Obergrenze ist ein Kontext, den eine Sharpe Ratio allein nicht liefert.
Die Positionsgrößenbestimmung liegt stromabwärts von alledem. Eine aufgeblähte Gewinnrate speist eine aufgeblähte Einsatzgröße, und das ist der Punkt, an dem Kelly-Kriterium Positionsgrößenbestimmung einen Buchhaltungsfehler in einen Drawdown verwandelt. Dieselbe Disziplin gilt, bevor echtes Kapital bewegt wird: Papierhandel vor echtem Geld testet Auftragsmechaniken, und automatisierte Stacks tragen dieselbe Gefahr mit Maschinengeschwindigkeit, behandelt in Multi-Agent-KI-Handelssysteme. Effekte, die sorgfältige Point-in-Time-Tests überleben, wie die Niedrigvolatilitätsanomalie, sind genau aus diesem Grund interessant.
FAQ
Was ist Look-ahead-Bias im Backtesting?
Es ist die Verwendung von Daten in einem simulierten Handel, die zum Zeitpunkt der Platzierung des Handels nicht verfügbar waren. Häufige Formen sind die Entscheidung auf einem Preisbalken, in dem der Handel auch ausgeführt wird, das Screening eines Universums von Unternehmen, die heute noch notiert sind, und das Lesen einer Finanzzahl, die nach dem daran hängenden Datum revidiert wurde.
Wie kann man Look-ahead-Bias erkennen?
Verzögern Sie jedes Signal um eine volle Periode und führen Sie es erneut aus: Ein Leck bricht meist zusammen, während ein echter Vorteil sanft zerfällt. Ein stärkerer Test ersetzt alle Daten nach jedem Entscheidungszeitstempel durch Rauschen und bestätigt, dass jede Entscheidung unverändert herauskommt.
Ist Survivorship-Bias dasselbe wie Look-ahead-Bias?
Sie sind verschieden, treten aber gemeinsam auf. Survivorship-Bias ist eine Stichprobe, die aus den Namen besteht, die überlebt haben, und zu wissen, welche Namen überlebt haben, ist selbst eine Information aus der Zukunft. Daher ist ein Nur-Überlebenden-Universum ein Look-ahead-Leck, das in den Daten und nicht in der Regel sitzt.
Warum sehen Backtests mit Look-ahead-Bias so gut aus?
Das Leck selektiert Ergebnisse, anstatt sie vorherzusagen. Im obigen Panel erzeugte das Screening von Sitzungen auf ihren eigenen Schlusskurs einen durchschnittlichen Sitzungsgewinn von etwa 0.455 Prozentpunkten über der verzögerten Version in 2016, ein Vorteil, der definitionsbedingt und nicht verdient ist.
Was sind Point-in-Time-Daten?
Point-in-Time-Daten speichern jeden Wert so, wie er an jedem historischen Datum bekannt war, einschließlich der ursprünglichen Zahl und jeder späteren Revision, zusammen mit dem Universum der Wertpapiere, wie es an diesem Tag bestand. Es ist die Referenz, die ein Backtest benötigt, um zu zeigen, dass seine Eingaben vor seinen Entscheidungen existierten.
Jede Zahl oben ist eine gespeicherte, versionierte Abfrage über echte Tagesbalken. Erweitern Sie das SQL eines beliebigen Panels oder führen Sie den Lag-Test mit Ihrer eigenen Regel auf dem Strasmore-Terminal aus.