Dokumentation1.0 (latest)
SeitenLebenszyklus einer Strategie · 8 / 29

Strategie-Lebenszyklus

Eine QuantCraft-Strategie ist eine gewöhnliche Python-Datei, die eine kleine Menge von Callback-Funktionen definiert. Die Backtest-Engine ruft diese Funktionen in fester Reihenfolge auf, während sie die historischen Daten durchläuft. Sie rufen sie nicht selbst auf — das tut die Engine. Nutzen Sie Test, um sie auszulösen (Code ausführen).

Der Lebenszyklus von Anfang bis Ende:

on_init → on_bar → on_tick (×4 per bar) → account tick(close) → on_finish └─────────── repeats for every bar ───────────┘

Im Backtest wird on_tick viermal pro Balken auf synthetischem OHLC aus jedem Balken ausgelöst (keine echte Tick-Historie). Nach diesen vier Ticks nimmt die Engine eine letzte Mark-to-Market-Bewertung des Kontos zum Schluss vor — kein fünftes on_tick. on_timer steht nur bei Forward-Läufen zur Verfügung (Chart-Forward, Forward-Bulk / QuantCloud), wenn timerIntervalMs gesetzt ist — der IDE-Dialog Run backtest hat kein Timer-Bedienelement. Bei Forward-Läufen läuft on_tick bei jedem Kursupdate Ihres verbundenen Brokers; an Intraday-Grenzen wird oft on_tick dann on_bar ausgelöst — nehmen Sie nicht die Backtest-Reihenfolge an.

Diese Seite behandelt jeden Callback, wie Multi-Symbol-Strategien daran andocken, und die Grundlagen, die Sie für Ihre erste Strategie brauchen.


Die Strategiedatei

Eine minimale Strategie sieht so aus:

import quantcraft.process.runtime as bt # account, chart_indicators, qc_* handles from quantcraft import Timeframe import quantcraft.runtime as rt def on_init(symbols=None): pass def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None): close_px = float(bar["close"]) daily = rt.get_bar(Timeframe.DAILY, shift=1) def on_tick(bar_index, tick_in_bar, price, bar, fundamentals=None, calendar=None, symbol=None): if tick_in_bar == 3: close_px = price def on_finish(bars, symbol=None, bars_by_symbol=None): pass

Einige Regeln gelten für alle Callbacks:

  • Sie müssen Funktionen auf oberster Ebene in Ihrer Datei sein (nicht verschachtelt oder in einer Klasse).
  • Die Backtest-Engine verlangt aufrufbare on_init, on_bar, on_tick und on_finish (sonst scheitert der Lauf mit User script must define callable: …). Die IDE-Schaltflächen Test, Compile und Debug Test erscheinen, wenn der aktive .py-Tab on_init / on_bar / on_finish definiert; ein fehlendes on_tick lässt den Backtest beim Start dennoch scheitern. on_timer ist optional und wird nur bei Forward-Läufen mit Timer-Intervall genutzt.
  • Fügen Sie nur die optionalen Argumente hinzu, die Sie nutzen. calendar, symbols (bei on_init) und die Argumente von on_finish werden nach Namen zugeordnet; fundamentals und symbol werden zugeordnet, indem nacheinander die gängigen Formen probiert werden, daher behalten Sie die dokumentierte Reihenfolge bei. Die sicherste vollständige Signatur ist def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None). Ein deklariertes calendar erhält immer das Kalender-Handle oder None — nie das Fundamentaldaten-Objekt.
  • In Callbacks platzieren Sie Orders über account und zeichnen Indikatorwerte über chart_indicators auf (Indikatorserien) — beides wird aus quantcraft.process.runtime gelesen.

Runtime-Globals

Die Engine stellt diese aus quantcraft.process.runtime bereit, bevor Callbacks laufen:

