4. Wie eine Strategie Daten deklariert und verwendet
4.1. 1. 策略层在整体中的位置
Die Strategieschicht ist für zwei Dinge verantwortlich: Angabe, „welche Daten benötigt werden“ (und die Fensterlänge, ob die letzte Periode verwendet werden soll) und in real() „Verwendung der Daten zur Berechnung von Signalen“. Daten werden von der Strategie nicht aktiv abgerufen; Stattdessen bereitet die Laufzeit es bei jedem Schritt gemäß den Deklarationen vor und fügt es ein, und die Strategie ruft es nur per ID über „get_data(dtype_id)“ ab. Auf diese Weise verwenden Backtesting und Live-Handel genau die gleiche Datenansicht und das gleiche Aufrufmuster.
4.2. 2. 策略如何声明需要的数据
Deklarieren Sie beim Initialisieren der Strategieklasse („init“) Datenanforderungen über die folgenden Attribute:
data_types: Ein oder mehrere DataType-Objekte (oder eine Liste/ein Diktat). Jeder DataType entspricht einer Art „referenzierbarer Information“ und wird einer eindeutigen dtype_id zugeordnet (z. B. „close_E_d“).
window_length: Die Länge des historischen Datenfensters (z. B. 20 bedeutet die letzten 20 Zyklen). Kann ein Skalar sein (gilt für alle deklarierten Datentypen) oder separat durch dtype angegeben werden.
use_latest_data_cycle: Legt fest, ob nur die Daten aus dem „letzten Einzelzyklus“ verwendet werden sollen (z. B. nur der neueste Querschnitt für die Aktienauswahl). Kann separat per dtype eingestellt werden.
Nach der Deklaration weiß die Engine, welche dtype_id die Strategie benötigt und welche Fensterlänge, sodass sie die entsprechenden Datenfenster vor der Ausführung vorbereiten und bei jedem Schritt aktualisieren/einfügen kann.
4.3. 3. 运行时数据如何到达策略
Vorbereitungsphase: Basierend auf dem Backtest-Zeitraum (oder der aktuellen Zeit im Live-Handel) und den data_types und window_length der Strategie ruft die Engine die Daten für den entsprechenden Zeitraum aus dem DataSource ab und schneidet das „Datenfenster“ für jeden Zeitschritt vorab (oder schneidet es bei Bedarf auf).
Bevor jeder Schritt ausgeführt wird: Für jede Strategie in der Gruppe, die im aktuellen Schritt ausgeführt werden soll, ruft die Engine update_running_data_window auf, um das Datenfenster für den aktuellen Schritt in den internen Status dieser Strategie zu schreiben (indiziert durch dtype_id).
Inreal(): Die Strategie ruft die eingefügten Fensterdaten (ein Numpy-Array) nach ID über get_data(dtype_id) ab, um Signale zu berechnen. Es sind keine Parameter erforderlich und es besteht kein Grund, sich darum zu kümmern, aus welcher Tabelle die Daten stammen.
Daher lautet der Datenfluss „Deklaration → Engine fügt Schritt für Schritt ein → get_data verweist darauf“. Der Strategiecode enthält überhaupt keine Logik zum „Tabellenlesen“ oder „Ziehen/Abrufen“.
4.4. 4. 数据窗口的含义
Zeitdimension: window_length bedeutet „wie viele Zeiträume zurückblicken“. Beispielsweise bedeutet window_length=20 bei täglicher Häufigkeit Daten für die letzten 20 Handelstage; Die Array-Form ist typischerweise (n_periods,) oder (n_assets, n_periods), wobei die letzte Dimension die Zeit und die letzte Spalte die jüngste Periode ist.
Formen in Multi-Asset-Fällen: Verschiedene Basisklassen der Strategie organisieren Daten leicht unterschiedlich:
RuleIterator: iteriert normalerweise nach Asset; Jede realise() sieht eine einzelne Asset-Zeitreihe oder einen Querschnitt.
FactorSorter: ein Multi-Asset-Querschnitt (z. B. ein Faktorwert pro Aktie), der für das Ranking und die Aktienauswahl verwendet wird.
GeneralStg: Fenster mit mehreren Assets und mehreren D-Typen, die ein Signalarray mit der gleichen Länge wie die Anzahl der Assets zurückgeben.
Die genauen Formen unterliegen der API- und Strategie-Basisklassendokumentation; In dieser Serie wird betont, dass „Fenster von der Engine gemäß Deklarationen vorbereitet werden und die Strategie sie per ID über get_data abruft“.
4.5. 5. 过程数据(proc.*)
In addition to the static historical data described above (“declaration → engine injection”), qteasy supports process data: state that depends on the backtest/live execution path (such as current positions, cash, historical trade records, etc.). Prozessdaten müssen nicht in data_types deklariert werden; Es wird zur Laufzeit durch Backtester (Backtesting) oder Trader (Live-Handel) verwaltet und injiziert.
Zugriffsmuster: in
realize()nach Bedarf über Formulare wieself.get_data('proc.own_cash'),self.get_data('proc.trade_records', lag=0)usw. abrufen; unterstützt die Parameter „Lag“ (Schritte oder Zeit wie „1d“) und „Fenster“ (wie „5d“).Einschränkung: Ein einzelner Aufruf erlaubt nur ein „proc.*“-Feld und es darf nicht mit statischen Daten im selben Aufruf gemischt werden; Jede Strategie, die Prozessdaten verwendet, folgt automatisch dem dynamischen Backtesting-Pfad (Signale Schritt für Schritt generieren, Trades Schritt für Schritt ausführen).
Weitere Informationen finden Sie unter Prozessdaten (proc.*) und dynamisches Backtesting.
4.6. 6. 参考数据(若有)
Neben den von der Strategie deklarierten Datentypen unterstützt qteasy „Referenzdaten“ (z. B. den Schlusskurs eines Index, der zur Berechnung von Marktrenditen usw. verwendet wird). Der Unterschied zwischen Referenzdaten und Primärdaten besteht darin, dass sie normalerweise keine Eins-zu-eins-Entsprechung mit dem Asset-Pool haben und auch in einer Strategie über die entsprechende dtype_id oder eine dedizierte Schnittstelle abgerufen werden können. Informationen zu spezifischen Konfigurations- und Referenzierungsmethoden finden Sie in der Dokumentation und API für die aktuelle Version.
4.7. 7. 小结
„Declare → engine injects → get_data references“ stellt sicher, dass:
Backtesting und Live-Handel nutzen die gleiche Datenansicht und das gleiche Zugriffsmuster;
Die Strategie kann nicht auf nicht deklarierte oder zukünftige Daten zugreifen, wodurch eine Voreingenommenheit auf Mechanismusebene verhindert wird.
Eine einheitliche Schnittstelle, die einfach zu warten und zu erweitern ist.
„Deklaration → Engine-Injektion → get_data-Referenz“ gilt auch für Prozessdaten, mit der Ausnahme, dass Prozessdaten nicht deklariert werden müssen, schrittweise von der Laufzeitschicht injiziert werden und erst bei Verwendung den dynamischen Backtesting-Pfad auslösen. Weitere Informationen zur Verwendung finden Sie im „Benutzerhandbuch“ und in der „API-Referenz“.