Erstellen Sie Handelsstrategien und werten Sie Backtesting-Ergebnisse aus
Alle Handelsstrategien in qteasy werden durch das qteast.Operator (Händler) -Objekt implementiert, das ein Strategiecontainer ist. Ein Händler kann gleichzeitig mehrere verschiedene Handelsstrategien verwalten, auch wenn diese Handelsstrategien unterschiedliche Ausführungszeiten und Ausführungsfrequenzen haben oder unterschiedliche Zwecke haben, z. B. eine Strategie für die Aktienauswahl, eine andere Strategie für die Marktzeit und eine weitere Strategie für das Risikomanagement. Benutzer können sehr flexibel Handelsstrategien im Operator-Objekt hinzufügen oder ändern.
Nachdem die Strategie an den Operator übergeben wurde, wird der Operator-Objekt die entsprechende Handelsstrategie zum richtigen Zeitpunkt starten, das Handelssignal generieren und alle Handelssignale mischen (blend) und in Handelssignale umwandeln, sobald die Asset-Klasse des Handels, die Größe des Asset-Pools und die Ausführungszeit und -frequenz jeder Strategie festgelegt sind.
Weitere Informationen zum Operator-Objekt finden Sie in der qteasy-Dokumentation
qteasy bietet zwei Möglichkeiten zum Erstellen von Handelsstrategien:
Verwendung integrierter Handelsstrategiekombinationen
„qteasy“ bietet eine Vielzahl integrierter Handelsstrategien, die Benutzer ohne manuelle Erstellung verwenden können. Durch Verweis auf den Namen der integrierten Strategie (für eine detaillierte Dokumentation aller integrierten Strategien) können Benutzer schnell Strategien erstellen und auch mehrere einfache Strategien zu komplexeren zusammengesetzten Strategien kombinieren.
Durch den Strategiekurs zur Erstellung von Strategien
Wenn die Strategie des Benutzers sehr komplex ist, kann eine Strategie über die Klasse „qteasy.Strategy“ angepasst werden.
Das Erstellen von Handelsstrategien, das Backtesting der Handelsergebnisse von Handelsstrategien anhand historischer Daten und die Auswertung der Handelsergebnisse gehören zu den Kernfunktionen von qteasy. qteasy fasst eine Reihe von Handelsstrategien über ein Händlerobjekt (Operator) zusammen und simuliert den Betrieb von Handelsstrategien innerhalb eines festgelegten historischen Zeitraums mithilfe der Funktion qt.run(), generiert Handelssignale, simuliert den Handel anhand historischer Preise, generiert Handelsergebnisse, berechnet Bewertungsindikatoren und gibt sie in visueller Form als Diagramme aus.
Hier ist ein Beispiel für eine gängige Fonds-Timing-Investitionsstrategie mit folgendem Inhalt:
Erstellen Sie eine einfache DMA-Timing-Investitionsstrategie, erstellen Sie ein Händlerobjekt mit dieser Strategie und zeigen Sie, wie Sie Strategien ändern und hinzufügen
Legen Sie mit „qt.configure()“ die relevanten Umgebungsvariablen fest und verwenden Sie die historischen Daten des CSI 300-Index der letzten 10 Jahre, um die Strategieleistung zu testen
Optimieren Sie die Strategieparameter anhand der historischen Daten des CSI 300-Index der letzten 10 Jahre und demonstrieren Sie schließlich die Ergebnisse nach der Optimierung
Zuerst importieren wir das Modul qteasy. Um Diagramme online zu drucken, verwenden Sie „matplotlib inline“, um den Diagrammdruckmodus auf Online-Druck einzustellen.
Erstellen Sie Strategie- und Operator-Objekte
Jede Handelsstrategie in qteasy ist als Handelsstrategieobjekt (Strategieobjekt) definiert. Jedes Handelsobjekt enthält eine Reihe von Handelsregeln, die drei Aspekte umfassen:
Strategieausführungsregeln umfassen die Häufigkeit der Strategieoperation, die Art der verwendeten historischen Daten und die Länge des historischen Datenfensters, die definieren, wie die Strategie funktioniert und wie historische Daten verwendet werden
Signalgenerierungsregeln Die Regeln für die Generierung von Handelssignalen, d. h. wie welche Art von Handelssignalen auf der Grundlage relevanter historischer Daten generiert werden, was den Kern der Handelsstrategie darstellt
Handelssignaltypen Die verschiedenen Arten von Handelssignalen bestimmen, wie das Simulationshandelsmodul Handelssignale verarbeitet
In qteasy werden Handelsstrategien vom Händlerobjekt (Operator) ausgeführt. Gleichzeitig kann nur ein Operator-Objekt ausgeführt werden, aber derselbe Händler kann eine oder mehrere Handelsstrategien gleichzeitig ausführen. Diese Handelsstrategien können mit demselben Portfolio gehandelt werden, und Benutzer können spezifische „Mischmethoden“ definieren, um mehrere einfache Handelsstrategien zu einer komplexen Handelsstrategie zu kombinieren.
Erstellen Sie ein Strategieobjekt
Das Erstellen eines Strategieobjekts ist am einfachsten mit dem Modul qt.built_in und kann auch beim Erstellen des Operator-Objekts erstellt werden.
import qteasy as qt
# 通过qt内置策略模块创建一个DMA则时策略
stg = qt.built_in.DMA()
# 通过stg.info()可以查看策略的主要信息:
stg.info()
Strategy_type: RuleIterator
Strategy name: DMA
Description: Quick DMA strategy, determine long/short position according to differences of moving average prices with simple timing strategy
Strategy Parameter: (12, 26, 9)
Strategy Properties Property Value
-------------------------------------------------
Param. count 3
Param. types ['int', 'int', 'int']
Param. range [(10, 250), (10, 250), (5, 250)]
Run parameters d @ close
Data types ['close']
Data parameters 270 d
Die grundlegenden Informationen dieser Handelsstrategie können wir der Ausgabe entnehmen. Wichtige Informationen sind neben dem Namen und der Beschreibung:
Strategieparameter. Der Strategieparameter ist der externe Parameter, der während des Betriebs der Strategie benötigt wird. Abhängig von den unterschiedlichen Strategieregeln sind auch die von der Strategie verwendeten Parameter unterschiedlich. Diese Parameter wirken sich auf den Betrieb der Strategie aus, und verschiedene Parameter wirken sich auf die Ausgabe der Strategie aus. Beispielsweise sind in einer Dual-Moving-Average-Strategie der Berechnungszeitraum des Long-Moving-Average und der Berechnungszeitraum des Short-Moving-Average zwei Strategieparameter.
Parametertypen/Bereich: Verschiedene Strategieparameter können das Endergebnis einer Strategie stark beeinflussen. Nachdem der Wertebereich und die Art der Parameter festgelegt wurden, kann qteasy mithilfe verschiedener Methoden nach den besten Parametern im Parameterraum suchen, um die Leistung der Strategie zu optimieren.
Strategiedatenhäufigkeit / Stichprobenhäufigkeit. Die Häufigkeit der Strategieoperation und die Häufigkeit der erforderlichen Daten, z. B. einmal pro Woche, einmal im Monat oder einmal pro Minute usw. Im Allgemeinen hängt die Datenhäufigkeit mit der Ausführungshäufigkeit zusammen.
Datentypen: Die historischen Datentypen, die zum Ausführen der Strategie erforderlich sind. Für die DMA-Strategie wird nur der Schlusskurs benötigt.
Wenn Sie alle integrierten Strategien sehen möchten, können Sie die Funktion qt.built_ins() verwenden. Wenn Sie die Funktionsparameter nicht angeben, wird eine Liste aller integrierten Strategien angezeigt. Wenn Sie Parameter angeben, werden detaillierte Informationen zur angegebenen integrierten Strategie angezeigt. Zum Beispiel:
qt.built_ins('dma')
Ergebnis:
DMA择时策略
策略参数:
s, int, 短均线周期
l, int, 长均线周期
d, int, DMA周期
信号类型:
PS型:百分比买卖交易信号
信号规则:
在下面情况下产生买入信号:
1, DMA在AMA上方时,多头区间,即DMA线自下而上穿越AMA线后,输出为1
2, DMA在AMA下方时,空头区间,即DMA线自上而下穿越AMA线后,输出为0
3, DMA与股价发生背离时的交叉信号,可信度较高
策略属性缺省值:
默认参数:(12, 26, 9)
数据类型:close 收盘价,单数据输入
采样频率:天
窗口长度:270
参数范围:[(10, 250), (10, 250), (8, 250)]
策略不支持参考数据,不支持交易数据
Zu den weiteren integrierten Strategiefunktionen gehören:
qt.built_ins(stg_id=None)
Wenn stg_id=None, wird eine Liste aller integrierten Strategien angezeigt. Andernfalls werden detaillierte Informationen zur angegebenen integrierten Strategie angezeigt.
qt.built_in_list(stg_id=None)
Wenn stg_id=None, wird eine Liste aller integrierten Strategien zurückgegeben, andernfalls werden detaillierte Informationen zur angegebenen integrierten Strategie zurückgegeben.
qt.built_in_strategies(stg_id=None)
Wenn stg_id=None, wird eine Liste aller integrierten Strategien zurückgegeben, andernfalls werden detaillierte Informationen zur angegebenen integrierten Strategie zurückgegeben.
qt.get_built_in_strategy(stg_id)
Geben Sie gemäß der angegebenen integrierten Strategie-ID das integrierte Strategieobjekt zurück.
Erstellen Sie ein Operator-Objekt
Das Erstellen eines „Operator“-Objekts kann mit „qt.Operator()“ erfolgen. Nach der Erstellung eines Operator-Objekts werden alle Handelsstrategien vom Händlerobjekt ausgeführt. Beim Erstellen des Händlerobjekts können Sie festlegen, wie mit Handelssignalen umgegangen wird und wie der Handel ausgeführt wird:
qt.Operator(strategies=None, signal_type=None, op_type=None)
„Strategien“: Die Handelsstrategien im Händlerobjekt können eine oder mehrere Handelsstrategien oder eine Liste einer Handelsstrategie sein. Wenn keine Handelsstrategie angegeben ist, wird ein leeres Händlerobjekt erstellt und die Handelsstrategie kann später hinzugefügt oder gelöscht werden. Sobald eine Handelsstrategie hinzugefügt wird, weist das Händlerobjekt jeder Handelsstrategie eine eindeutige ID zu, die zur Referenzierung dieser Handelsstrategie verwendet werden kann. Gleichzeitig weist das Händlerobjekt jeder Handelsstrategie entsprechend der Betriebshäufigkeit und dem Timing der Strategie automatisch einen Betriebszeitpunkt zu. Erst wenn der Betriebszeitpunkt erreicht ist, führt das Händlerobjekt diese Handelsstrategie aus und generiert Handelssignale.
„signal_type“: Der Typ des Handelssignals kann „pt“, „ps“ oder „vs“ sein. Der Standardwert ist „pt“, was Signale für die Zielhaltequote, prozentuale Handelssignale bzw. Mengenhandelssignale darstellt. Verschiedene Arten von Handelssignalen bestimmen, wie das Händlerobjekt Handelssignale verarbeitet und wie das Händlerobjekt die Handelssignale mehrerer Handelsstrategien zu einem einzigen Handelssignal mischt.
„op_type“: Der Betriebsmodus des Händlerobjekts kann „Batch“ oder „Echtzeit“ sein. Der Standardwert ist „Batch“, was den Batch-Betriebsmodus bzw. den Echtzeit-Betriebsmodus darstellt. Im Batch-Betriebsmodus generiert das Händlerobjekt vorab Handelssignale im Backtesting- oder Optimierungsmodus und führt dann den simulierten Handel in Batches durch, was schneller ist. Im Echtzeitbetriebsmodus generiert das Händlerobjekt Handelssignale und simuliert sofort den Handel. Nach der Generierung simulierter Handelsergebnisse wird das nächste Handelssignal generiert, das für den realen Handelsbetriebsmodus oder den speziellen Backtesting-Modus geeignet ist.
Für qteasy sind die Handelssignale von Handelsstrategien und die Handelsaufträge von Aktien/Fonds zwei unterschiedliche Konzepte.
Alle Handelsstrategien basieren auf historischen Daten, um Handelssignale zu generieren, während das Händlerobjekt Handelsaufträge auf der Grundlage von Handelssignalen generiert, das Handelsverhalten des Händlers simuliert und letztendlich Handelsergebnisse generiert.
Drei Arten von Strategiesignalen
In qteasy sind Handelssignale Gleitkommazahlen, und dasselbe Handelssignal kann unterschiedliche Bedeutungen haben, die vom Händlerobjekt als unterschiedliche Handelsaufträge interpretiert werden. Die Bedeutung des Handelssignals wird durch den Signaltyp des Händlerobjekts bestimmt, der „pt“, „ps“ oder „vs“ sein kann und jeweils Zielhalteverhältnissignale, prozentuale Handelssignale bzw. Mengenhandelssignale darstellt.
Es gibt drei Arten von Handelssignalen:
PT: Dieses Handelssignal stellt die Zielbeteiligungsquote dar, was bedeutet, dass der Wert der gehaltenen Aktien den Anteil des Gesamtvermögens ausmacht. Wenn das aktuelle Gesamtvermögen beispielsweise 1 Million Yuan beträgt, bedeutet 0,2, dass die Haltemenge einer bestimmten Aktie oder eines bestimmten Fonds so kontrolliert wird, dass ihr Marktwert 20 % von 1 Million Yuan erreicht, was 200.000 Yuan entspricht. In diesem Fall hängt die Anzahl der gekauften oder verkauften Aktien von der aktuellen Anzahl der gehaltenen Aktien ab. Wenn die aktuelle Anzahl der gehaltenen Aktien 0 beträgt, dann kaufen Sie Aktien im Wert von 200.000 Yuan. Wenn der aktuelle Wert der gehaltenen Aktien 300.000 Yuan beträgt, dann verkaufen Sie sie im Wert von 100.000 Yuan.
PS: Dieses Handelssignal stellt direkt das Kauf-/Verkaufsverhältnis dar. In diesem Fall steht die Anzahl der gekauften oder verkauften Aktien nicht im Zusammenhang mit der aktuellen Anzahl der gehaltenen Aktien, sondern nur im Zusammenhang mit dem Gesamtvermögen. Wenn das Gesamtvermögen 1 Million Yuan beträgt, bedeutet 0,2 den Kauf von Aktien im Wert von 200.000 Yuan.
VS: In diesem Fall repräsentiert das Handelssignal direkt die Kauf-/Verkaufsmenge. In diesem Fall steht die Anzahl der gekauften oder verkauften Aktien in keinem Zusammenhang mit der Bilanzsumme oder der Anzahl der gehaltenen Aktien. 2000 bedeutet den Kauf von 2000 Aktien.
Wenn sich die generierten Handelsaufträge außerdem je nach Art des vom Händler geführten Kontos unterscheiden (z. B. ein Aktienkonto oder ein Terminkonto), unterscheiden sich auch die generierten Handelsaufträge. Die spezifische Erklärung ist in der folgenden Tabelle aufgeführt:
| 账户类型 | 信号类型 | 交易信号 | 信号含义 | 信号举例 | 交易订单举例 |
|---|---|---|---|---|---|
| 股票账户 | PT | sig > 0 | 持有该资产,并使持有资产的市值为总资产的sig倍 | 0.5 | 根据当前持有的资产比例确定交易订单,如果已经满仓持有,则卖掉50%仓位,如果持仓为0,则买入至50%仓位 |
| sig = 0 | 清空全部持有的资产,持有资产为0 | 0 | 根据当前持有的资产比例确定交易订单,如果持仓则卖掉全部持仓,如果没有持仓则不交易 | ||
| sig < 0 | 无意义 | N/A | N/A | ||
| PS | sig > 0 | 买入该资产,买入的金额占总资产的比例为sig | 0.5 | 总资产为100,000,则此时花费50,000元金额买入资产(含手续费) | |
| sig = 0 | 不进行任何操作 | 0 | 不进行任何操作 | sig < 0 | 卖出该资产,卖出的部分占当前持有数量的比例为sig | -0.5 | 假设当前持有1000股,则此时应卖出500股 |
| VS | sig > 0 | 买入该资产,买入的数量为sig | 500 | 买入500股 | |
| sig = 0 | 不进行任何操作 | 0 | 不进行任何操作 | sig < 0 | 卖出该资产,卖出的数量为abs(sig) | -500 | 卖出500股 |
| 期货账户 (未实现) | PT | sig > 0 | 平掉所有空仓,开多仓,并使持有合约价值为总资产的sig倍 | 1.5 | 假设总资产为100,000,开多仓持有总价150,000的合约 *当保证金比例<1时,持仓比例可以大于100% |
| sig = 0 | 平掉全部持有的仓位,持有头寸为0 | 0 | 平掉所有持有的多仓和空仓 | ||
| sig < 0 | 平掉所有多仓,开空仓,并使持有合约价值为总资产的sig倍 | -1.5 | 总资产为100,000,则开空仓持有总价150,000的合约 * 如果保证金比例<1时,持空仓比例可以大于100% |
||
| PS | sig > 0 | 如果持有空仓:平部分空仓,平空仓的数量占总持有的比例为sig | 0.5 | 如果总持仓为1,000手,则此时平仓500手 * 此时sig必须小于等于1 |
|
| 如果持有多仓:开多仓,开仓的合约价值占总资产的比例为sig | 1.5 | 如果总资产为100,000,则开多仓持有总价150,000元的合约 * 如果保证金比例<1时,sig可以大于1 |
|||
| sig = 0 | 不进行任何操作 | 0 | 不进行任何操作 | ||
| sig < 0 | 如果持有多仓:平部分多仓,平仓的数量占总持有的比例为sig | 0.5 | 如果总持仓为1,000手,则此时平仓500手 * 此时sig必须小于等于1 |
||
| 如果持有空仓:开空仓,开仓的合约价值占总资产的比例为sig | 1.5 | 如果总资产为100,000,则开空仓持有总价150,000元的合约 * 如果保证金比例<1时,sig可以大于1 |
|||
| VS | sig > 0 | 平空仓或开多仓,开平仓的数量为sig。如果持有空头数量超过sig则忽略剩余部分 | 1500 | 如果持有1500手以上空头仓位,则平仓1500手,如果当前没有持仓,则开多仓持有1500手合约 | |
| sig = 0 | 不进行任何操作 | 0 | 不进行任何操作 | sig < 0 | 平多仓或开空仓,开平仓的数量为sig。如果持有多头数量超过sig则忽略剩余部分 | -500 | 如果持有1500手以上多头仓位,则平仓1500手,如果当前没有持仓,则开空仓持有1500手合约 |
Mischen von Handelssignalen
Obwohl dasselbe Operator-Objekt gleichzeitig nur einen Signaltyp erzeugen kann, kann es, da das Operator-Objekt eine unendliche Anzahl verschiedener Handelsstrategien aufnehmen kann, auch eine unendliche Anzahl von Sätzen derselben Art von Handelsstrategien erzeugen. Um beim Trading-Backtesting Rechenaufwand zu sparen, zu vermeiden, dass widersprüchliche oder doppelte Handelssignale Rechenressourcen beanspruchen, und um die Flexibilität von Handelssignalen zu erhöhen, sollten alle Handelssignale zu einem Satz gemischt werden, bevor sie zum Testen an das Backtesting-Programm gesendet werden.
Allerdings können in einem Operator-Objekt die von verschiedenen Strategien generierten Handelssignale zu unterschiedlichen Handelspreisen laufen. Beispielsweise generieren einige Strategien Handelssignale für den Eröffnungskurs, während andere Handelsstrategien für den Schlusskurs generieren. In diesem Fall sollten unterschiedliche Handelspreissignale nicht vermischt werden. Aber ansonsten sollten alle Signale gemischt sein, solange die Handelspreise gleich sind.
Unter dem Mischen von Handelssignalen versteht man verschiedene Operationen oder Funktionen von Handelssignalen, von einfachen logischen Operationen und Additions-/Subtraktionsoperationen bis hin zu komplexen benutzerdefinierten Funktionen. Solange sie auf eine ndarray-Funktion angewendet werden können, können sie theoretisch zum Mischen von Handelssignalen verwendet werden, solange das endgültige Ausgabehandelssignal aussagekräftig ist.
Die Signalmischung basiert auf einer Reihe vordefinierter Operationen und Funktionen, die als „atomare Funktionen“ oder „Operatoren“ bezeichnet werden. Benutzer verwenden diese „Operatoren“, um die vom Operator-Objekt generierten Handelssignale zu manipulieren und mehrere Sätze von Handelssignalen in einen einzigartigen Satz von Handelssignalen umzuwandeln, während ihre Form und aussagekräftigen Zahlen beibehalten werden.
Signale werden durch einen Mischausdruck „blender“ gemischt, zum Beispiel „s0 und (s1 + s2) * avg(s3, s4)“.
blender-Ausdrücke unterstützen die folgenden Funktionen:
Element |
Beispiel |
Beschreibung |
|---|---|---|
Strategieindex |
|
Eine Zeichenfolge, die mit s beginnt und mit einer Zahl endet, wobei die Zahl die Sequenznummer der Strategie in „Operator“ ist und das von dieser Strategie generierte Handelssignal darstellt |
Ziffern |
|
Jede gültige Zahl, eine Zahl, die an Ausdrucksoperationen beteiligt ist |
Betreiber |
|
Enthält |
Logische Operatoren |
|
Unterstützt logische Operatoren in Formen wie „&|~“ und „und/oder/nicht“. |
Funktionen |
|
Die unterstützten Funktionen sind in der folgenden Tabelle aufgeführt |
Perenthesen |
|
Kombinierte Operationen |
Weitere Beispiele zum Mischen von Ausdrücken finden Sie unter „qteasy“ Tutorial 04 – Integrierte Strategien verwenden
op = qt.Operator()
OPERATOR INFO:
=========================
Information of the Module
=========================
Total 0 operation strategies, requiring 0 types of historical data:
0 types of back test price types:
[]
Das Operator-Objekt ist ein Strategiecontainer, und einem Operator-Objekt können beliebig viele Handelsstrategien hinzugefügt werden. Gleichzeitig können die Mischmethode (Blender), die Handelssignalverarbeitungsmethode und die Handelsoperationsmethode der Handelsstrategie im Operator-Objekt verwaltet werden.
Normale Operator-Attribute und -Methoden sind wie folgt:
Erhalten Sie grundlegende Informationen zum Operator-Objekt
op.info()
Drucken Sie wichtige Informationen des Operator-Objekts
op.strategies
Rufen Sie die Liste aller Handelsstrategien im Objekt Operator ab
op.strategy_ids
Rufen Sie die IDs aller Handelsstrategien im Objekt Operator ab
op.strategy_count
Ermitteln Sie die Anzahl der Handelsstrategien im Operator-Objekt
op.signal_type
Signaltyp des Operator-Objekts, das die Bedeutung und Verarbeitungsmethode von Handelssignalen darstellt:
‚pt‘: Ziel-Haltequote-Signal, in diesem Modus konzentriert sich der Händler auf die Haltequote jeder einzelnen Aktie in einem Portfolio. Halten Sie durch rechtzeitiges Kaufen und Verkaufen die Beteiligungsquote jeder einzelnen Aktie auf einem Zielwert;
‚ps‘: Prozentuales Handelssignal. In diesem Modus konzentriert sich der Händler auf den Anteil der in regelmäßigen Abständen generierten Handelssignale und kauft oder verkauft Aktien proportional zu den Handelssignalen
‚vs‘: Mengenhandelssignal, in diesem Modus konzentriert sich der Händler auf die in regelmäßigen Abständen generierten Handelssignale und kauft oder verkauft eine bestimmte Anzahl von Aktien entsprechend den Handelssignalen
op.op_type
Laufmodus des Operator-Objekts:
„Batch“: Batch-Betriebsmodus, im Backtesting- oder Optimierungsmodus, Handelslisten im Voraus generieren und dann simulierten Handel in Batches durchführen, was schneller ist
„Echtzeit“: Echtzeit-Betriebsmodus, Handelssignale generieren und den Handel sofort simulieren. Generieren Sie nach der Generierung simulierter Handelsergebnisse das nächste Handelssignal, das für den Echtzeitbetriebsmodus oder den speziellen Backtesting-Modus geeignet ist
Holen Sie sich eine Handelsstrategie
op.get_stg(stg_id)
Holen Sie sich das Strategieobjekt anhand der Strategie-ID. Die folgenden Methoden haben den gleichen Effekt und können verwendet werden, um eine Strategie anhand der Zahlenfolge zu ermitteln
stg = op.get_stg(stg_id)
stg = op[stg_id]
stg = op[stg_idx]
Handelsstrategie hinzufügen oder ändern
op.add_strategy(stg, **kwargs)
Fügen Sie Operator eine Strategie hinzu und legen Sie gleichzeitig Strategieparameter fest
op.add_strategies(strategies)
Fügen Sie eine Reihe von Strategien stapelweise zu Operator hinzu und können Sie nicht gleichzeitig Strategieparameter festlegen
op.remove_strategy(id_or_pos=None)
Entfernen Sie eine Strategie aus Operator
op.clear_strategies()
Entfernen Sie alle Handelsstrategien in Operator
Legen Sie Strategieparameter oder Operator-Parameter fest
op.set_parameter(stg_id, pars=None, opt_tag=None, par_range=None, par_types=None, data_freq=None, run_freq=None, window_length=None, data_types=None, strategy_run_timing=None, **kwargs)
Legen Sie anhand einer Handelsstrategie-ID die Strategieparameter oder andere Attribute dieser Handelsstrategie fest
op.set_blender(price_type=None, blender=None)
Legen Sie die Mischmethode der Handelsstrategie fest. Wenn in Operator mehrere Handelsstrategien vorhanden sind, wird jede Handelsstrategie separat ausgeführt, um mehrere Sätze von Handelssignalen zu generieren, und gibt dann einen Satz von Handelssignalen gemäß benutzerdefinierten Handelsregeln aus
Mit dem folgenden Code können wir die neu erstellte DMA-Strategie zu Operator hinzufügen und die erforderlichen Strategieparameter festlegen
Alle Parametereinstellungen können mit der Methode „operator.set_parameter“ vorgenommen werden und mehrere Parameter können gleichzeitig übergeben werden. Durch Festlegen des „opt_tag“ der Strategie können Sie steuern, ob die Strategie an der Optimierung teilnimmt, während der Parameter „par_range“ den für die Strategieoptimierung erforderlichen Parameterraum definiert. Zum jetzigen Zeitpunkt wissen wir nicht, welche optimalen DMA-Timing-Parameter für den CSI 300-Index in den letzten 15 Jahren gelten, daher können wir ein paar zufällige Parameter eingeben, um einen Backtest durchzuführen und zu sehen, wie es verläuft.
op.clear_strategies()
op.add_strategy(stg, pars=(26, 35, 189), opt_tag=1)
print(f'Operator strategies: {op.strategies}')
print(f'Strategy IDs are: {op.strategy_ids}')
op.info(verbose=True)
Operator strategies: [RULE-ITER(DMA)]
Strategy IDs are: ['custom']
OPERATOR INFO:
=========================
Information of the Module
=========================
Total 1 operation strategies, requiring 1 types of historical data:
close
1 types of back test price types:
['close']
for backtest histoty price type - close:
[RULE-ITER(DMA)]:
no blender
Parameters of GeneralStg Strategies:
Strategy_type: RuleIterator
Strategy name: DMA
Description: Quick DMA strategy, determine long/short position according to differences of moving average prices with simple timing strategy
Strategy Parameter: (26, 35, 189)
Strategy Properties Property Value
---------------------------------------
Parameter count 3
Parameter types ['int', 'int', 'int']
Parameter range [(10, 250), (10, 250), (10, 250)]
Data frequency d
Sample frequency d
Window length 270
Data types ['close']
=========================
Konfigurieren Sie die Backtesting-Parameter von qteasy
Das Backtesting kann beginnen, nachdem das Operator-Objekt erstellt und Strategien hinzugefügt wurden
qteasy bietet umfangreiche Umgebungsparameter zur Steuerung des spezifischen Prozesses des Backtestings. Alle Werte der Umgebungsparametervariablen können über „qt.Configuration()“ angezeigt und über „qt.Configure()“ festgelegt werden.
qt.configuration()
Überprüfen Sie die laufenden Umgebungsvariablen qteasy
qt.configure()
Legen Sie qteasy-Laufumgebungsvariablen fest
Zu den Umgebungsvariablenparametern im Zusammenhang mit Backtesting gehören:
Zielaktien/Index für Backtesting
Start- und Endzeitraum des Backtestings
Erstinvestitionsbetrag für das Backtesting
Handelsgebühren und Handelsregeln für Backtesting
Referenzindex zur Bewertung von Handelsergebnissen
Alle oben genannten Backtesting-Handelsparameter können über „qt.configure()“ festgelegt werden
qt.configure(
mode=1, # 设置运行模式为:1-回测模式
benchmark_asset = '000300.SH', # 设置交易评价基准(类型由系统根据代码自动推断)
asset_pool = '000300.SH', # 设置交易资产组合
asset_type = 'IDX', # 交易资产组合的资产类型
trade_batch_size = 0.01, # 设置允许最小交易批量(最小0.01)
invest_start = '20100105', # 设置交易开始日期
invest_end = '20201231', # 设置交易终止日期
invest_cash_amounts = [1000000], # 设置初始交易投资金额为十万元
visual=True # 输出可视化交易结果图表
)
Starten Sie qteasy und führen Sie Operator aus
qt.run(operator, **config)
Beginnen Sie mit der Ausführung von Operator. Je nach Betriebsmodus wechselt qteasy in unterschiedliche Betriebsmodi und gibt unterschiedliche Ergebnisse aus:
Modus 0 Echtzeitmodus: Lesen Sie die neuesten (Echtzeit-)Daten und generieren Sie die neuesten Handelssignale. In diesem Modus können Sie qteasy so einstellen, dass es regelmäßig ausgeführt wird, die neuesten Daten regelmäßig liest und regelmäßig Echtzeit-Handelssignale generiert
Modus 1 Backtesting-Modus: Historische Daten über einen bestimmten Zeitraum lesen, anhand dieser Daten Handelssignale generieren und den Handel simulieren, um die Ergebnisse des simulierten Handels auszugeben
Modus 2 Optimierungsmodus: Historische Daten über einen bestimmten Zeitraum lesen, wiederholt dieselben Handelsstrategien ausführen, aber unterschiedliche Parameterkombinationen verwenden, um in diesem Zeitraum nach den Strategieparametern mit der besten Leistung zu suchen
Operator kann durch Ausführen von „qteasy.run(operator, **config)“ gestartet werden, wobei „**config“ der Testumgebungsparameter ist. Die in qt.run() als Parameter übergebenen Umgebungsvariablen sind nur für diesen Lauf gültig, die in qt.configure() festgelegten Umgebungsvariablen bleiben jedoch bis zur nächsten Änderung gültig.
Die endgültigen Backtesting-Vermögenswerte belaufen sich auf 190.000 Yuan, die jährliche Rendite beträgt nur 4,83 %, die Sharpe-Ratio beträgt nur 0,0783 und die Rendite ist im gleichen Zeitraum niedriger als die des CSI 300-Index
qt.run(op)
Das System liest automatisch historische Daten, führt Backtesting durch, schließt die Ergebnisauswertung ab und druckt den Backtesting-Bericht nach der Ausführung von qteasy.
Der Backtesting-Bericht enthält die folgenden Informationen:
Gesamtzeit für das Backtesting
Start- und Enddatum, Dauer und andere Informationen des Backtesting-Intervalls
Handelsstatistiken: wie Anzahl der Käufe, Anzahl der Verkäufe, Verhältnis voller Positionen, Verhältnis leerer Positionen, Gesamthandelskosten usw.
Renditeinformationen: Anfangsinvestitionsbetrag, endgültiger Vermögenswert, Gesamtrendite, jährliche Rendite, Benchmark-Gesamtrendite, jährliche Benchmark-Rendite, Kurtosis und Schiefe der Rendite
Indikatoren zur Portfoliobewertung: Alpha, Beta, Sharpe Ratio, Information Ratio, Volatilität und maximaler Drawdown
====================================
| |
| BACK TESTING RESULT |
| |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 1s 164.2ms
time consumption for operation back looping: 6s 720.2ms
investment starts on 2010-01-05 00:00:00
ends on 2020-12-31 00:00:00
Total looped periods: 11.0 years.
-------------operation summary:------------
Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH 53 53 106 54.0% 0.0% 46.0%
Total operation fee: ¥ 20,382.34
total investment amount: ¥1,000,000.00
final value: ¥1,052,696.57
Total return: 5.27%
Avg Yearly return: 0.47%
Skewness: -0.76
Kurtosis: 11.44
Benchmark return: 46.22%
Benchmark Yearly return: 3.52%
------strategy loop_results indicators------
alpha: -0.047
Beta: 1.000
Sharp ratio: -0.077
Info ratio: -0.018
250 day volatility: 0.156
Max drawdown: 46.12%
peak / valley: 2010-11-08 / 2014-06-19
recovered on: 2015-04-17
===========END OF REPORT=============
Außer dem Backtesting-Bericht wird auch ein visuelles Diagramm gedruckt, das detaillierte Informationen zum gesamten Backtesting-Prozess zeigt.
Folgende Informationen werden in diesem Informationsdiagramm angezeigt:
Renditekurve der gesamten Backtesting-Historie (Anzeige von Haltedauer, Kauf-/Verkaufspunkten, Benchmark-Renditekurve und maximalem Drawdown-Zeitraum)
Renditekurve und Benchmark im logarithmischen Maßstab
Diagramm zur täglichen Änderung der Rücklaufquote
Rolling Sharpe Ratio und Alpha-Rate-Änderungsdiagramm (Bewertung der Portfoliorentabilität)
Rooling-Volatilitäts- und Beta-Rate-Änderungsdiagramm (Portfolio-Risikobewertung)
Drawdown-Analysekarte (U-Boot-Karte)
Monatliche und jährliche Rendite-Heatmap und Balkendiagramm
Histogramm der statistischen Häufigkeit der monatlichen Rücklaufquote