NameZweck
accountPaperAccount-Instanz, konfiguriert über den Tab Simulation (Saldo + Provision / Slippage). Bei Forward-Läufen ist es ein Live-Broker-Konto mit derselben API, das echte Orders platziert — siehe Kontomodell
chart_indicatorsChartIndicatorSeries-Collector, der ins Ergebnis zusammengeführt wird — sammeln Sie Werte, während der Lauf die Balken durchgeht, und geben Sie die Serien in on_finish aus
qc_fundamentalsOptionales QcFundamentals-Handle, wenn Fundamentaldaten geladen sind
qc_fama_frenchOptionales QcFamaFrench, wenn globale Fama-French-Faktoren geladen sind; bevorzugen Sie in Callbacks fama_french.qc — siehe Fama-French-Faktoren
qc_calendarBacktestCalendar | None — Kalenderdaten, wenn Include calendar data aktiviert ist; deckt jedes gehandelte Symbol ab. Nur Backtests — bei Forward-Läufen immer None. Callbacks können dasselbe Handle erhalten, indem sie ein Argument calendar benennen — siehe Kalenderdaten
qc_ohlcv_by_tfOptionale Puffer sekundärer Zeitrahmen, indiziert über den Zeitrahmen-String (fortgeschritten; bevorzugen Sie get_bar)
get_bar(tf, shift=1)Empfohlene API für den primären und die zusätzlichen Zeitrahmen — gibt einen BarSnapshot oder None zurück; Import über import quantcraft.runtime as rt

Bevorzugen Sie das Argument bars von on_finish(bars, ...) für Vollserien-Rechnungen — verlassen Sie sich in IDE-Strategien nicht auf das qc_ohlcv auf Modulebene (es ist beim Import oft None, bei einem Lauf mit Screener-Ziel None und umfasst sonst den gesamten geladenen Bereich einschließlich Warmup). Lesen Sie Kurse in Callbacks aus dem bar-Objekt. isinstance(bar, dict) ist False — OhlcvBarView ist ein Mapping (dict-artiger Zugriff funktioniert weiterhin).

Lesen Sie diese als Modulattribute. Jedes Handle wird von einem Wert pro Sitzung getragen, daher beziehen sich bt.account / bt.chart_indicators immer auf diesen Lauf. from quantcraft.process.runtime import account bindet einen Schnappschuss — in der Algo-Stammdatei bei einem Backtest in Ordnung, weil die Engine diese Namen nach dem Laden neu bindet (Forward-Läufe binden nur account, qc_fundamentals und qc_fama_french neu, nutzen Sie dort also bt.chart_indicators und rt.qc_ohlcv*), aber falsch in einem aufgeteilten Hilfsmodul, das in sys.modules gecacht bleibt und das Handle der ersten Sitzung behalten würde. Siehe Modul-Handles vs. importierte Namen.

Sekundäre Zeitrahmen

Der primäre Zeitrahmen des Laufs ist immer über rt.get_bar verfügbar. Wählen Sie zusätzliche Balkengrößen im Dropdown Additional timeframes des Dialogs Run backtest unter Symbol & data (Backtests) und lesen Sie sie dann aus jedem Callback:

from quantcraft import Timeframe import quantcraft.runtime as rt def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None): daily = rt.get_bar(Timeframe.DAILY, shift=1) if daily and bar.close[0] > daily.close: account.open_trade(...)

Die vollständige Semantik von shift, das Enum Timeframe und die Hinweise zu Forward-Läufen finden Sie unter OHLCV- und Balkendaten.