Im simulierten Handelsprozess von „qteasy“ können zahlreiche Parameter eingestellt werden, wie zum Beispiel:
Gesamtbetrag der investierten Mittel, Datum oder Einstellung für die mehrfache Investition in Stapeln;
Handelsgebühren für den Kauf und Verkauf, einschließlich Provisionssatz, Mindestgebühr, Festgebühr und Slippage. Für den Kauf und Verkauf können verschiedene Tarife separat eingestellt werden
Lieferzeit von Kauf- und Verkaufstransaktionen, d. h. T+N-Liefersystem
Mindeststapelgröße für Kauf- und Verkaufstransaktionen, z. B. ob Bruchteile von Aktien zulässig sind oder ob ganzzahlige Aktien oder sogar Hunderte von Aktien für den Handel erforderlich sind
Die endgültigen gedruckten Backtesting-Ergebnisse sind die Endergebnisse nach Berücksichtigung aller oben genannten Handelsparameter, sodass Sie die gesamten Handelskosten sehen können. Detaillierte Handelsparametereinstellungen finden Sie in der ausführlichen Dokumentation.
Darüber hinaus liefert „qteasy“ auch mehrere Indikatoren zur Strategieleistung: Alpha und Beta betragen 0,067 bzw. 1,002, während die Sharpe-Ratio 0,041 beträgt. Der maximale Drawdown erfolgte vom 3. August 2009 bis zum 10. Juli 2014 mit einem Drawdown von 35,0 %, und erst am 16. Dezember 2014 kam es zu einer Trendwende.
In den obigen Backtesting-Ergebnissen setzen wir den Parameter „visual=False“. Wenn wir „visual=True“ setzen, können wir visuelle Backtesting-Ergebnisse in Form von Diagrammen erhalten und visuelle Informationen bereitstellen:
Kapitalkurve der Anlagestrategie
Benchmark-Daten (CSI 300-Index) historische Kurve
Kauf- und Verkaufspunkte (angezeigt durch rote und grüne Pfeile in den Referenzdaten)
Haltedauer (grün zeigt Halten an)
Indikatoren zur Bewertung der Anlagestrategie (Alpha, Sharp usw.)
Drawdown-Analyse (zeigt die fünf größten Drawdowns)
Rückflussraten-Heatmap, Bergakkumulationsdiagramm und andere Diagramme
„qteasy“ bietet umfangreiche Strategie-Backtesting-Optionen, wie zum Beispiel:
Start- und Enddatum des Backtestings
Indikatoren zur Bewertung der Anlagestrategie
Wenn beim Backtesting negative Positionen zulässig sind (wird zur Simulation des Leerverkaufsverhaltens im Futures-Handel verwendet, oder es können spezielle Simulationsalgorithmen für den Futures-Handel verwendet werden)
Weitere Optionen finden Sie in der ausführlichen Dokumentation
Optimierung der Single-Timing-Strategie
Offensichtlich können die nicht optimierten Parameter keine idealen Backtesting-Ergebnisse erzielen, daher müssen wir eine Optimierung durchführen
Wir können die Optimierungsmethode festlegen und den Optimierungsprozess steuern, indem wir verschiedene Parameter des Kontextobjekts festlegen: Die Bedeutung der folgenden Parameter ist wie folgt:
Die Optimierungsmethode ist auf 1 eingestellt und verwendet die Monte-Carlo-Optimierung, die eine gute Optimierungsfähigkeit für einen größeren Parameterraum bietet
Die Ausgabeergebnismenge ist auf 30 eingestellt
Die Anzahl der Iterationen im Optimierungsprozess beträgt 1000
Wenn der parallele Parameter auf „True“ gesetzt ist, werden alle Kerne des Mehrkernprozessors für die parallele Berechnung verwendet, um Zeit zu sparen
Starten Sie dann die Optimierung und verwenden Sie die Variablen „perfs_dma“ und „pars_dma“, um die Optimierungsergebnisse zu speichern. Während des Optimierungsprozesses wird ein Fortschrittsbalken angezeigt und nach Abschluss werden die Optimierungsergebnisse angezeigt
pars_dma = qt.run(op,
mode=2,
opti_method=1,
opti_sample_count=1000,
opti_start='20101231',
opti_end='20201231',
opti_cash_dates='20101231',
test_start='20101231',
test_end='20201231',
test_cash_dates='20101231',
parallel=True)
print(f'optimization completed, 50 parameters found, they are\n'
f'{pars_dma}')
[########################################]1000/1000-100.0% best performance: 340613.629
Optimization completed, total time consumption: 38"247
[########################################]30/30-100.0% best performance: 340613.629
====================================
| |
| OPTIMIZATION RESULT |
| |
====================================
qteasy running mode: 2 - Strategy Parameter Optimization
investment starts on 2010-12-31 00:00:00
ends on 2020-12-31 00:00:00
Total looped periods: 10.0 years.
total investment amount: ¥ 100,000.00
Reference index type is 000300.SH at IDX
Total Benchmark rtn: 66.59%
Average Yearly Benchmark rtn rate: 5.23%
statistical analysis of optimal strategy messages indicators:
total return: 161.24% ± 29.73%
annual return: 10.01% ± 1.18%
alpha: 0.048 ± 0.014
Beta: 1.001 ± 0.001
Sharp ratio: 0.625 ± 0.089
Info ratio: 0.013 ± 0.004
250 day volatility: 0.151 ± 0.006
other messages indicators are listed in below table
Strategy items Sell-outs Buy-ins ttl-fee FV ROI Benchmark rtn MDD
0 (147, 157, 57) 25.0 25.0 1,213.16 231,710.13 131.7% 66.6% 38.1%
1 (88, 108, 127) 16.0 15.0 1,009.93 233,554.10 133.6% 66.6% 44.3%
2 (105, 160, 29) 21.0 20.0 1,344.78 232,247.09 132.2% 66.6% 26.4%
3 (149, 194, 24) 19.0 19.0 1,062.61 233,932.11 133.9% 66.6% 33.4%
4 (105, 185, 25) 18.0 17.0 1,094.07 236,171.54 136.2% 66.6% 40.6%
5 (86, 147, 107) 11.0 10.0 668.08 234,827.39 134.8% 66.6% 39.7%
6 (88, 157, 101) 11.0 10.0 715.01 236,851.09 136.9% 66.6% 31.6%
7 (144, 181, 57) 19.0 19.0 1,093.20 240,445.16 140.4% 66.6% 33.8%
8 (94, 165, 78) 12.0 11.0 724.66 240,825.90 140.8% 66.6% 38.1%
9 (68, 113, 142) 13.0 12.0 819.42 244,805.70 144.8% 66.6% 42.5%
10 (80, 64, 57) 30.0 30.0 1,767.04 245,084.54 145.1% 66.6% 28.8%
11 (101, 124, 65) 23.0 22.0 1,726.89 245,504.45 145.5% 66.6% 30.7%
12 (150, 189, 33) 20.0 20.0 1,142.62 246,185.41 146.2% 66.6% 34.3%
13 (119, 200, 30) 12.0 11.0 705.66 248,111.42 148.1% 66.6% 24.1%
14 (52, 111, 136) 14.0 13.0 810.29 254,764.49 154.8% 66.6% 40.5%
15 (55, 151, 87) 14.0 13.0 896.37 248,370.33 148.4% 66.6% 38.2%
16 (98, 129, 45) 22.0 21.0 1,480.50 252,764.13 152.8% 66.6% 37.1%
17 (101, 59, 50) 27.0 26.0 1,505.08 255,487.88 155.5% 66.6% 28.8%
18 (179, 240, 25) 19.0 19.0 1,149.62 259,380.09 159.4% 66.6% 33.8%
19 (82, 127, 144) 12.0 11.0 810.46 268,321.59 168.3% 66.6% 37.4%
20 (44, 135, 117) 13.0 12.0 741.60 268,837.16 168.8% 66.6% 42.6%
21 (103, 127, 57) 22.0 21.0 1,628.33 269,776.04 169.8% 66.6% 30.3%
22 (128, 152, 92) 15.0 15.0 883.81 272,170.16 172.2% 66.6% 32.6%
23 (91, 198, 13) 17.0 16.0 1,209.55 277,214.25 177.2% 66.6% 43.3%
24 (102, 110, 129) 26.0 25.0 2,056.58 311,876.36 211.9% 66.6% 33.4%
25 (129, 204, 16) 14.0 14.0 840.49 279,142.60 179.1% 66.6% 32.6%
26 (90, 185, 45) 11.0 10.0 735.84 279,320.37 179.3% 66.6% 40.6%
27 (104, 111, 107) 30.0 29.0 2,207.23 317,371.14 217.4% 66.6% 41.0%
28 (101, 150, 24) 23.0 22.0 2,012.97 331,442.65 231.4% 66.6% 26.4%
29 (104, 142, 87) 15.0 14.0 1,044.25 340,613.63 240.6% 66.6% 23.5%
===========END OF REPORT=============
[########################################]30/30-100.0% best performance: 340613.629
====================================
| |
| OPTIMIZATION RESULT |
| |
====================================
qteasy running mode: 2 - Strategy Parameter Optimization
investment starts on 2010-12-31 00:00:00
ends on 2020-12-31 00:00:00
Total looped periods: 10.0 years.
total investment amount: ¥ 100,000.00
Reference index type is 000300.SH at IDX
Total Benchmark rtn: 66.59%
Average Yearly Benchmark rtn rate: 5.23%
statistical analysis of optimal strategy messages indicators:
total return: 161.24% ± 29.73%
annual return: 10.01% ± 1.18%
alpha: 0.048 ± 0.014
Beta: 1.001 ± 0.001
Sharp ratio: 0.625 ± 0.089
Info ratio: 0.013 ± 0.004
250 day volatility: 0.151 ± 0.006
other messages indicators are listed in below table
Strategy items Sell-outs Buy-ins ttl-fee FV ROI Benchmark rtn MDD
0 (105, 160, 29) 21.0 20.0 1,344.78 232,247.09 132.2% 66.6% 26.4%
1 (88, 108, 127) 16.0 15.0 1,009.93 233,554.10 133.6% 66.6% 44.3%
2 (147, 157, 57) 25.0 25.0 1,213.16 231,710.13 131.7% 66.6% 38.1%
3 (105, 185, 25) 18.0 17.0 1,094.07 236,171.54 136.2% 66.6% 40.6%
4 (88, 157, 101) 11.0 10.0 715.01 236,851.09 136.9% 66.6% 31.6%
5 (149, 194, 24) 19.0 19.0 1,062.61 233,932.11 133.9% 66.6% 33.4%
6 (144, 181, 57) 19.0 19.0 1,093.20 240,445.16 140.4% 66.6% 33.8%
7 (86, 147, 107) 11.0 10.0 668.08 234,827.39 134.8% 66.6% 39.7%
8 (68, 113, 142) 13.0 12.0 819.42 244,805.70 144.8% 66.6% 42.5%
9 (94, 165, 78) 12.0 11.0 724.66 240,825.90 140.8% 66.6% 38.1%
10 (150, 189, 33) 20.0 20.0 1,142.62 246,185.41 146.2% 66.6% 34.3%
11 (101, 124, 65) 23.0 22.0 1,726.89 245,504.45 145.5% 66.6% 30.7%
12 (80, 64, 57) 30.0 30.0 1,767.04 245,084.54 145.1% 66.6% 28.8%
13 (119, 200, 30) 12.0 11.0 705.66 248,111.42 148.1% 66.6% 24.1%
14 (55, 151, 87) 14.0 13.0 896.37 248,370.33 148.4% 66.6% 38.2%
15 (98, 129, 45) 22.0 21.0 1,480.50 252,764.13 152.8% 66.6% 37.1%
16 (52, 111, 136) 14.0 13.0 810.29 254,764.49 154.8% 66.6% 40.5%
17 (101, 59, 50) 27.0 26.0 1,505.08 255,487.88 155.5% 66.6% 28.8%
18 (179, 240, 25) 19.0 19.0 1,149.62 259,380.09 159.4% 66.6% 33.8%
19 (82, 127, 144) 12.0 11.0 810.46 268,321.59 168.3% 66.6% 37.4%
20 (44, 135, 117) 13.0 12.0 741.60 268,837.16 168.8% 66.6% 42.6%
21 (103, 127, 57) 22.0 21.0 1,628.33 269,776.04 169.8% 66.6% 30.3%
22 (128, 152, 92) 15.0 15.0 883.81 272,170.16 172.2% 66.6% 32.6%
23 (91, 198, 13) 17.0 16.0 1,209.55 277,214.25 177.2% 66.6% 43.3%
24 (129, 204, 16) 14.0 14.0 840.49 279,142.60 179.1% 66.6% 32.6%
25 (90, 185, 45) 11.0 10.0 735.84 279,320.37 179.3% 66.6% 40.6%
26 (104, 111, 107) 30.0 29.0 2,207.23 317,371.14 217.4% 66.6% 41.0%
27 (102, 110, 129) 26.0 25.0 2,056.58 311,876.36 211.9% 66.6% 33.4%
28 (101, 150, 24) 23.0 22.0 2,012.97 331,442.65 231.4% 66.6% 26.4%
29 (104, 142, 87) 15.0 14.0 1,044.25 340,613.63 240.6% 66.6% 23.5%
===========END OF REPORT=============

optimization completed, 50 parameters found, they are
[(147, 157, 57), (105, 160, 29), (88, 108, 127), (149, 194, 24), (86, 147, 107), (105, 185, 25), (88, 157, 101), (144, 181, 57), (94, 165, 78), (68, 113, 142), (80, 64, 57), (101, 124, 65), (150, 189, 33), (119, 200, 30), (55, 151, 87), (98, 129, 45), (52, 111, 136), (101, 59, 50), (179, 240, 25), (82, 127, 144), (44, 135, 117), (103, 127, 57), (128, 152, 92), (91, 198, 13), (129, 204, 16), (90, 185, 45), (102, 110, 129), (104, 111, 107), (101, 150, 24), (104, 142, 87)]
Nach der Optimierung können wir dreißig Sätze bester Parameter sehen, und selbst der schlechteste Parameter kann einen Endwert von über 60.000 Yuan erzielen. Wir können daraus manuell die besten Parameter auswählen und einen weiteren Backtest durchführen:
Wir können feststellen, dass der Endwert von 19.000 im letzten Backtest auf 124.000 gestiegen ist, mit einer jährlichen Rendite von 18,9 %, und auch die Sharpe Ratio ist auf 0,833 gestiegen
op.set_parameter('dma', pars=(104, 142, 87))
qt.run(op,
mode=1, visual=True)
Die Ergebnisse des Backtestings lauten wie folgt:
====================================
| |
| BACK TESTING RESULT |
| |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 55.7ms
time consumption for operation back looping: 885.7ms
investment starts on 2010-12-31 00:00:00
ends on 2020-12-31 00:00:00
Total looped periods: 10.0 years.
-------------operation summary:------------
Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH 15 14 29 52.6% 0.0% 47.4%
Total operation fee: ¥ 1,044.25
total investment amount: ¥ 100,000.00
final value: ¥ 340,613.63
Total return: 240.61%
Avg Yearly return: 13.03%
Skewness: -0.78
Kurtosis: 13.36
Benchmark return: 66.59%
Benchmark Yearly return: 5.23%
------strategy loop_results indicators------
alpha: 0.087
Beta: 1.001
Sharp ratio: 0.751
Info ratio: 0.020
250 day volatility: 0.140
Max drawdown: 23.53%
peak / valley: 2015-12-31 / 2016-01-28
recovered on: 2017-08-28
===========END OF REPORT=============

Erstellen Sie eine benutzerdefinierte Strategie
qteasy ermöglicht nicht nur die Verwendung integrierter Strategien, sondern auch die Erstellung benutzerdefinierter Strategien. Nachfolgend finden Sie ein einfaches Beispiel, das eine einfache Rotationshandelsstrategie definiert