Ausführungszeitpunkt

  • bar["close"] in on_bar ist der Schlusskurs des aktuellen Ausführungsbalkens.
  • account.open_trade / close_trade nehmen einen angeforderten Kurs entgegen und wenden dann die Slippage- und Provisionsmodelle des Laufs an. Die gespeicherten entry_price / exit_price sind die Ausführungskurse; die angeforderten Kurse bleiben als raw_entry_price / raw_exit_price erhalten. Beim standardmäßigen Volumenanteil-Slippage weichen Ausführungen meist vom übergebenen Kurs ab.
  • Um aus on_bar den Balkenschluss anzupeilen, übergeben Sie float(bar["close"]) (weiterhin Slippage/Provision unterworfen).
  • Um während der Intrabar-Simulation auszuführen, rufen Sie aus on_tick auf, wenn tick_in_bar == 3 — price ist dann der Schlusskurs dieses Symbols für die Zeile.

on_init — alles vorbereiten

Läuft direkt, nachdem die Engine das Konto vorbereitet, Marktdaten geladen und die Runtime aufgebaut hat — aber bevor Balken verarbeitet werden.

Nutzen Sie sie, um:

  • Variablen zu initialisieren, die Ihre Strategie zwischen Balken mitführt (Zähler, Zustandsautomaten, Parameterwerte).
  • Indikatoren oder Warmup-Puffer zu konfigurieren.
  • Eingabeparameter zu lesen, damit sie den Rest des Laufs steuern.
def on_init(symbols=None): global lookback, position_size lookback = 20 position_size = 100

In on_init haben Sie keinen Zugriff auf einen aktuellen Balken — zu diesem Zeitpunkt hat die Simulation noch nicht begonnen.

Parameter symbols (nur Screener-Läufe): Nutzt der Backtest eine Screener-Symbolquelle, wird on_init bei jedem Rebalancing erneut mit symbols=<Liste der Ticker> für das neue Universum ausgelöst. So kann Ihre Strategie auf einen neuen Tickersatz reagieren, ohne die Simulation neu zu starten.

  • Zu Beginn des Laufs wird on_init zweimal kurz hintereinander ausgelöst — einmal mit symbols=None (der Standard-Setup-Aufruf) und einmal mit symbols=<anfängliche Ticker>.
  • Erneute Auslösungen setzen den Zustand auf Modulebene nicht zurück; Variablen, die Sie im ersten Aufruf gesetzt haben, sind weiterhin da.
  • Strategien, die def on_init(): (ohne Parameter) definieren, funktionieren genau wie bisher — die Engine ordnet Argumente nach Namen zu, sodass der fehlende Parameter einfach ignoriert wird.

on_bar — einmal pro Balken

Läuft einmal pro Ausführungsbalken, vor den vier Intrabar-Ticks dieses Balkens. Hier treffen die meisten Strategien ihre Entscheidungen.

def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None): if bar.bars_back < 1: return if bar.close[0] > bar.close[1]: account.open_trade(...)

Parameter:

  • bar_index — nullbasierter Index des aktuellen Ausführungsbalkens.
  • bar — die Ansicht des aktuellen Balkens (OhlcvBarView). Verhält sich wie ein schreibgeschütztes Mapping (bar["open"], bar["high"], bar["low"], bar["close"], bar["volume"], bar["t"]) und bietet außerdem Historie über Offsets: bar.close[0] ist der Schlusskurs des aktuellen Balkens, bar.close[1] der des vorherigen Balkens, und so weiter. len(bar.close) und bar.bars_back sagen, wie viel Historie verfügbar ist. Es ist kein einfaches dict (isinstance(bar, dict) ist False).
  • fundamentals — Fundamentaldaten-Snapshot für diesen Balken oder None, wenn nicht konfiguriert.
  • calendar — BacktestCalendar-Handle, wenn Include calendar data aktiviert ist, sonst None (bei Forward-Läufen immer None). Die vollständige API siehe Kalenderdaten. Da Argumente nach Namen zugeordnet werden, lässt das Weglassen dieses Parameters Ihren Callback unverändert.
  • symbol — Ticker-String in Großbuchstaben. Nützlich in Multi-Symbol-Strategien; Sie können ihn weglassen, wenn Sie nur ein Symbol laden.

Gängige Muster:

  • Ein- und Ausstiege zum Balkenschluss entscheiden: Übergeben Sie bar.close[0] (oder float(bar["close"])) an account.open_trade / account.close_trade.
  • Einfache Indikatoren berechnen, indem Sie Offsets wie bar.close[0], bar.close[1], … lesen.
  • Frühe Balken überspringen, die nicht genug Historie haben (if bar.bars_back < N: return).

Tipp: on_bar läuft immer vor allen Tick-Callbacks desselben Balkens.


on_tick — Intrabar- und Live-Kursupdates

on_tick hat im Backtest und im Forward-Lauf dieselbe Signatur, doch wann es ausgelöst wird und was price bedeutet, hängt vom Laufmodus ab.

Backtest (Test)

Läuft bis zu viermal pro Balken, nach on_bar, um die Bewegung innerhalb des Balkens zu simulieren. Die Engine geht das OHLC jedes Balkens in dieser Reihenfolge durch:

tick_in_barBedeutung
0Balken-Eröffnung
1Balken-Hoch
2Balken-Tief
3Balken-Schluss

Keine echten Tickdaten im Backtest. Historische Läufe laden keine Broker-Tick-Historie. Die vier Aufrufe pro Balken nutzen synthetische Kurse, die allein aus dem OHLC jedes Balkens abgeleitet sind. Sie können Intrabar-Ausführungen in der Simulation annähern, aber das on_tick-Verhalten im Backtest wird nicht den Live-Forward-Ticks entsprechen. Für Entscheidungen zum Balkenschluss reicht on_bar — on_tick mit tick_in_bar == 3 entspricht in der Simulation dem Handeln auf den Balkenschluss.

def on_tick(bar_index, tick_in_bar, price, bar, fundamentals=None, calendar=None, symbol=None): if tick_in_bar == 3: # Backtest simulation: closing tick fill account.close_trade(position_id, price)

Nutzen Sie das Backtest-on_tick, wenn das Timing innerhalb des Balkens in der Simulation zählt — etwa um am Schluss-Tick auszuführen, einen Intrabar-Stop zu simulieren oder die Berührung des Hochs oder Tiefs des Balkens auszuwerten.

Forward-Läufe (Chart-Forward, Forward-Bulk / QuantCloud)

Bei Forward-Läufen läuft on_tick jedes Mal, wenn die Plattform einen Kurs von Ihrem verbundenen Broker erhält, solange Ihr Algo angehängt ist. Es gibt keinen festen OHLC-Durchlauf mit vier Ticks — jeder Aufruf spiegelt eine Live-Notierung wider.

def on_tick(bar_index, tick_in_bar, price, bar, fundamentals=None, calendar=None, symbol=None): # Forward run: react to each broker price update if price <= stop_level: account.close_trade(position_id, price)
  • price — die jüngste Broker-Notierung für dieses Symbol.
  • bar — die Ansicht des aktuellen Balkens für die Historie (gleiche Form wie im Backtest).
  • tick_in_bar — kann aus Signaturkompatibilität noch vorhanden sein; verzweigen Sie bei Forward-Läufen nach price, nicht nach synthetischen OHLC-Phasen.

Nutzen Sie das Forward-on_tick für Live-Intrabar-Logik — Stops, Trailing-Ausstiege oder jede Reaktion auf Marks zwischen Balkenschlüssen.

Parameter (beide Modi)

  • bar_index — wie in on_bar.
  • tick_in_bar — im Backtest 0, 1, 2 oder 3 (synthetischer OHLC-Schritt). Verlassen Sie sich bei Forward-Läufen nicht darauf für Balkenphasen-Logik.
  • price — synthetischer OHLC-Schritt im Backtest; Live-Broker-Notierung bei Forward-Läufen.
  • bar — dieselbe Balkenansicht wie in on_bar.
  • fundamentals, calendar, symbol — gleiche Bedeutung wie in on_bar.

Wenn Sie im Backtest nur Entscheidungen zum Balkenschluss brauchen, können Sie on_tick ganz ignorieren und Ihre Logik in on_bar legen.


on_timer — optionaler periodischer Callback (nur Forward-Läufe)

IDE-Backtest: Der Dialog Run backtest setzt kein Timer-Intervall. Auch wenn Sie on_timer in Ihrer Strategiedatei definieren, wird es bei IDE-Backtests nicht aufgerufen. Legen Sie periodische oder zeitbasierte Logik bei Backtests in on_bar oder on_tick.

Forward-Läufe (Chart-Forward-Test, Forward-Bulk / QuantCloud) können in ihrem Lauf-Dialog timerIntervalMs setzen. Ist es konfiguriert, läuft on_timer in einem festen Zeitintervall zwischen Ticks, nur wenn zwei Bedingungen erfüllt sind:

  1. Sie haben timer_interval_ms / timerIntervalMs für den Lauf konfiguriert (eine positive ganze Zahl in Millisekunden).
  2. Ihre Datei definiert eine Funktion on_timer.
def on_timer(bar_index, tick_in_bar, price, bar, fundamentals=None, calendar=None, symbol=None): pass

Die Signatur hat dieselbe Form wie on_tick. Nutzen Sie on_timer für zeitbasierte Verhaltensweisen (zum Beispiel: ein langsames Signal jede Minute aktualisieren oder eine Prüfung unabhängig von der Balkenzahl einplanen). Ist timer_interval_ms nicht gesetzt, wird on_timer nie aufgerufen, auch wenn es definiert ist.


Kalenderdaten in Callbacks

Ist Include calendar data im Tab Symbol & data aktiviert, kann jeder Callback ein BacktestCalendar-Handle erhalten, indem Sie einen Parameter calendar hinzufügen:

def on_bar(bar_index, bar, calendar=None, symbol=None): if calendar is None: # always guard — not every run enables calendar data return days = calendar.days_to_earnings(bar["t"], symbol) if days is not None and days <= 2: return # avoid trading into an earnings print divs = calendar.dividends(bar["t"], symbol) if divs and (divs[-1].amount or 0) > 0.5: # amount can be None ...

Dasselbe Handle steht in on_tick und on_timer zur Verfügung — aber Kalenderdaten gibt es nur im Backtest, bei Forward-Läufen ist calendar also immer None. Alle Abfragen sind Point-in-Time — dividends(bar["t"], symbol) liefert nur Dividenden, die zu diesem Balken öffentlich waren, nie zukünftige.

Wichtige Methoden:

MethodeLiefert
dividends(bar_time, symbol=None)Zu diesem Balken öffentliche Dividenden (älteste zuerst)
splits(bar_time, symbol=None)Bis zu diesem Balken angekündigte Splits (älteste zuerst)
next_earnings(bar_time, symbol=None){date, basis, estimated, …} oder None
days_to_earnings(bar_time, symbol=None)int oder None
has(symbol=None)Ob dieses Symbol überhaupt Kalenderdaten hat

Listen sind älteste zuerst — [-1] ist das jüngste Ereignis. Das ist das Gegenteil der Fundamentaldaten, bei denen Index 0 die neueste Periode ist.

Das Runtime-Global qc_calendar enthält dasselbe Handle, falls Sie es lieber aus quantcraft.process.runtime statt aus dem Callback-Argument lesen.

Siehe Kalenderdaten für die Feldschemata der Ereignisse, Details zur Simulation von Kapitalmaßnahmen und Fehlerbehebung.


on_finish — abschließen

Läuft einmal, nach dem letzten Balken. Nutzen Sie es, um finale Ausgaben zu berechnen, Chart-Indikatoren aufzubauen oder eine Zusammenfassung auszugeben.

def on_finish(bars, symbol=None, bars_by_symbol=None): closes = [b["close"] for b in bars] bt.chart_indicators.add(...)

Parameter:

  • bars — chronologische Liste von OHLC-Dictionaries für das Taktsymbol, ältester zuerst — das ausgeführte Fenster, dieselben Zeilen, die der Test-Results-Chart zeichnet. Jeder Eintrag hat t, open, high, low, close, volume und optional fundamentals. Dies ist die kanonische Serie über die gesamte Historie für on_finish.
  • symbol — Ticker des Taktsymbols in Großbuchstaben.
  • Bei einem Screener-Lauf gibt es kein Taktsymbol: bars ist [] und symbol ist "", nutzen Sie also bars_by_symbol.
  • bars_by_symbol — bei Multi-Symbol-Läufen ein Dict, das jeden Ticker auf seine chronologische Balkenliste abbildet (an die Ausführungsuhr angeglichen). Bei Einzelsymbol-Läufen können Sie es ignorieren.

Gängige Verwendungen:

  • Indikatorserien an chart_indicators.add(...) übergeben, damit sie in den Ergebnis-Charts erscheinen. Bevorzugen Sie Werte, die Sie pro Symbol angesammelt haben, während der Lauf die Balken durchging; berechnen Sie aus bars nur Indikatoren neu, die Sie nicht pro Balken mitgeführt haben — siehe Indikatorserien.
  • Eine finale Zusammenfassung im Ausgabebereich ausgeben oder protokollieren.
  • Portfolio-Kennzahlen für die Ergebnis-Nutzlast aktualisieren.

Jedes return in on_finish ist stumm. Der Lauf gelingt trotzdem und Test Results wird weiterhin gerendert — ein frühes Return bedeutet nur, dass Ihre Serien oder Kennzahlen nie angehängt wurden, ohne irgendeinen Fehler. Geben Sie beim Debuggen an jeder Absicherung auf sys.stderr aus; die Meldung erscheint im Ausgabebereich.


Grundlagen für mehrere Symbole

QuantCraft-Strategien können auf einem Symbol oder auf mehreren gleichzeitig laufen. Der Lebenszyklus bleibt derselbe — nur die Callback-Signaturen und die Daten, die sie erhalten, ändern sich leicht.

Mehrere Symbole konfigurieren

Wählen Sie im Tab Symbol & data von Run backtest einen oder mehrere Ticker in Großbuchstaben. Alle aufgeführten Symbole werden gemeinsam geladen und simuliert.

Das Taktsymbol

Wenn Sie mehrere Symbole ausführen, bestimmt eines davon den Takt — seine Balkenzeitstempel entscheiden, wann Callbacks laufen. Der Dialog Run backtest hat kein Bedienelement für ein Primärsymbol. Auflösungsreihenfolge:

  1. Ein SYMBOL = "AAPL" auf oberster Ebene in Ihrer Strategiedatei, wenn dieser Ticker in der geladenen Liste ist.
  2. Andernfalls das erste geladene Symbol.

Bei einer Screener-Symbolquelle gibt es überhaupt kein Taktsymbol — die Symbolmenge ändert sich im Verlauf des Laufs. rt.get_bar liest immer die Balken des Taktsymbols (und gibt bei einem Screener-Lauf None zurück); nutzen Sie für die Historie eines anderen Tickers daher dessen bar.close[i]-Offsets.

Das Taktsymbol ist auch dasjenige, das on_finish(bars, symbol=...) für seine Argumente bars und symbol verwendet.

Callbacks pro Symbol

Für jeden Ausführungsbalken geht die Engine die Symbole in Listenreihenfolge durch:

  1. on_bar läuft einmal pro geladenem Ticker zur Zeit dieses Balkens (vor allen Ticks dieses Balkens).
  2. Nur Backtest: für jedes tick_in_bar (0 = Eröffnung, 1 = Hoch, 2 = Tief, 3 = Schluss) läuft on_tick einmal pro Ticker auf synthetischem OHLC (keine echten Tickdaten).
  3. Nur Backtest: nach den vier Tick-Runden bewertet ein abschließendes tick(close_map) des Kontos das Eigenkapital zum Schluss — kein fünftes on_tick.
  4. Forward-Läufe: on_tick läuft pro Broker-Kursupdate pro Symbol, sobald Notierungen von Ihrem verbundenen Broker eintreffen (nicht auf vier Aufrufe pro Balken beschränkt). An Intraday-Grenzen wird oft on_tick dann on_bar ausgelöst — nehmen Sie nicht die Backtest-Reihenfolge an.
  5. on_timer (nur bei Forward-Läufen mit konfiguriertem timerIntervalMs — nicht im IDE-Backtest) folgt zwischen den Ticks demselben Muster pro Ticker.

Das heißt, ein Multi-Symbol-on_bar wird zum Beispiel dreimal pro Balken aufgerufen, wenn drei Symbole geladen sind. Nutzen Sie den Parameter symbol, um zu wissen, für welchen Ticker der Aufruf gilt:

def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None): if symbol == "AAPL": ... elif symbol == "MSFT": ...

Die bar-Ansicht gehört immer zu dem Symbol, für das der Callback aufgerufen wurde. Dasselbe gilt für price in on_tick.

As-of-Ausrichtung. Pro Ausführungsbalkenzeit erhält jeder Ticker seinen jüngsten Balken zu oder vor dieser Zeit. Ein Ticker ohne Balken zu genau dieser Zeit (ein Handelsstopp, eine fehlende Minute, ein anderer Handelskalender) erhält seinen vorherigen Balken erneut. Wenn Sie Balken oder Signale pro Ticker zählen, überspringen Sie Wiederholungen, indem Sie sich das zuletzt gesehene bar["t"] für dieses Symbol merken:

_last_t = {} def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None): if _last_t.get(symbol) == bar["t"]: return # same bar as last step for this ticker _last_t[symbol] = bar["t"] ...

on_finish bei mehreren Symbolen

on_finish läuft weiterhin einmal am Ende. Um mit der Historie aller Symbole zu arbeiten, nutzen Sie bars_by_symbol:

def on_finish(bars, symbol=None, bars_by_symbol=None): if bars_by_symbol: for ticker, ticker_bars in bars_by_symbol.items(): ...

Alles zusammen

Eine typische Einzelsymbol-Strategie:

  1. Setzt Eingabeparameter oder anderen Zustand in on_init.
  2. Liest die Kurshistorie (OHLCV) über bar.close[0], bar.close[1], … in on_bar, um Handelsentscheidungen zu treffen, und ruft account.open_trade / account.close_trade auf.
  3. Nutzt optional on_tick — im Backtest für synthetische Intrabar-Ausführungen (z. B. tick_in_bar == 3 für den Schluss-Tick); bei Forward-Läufen, um zwischen Balkenschlüssen auf Live-Broker-Kurse zu reagieren.
  4. Nutzt optional on_timer bei Forward-Läufen, wenn timerIntervalMs konfiguriert ist (im IDE-Run-backtest nicht verfügbar).
  5. Baut Chart-Indikatoren auf und finalisiert Ergebnisse in on_finish mithilfe von bars.

Eine Multi-Symbol-Strategie nutzt dieselben Callbacks, verzweigt darin lediglich nach dem Argument symbol und liest Daten pro Ticker über den erhaltenen bar — und in on_finish über bars_by_symbol.

Mehr Details? Siehe Kontomodell, Fundamentaldaten, Fama-French-Faktoren, OHLCV- und Balkendaten, Indikatorserien oder den integrierten Tab Documentation in der rechten Seitenleiste (Arbeitsbereich-Layout).

Lebenszyklus einer Strategie — Dokumentation (1.0 (latest)) | QuantCraft