8. 組み込みの戦略を使用する

qteasy は、以下の機能を備えた定量的取引分析ツールキットの完全にローカライズされた展開と運用です。

  • 財務データへのアクセス、クリーニング、保存、処理、視覚化、および使用

  • クオンツ取引戦略を作成し、多数の組み込みの基本取引戦略を提供します

  • ベクトル化された高速取引戦略のバックテストと取引結果の評価

  • 取引戦略パラメーターの最適化と評価

  • 取引戦略の展開と実際の運用

この一連のチュートリアルでは、一連の実践的な例を通じて、qteasy の主な機能と使用法を完全に理解できます。

8.1. 始める前に

このチュートリアルを開始する前に、次のことを習得していることを確認してください。

  • qteasy のインストールと構成 —— 詳細は QTEASY チュートリアル 1 を参照してください。

  • ローカル データ ソースが設定されており、十分な履歴データがすでにローカルにダウンロードされています (取引カレンダー、株式/ファンド/指数の基本情報、株式/ファンド/指数の価格データ、財務指標またはその他の財務データが含まれます。詳細については、QTEASY チュートリアル 2 を参照してください)。

  • トレーダー オブジェクトの作成方法、組み込み取引戦略の使用方法とその履歴パフォーマンスのバックテスト方法、バックテスト ログの確認方法、戦略の実行パラメーターまたは調整可能なパラメーターの調整方法の理解方法、および戦略のパフォーマンスの向上方法を学びます — QTEASY チュートリアル 3

QTEASY ドキュメント では、戦略を実行するためのトレーダー オブジェクトの作成方法、履歴データを使用したバックテスト戦略、バックテスト取引記録のレビュー、戦略の変更などに関する詳細コンテンツも見つけることができます。 qteasy の基本的な使用法にまだ慣れていない場合は、そこにアクセスして詳細な説明を参照してください。

8.2. この章の対象

前のチュートリアル セクションでは、Operator トレーダー オブジェクトを作成し、最初の銘柄選択取引戦略を実行させました。ただし、qteasy では、トレーダーは単一の取引戦略を実行するだけではありません。実際、Operator オブジェクトは実際のトレーダーに似ており、任意の数の取引戦略を同時に管理および実行できます。これらの戦略は、異なる時間と頻度で個別に実行することも、多くをまとめてバッチで実行することもできます。また、同時に実行される戦略は、任意の指定された方法で目的の形式に「ブレンド」することもできます。

トレーダーは、さまざまな色の絵の具が入ったパレットを持っている画家と考えることができます。さまざまな色を使用して鮮やかな線を描いたり、複数の色を混ぜて柔らかいトランジショントーンを作成したりできます。このようにして、たとえ画家が絵の具をほんの一握りしか持っていなくても、その筆は広大な世界を構成する何百万もの色を混ぜ合わせることができます。

これは、まさに qteasy の重要な設計コンセプトの 1 つです。次の 2 つのツールを使用すると、Operator トレーダー オブジェクトは、非常に単純な取引戦略を組み合わせて非常に複雑な取引戦略に構成することができ、それによって複雑な機能が可能になります。これら 2 つのツールには次のものが含まれます。

  • 戦略グループ: トレーダーはグループで複数の戦略を実行できます。取引戦略の各グループは、同じ実行頻度 (例: 毎日、毎時、または毎分) と同じ実行タイミング (例: 毎日の終値または毎日 10:30) を共有するため、戦略をいつ実行するかを柔軟に制御できます。

  • Blender Strategy Mixer: 同じグループ内で同時に実行される取引戦略は、必然的に同時に実行されます。各戦略は独自のロジックに従って一連の取引シグナルを生成しますが、この一連のシグナルは何らかの方法で 1 つのセットに「マージ」する必要があります。このマージは、ミキサー blender によって実行されます。ミキサーは、特に複数の戦略によって生成された取引シグナルを 1 つのセットに結合する役割を果たします。マージ ロジックはユーザー定義の blender string 構成文字列によって完全に決定され、ユーザーが完全に制御できます。

この章では、qteasy でさらに多くの組み込み戦略を使用する方法、トレーダーに複数の取引戦略を同時に実行させる方法、および戦略ミキサー blender を使用して取引戦略を使用してさまざまな組み合わせ戦略を生成する方法を学びます。

現在、qteasy は 70 を超える組み込み取引戦略をサポートしており、そのすべてをすぐに使用できます。組み込みの取引戦略の完全なリストについては、参考ドキュメント を参照してください。

以下の API を使用して、qteasy で提供されるすべての組み込み取引戦略のリストを取得できます。

import qteasy as qt
qt.built_ins()

上記の API は、qteasy に組み込まれているすべての取引戦略を返します。

{'crossline': qteasy.built_in.CROSSLINE,
 'macd': qteasy.built_in.MACD,
 'dma': qteasy.built_in.DMA,
 'trix': qteasy.built_in.TRIX,
 'cdl': qteasy.built_in.CDL,
 'bband': qteasy.built_in.BBand,
 's-bband': qteasy.built_in.SoftBBand,
 'sarext': qteasy.built_in.SAREXT,
 'ssma': qteasy.built_in.SCRSSMA,
 'sdema': qteasy.built_in.SCRSDEMA,
 'sema': qteasy.built_in.SCRSEMA,
 'sht': qteasy.built_in.SCRSHT,
 'skama': qteasy.built_in.SCRSKAMA,
 'smama': qteasy.built_in.SCRSMAMA,
 ...}

次のリストは、qteasy ですぐに使用できる組み込みの取引戦略の一部を示しています。完全なリストについては、参考ドキュメント を参照してください。

ID

名前

説明

crossline

TimingCrossline

クロスライン タイミング戦略クラス。長移動平均と短移動平均のクロスを使用してロングとショートの状態を決定します。
1.短期移動平均が長期移動平均を上回り、距離が l*m% より大きい場合、目標位置を 1
2 に設定します。短期移動平均が長期移動平均を下回り、距離が l*m% より大きい場合、目標位置を -1 に設定します
3。長移動平均と短移動平均の間の距離が l*m% 以下の場合、ポジションターゲットを 0 に設定します。

macd

TimingMACD

MACD タイミング戦略クラス。MACD 移動平均戦略を使用してターゲット ポジション パーセンテージを生成します。
1. MACD値が0より大きい場合、ポジションターゲットを1
2に設定します。 MACD値が0未満の場合、ポジションターゲットを0に設定します

dma

TimingDMA

DMA タイミング戦略
1. DMA が AMA よりも高い場合、長い間隔になります。つまり、DMA ラインが AMA ラインを下から上に横切った後、出力は 1
2 になります。 DMA が AMA を下回る場合、それは短い間隔です。つまり、DMA ラインが AMA ラインを上から下まで横切った後、出力は 0 になります。

trix

TimingTRIX

TRIX タイミング戦略、株価の 3 倍平滑指数移動平均価格を長短の判断に使用する:
価格の 3 倍平滑指数移動平均価格 TRIX を計算し、M 日 TRIX の移動平均を計算します。
1. TRIX が MATRIX より上の場合、位置目標を 1
2 に設定します。 TRIX が MATRIX を下回る場合、位置ターゲットを -1 に設定します

cdl

TimingCDL

CDL タイミング戦略、K ライン チャートの要件を満たす cdldoji パターンを見つけます
履歴データ ウィンドウ (0 から 100 の間) に表示される cdldoji パターンを検索し、それを合計/100 し、同等の cdldoji 一致数量を計算し、一致する数量を取引シグナルとして使用します。

bband

TimingBBand

ボリンジャーバンド取引戦略では、株価とボリンジャーバンドの上下バンドの関係に基づいてロングポジションとショートポジションを決定し、価格がボリンジャーバンドラインの上または下を横切るときに取引シグナルを生成します。ボリンジャーバンドラインの移動平均線タイプは選択できません
1.価格がアッパーバンドを超えると、フルポジションの買いシグナルが生成されます
2.価格が下限バンドを下回ると、フルポジションの売りシグナルが生成されます。

s-bband

SoftBBand

ボリンジャーバンドのプログレッシブ取引戦略では、株価とボリンジャーバンドの上下バンドの関係に基づいてロングポジションとショートポジションを決定し、取引シグナルは一度に生成されるのではなく、徐々に売買されます。 BBAND を計算し、価格が BBAND の上限または下限バンドを超えているかどうかを確認します。
1.価格が上限バンドを超えた後は、毎日 10% の比例した買いシグナルが生成されます。
2.価格が下限バンドを下回ると、毎日 33% の比例した売りシグナルが生成されます。

sarext

TimingSAREXT

拡張パラボリック SAR 戦略。インデックスが 0 より大きい場合に買いシグナルが発行され、インデックスが 0 より小さい場合に売りシグナルが発行されます。

ssma

SCRSSMA

単一移動平均クロス戦略 —— SMA移動平均(単純移動平均):株価とSMA移動平均の相対位置に応じてポジション比率を設定

sdema

SCRSDEMA

単一移動平均クロス戦略 —— DEMA移動平均(二重指数平滑移動平均):株価とDEMA移動平均の相対位置に応じてポジション比率を設定

sema

SCRSEMA

単一移動平均クロス戦略 —— EMA移動平均(指数平滑移動平均):株価とEMA移動平均の相対位置に応じてポジション比率を設定

組み込みストラテジーの完全なリストは、参考ドキュメント を参照してください。

各組み込み取引戦略には独自の ID があります (例: 上の表の crosslinemacddma など)。ユーザーは、この ID を使用して組み込み取引戦略のインスタンスを取得し、それをトレーダー オブジェクトに追加して使用できます。例えば:

stg = qt.get_built_in_strategy('dma')
stg.info()

得られた出力:

================================ Strategy: DMA =================================
Strategy RULE-ITER(DMA)
Parameters: ['slow', 'long', 'diff'] = (12, 26, 9)                  
Date Types: close_ANY_d x 270                                       
----------------------------- Iteration Properties -----------------------------
Allow multi pars        True
Multi-parameter not set                      

戦略パラメーターの意味、シグナル生成ルールなど、各組み込み取引戦略の詳細な説明を表示する必要がある場合は、各取引戦略の doc-string を表示できます。

例えば:

qt.built_in_doc('Crossline', print_out=True)

ご覧いただけます

Init signature: qt.built_in.TimingCrossline(pars:tuple=(35, 120, 0.02))
Docstring:     
crossline择时策略类,利用长短均线的交叉确定多空状态

策略参数:
    s: int, 短均线计算日期;
    l: int, 长均线计算日期;
    m: float, 均线边界宽度(百分比);
信号类型:
    PT型:目标仓位百分比
信号规则:
    1,当短均线位于长均线上方,且距离大于l*m%时,设置仓位目标为1
    2,当短均线位于长均线下方,且距离大于l*mM时,设置仓位目标为-1
    3,当长短均线之间的距离不大于l*m%时,设置仓位目标为0

策略属性缺省值:
默认参数:(35, 120, 0.02)
数据类型:close 收盘价,单数据输入
采样频率:天
窗口长度:270
参数范围:[(10, 250), (10, 250), (0, 1)]
策略不支持参考数据,不支持交易数据
File:           ~/Library/CloudStorage/OneDrive-Personal/Projects/PycharmProjects/qteasy/qteasy/built_in.py
Type:           type
Subclasses:     

ipython などのインタラクティブな python 環境では、? を使用して組み込みの取引戦略に関する詳細情報を表示することもできます。次に例を示します。

>>> qt.built_in.SelectingNDayRateChange?

以下を確認できます。

Init signature: qt.built_in.SelectingNDayRateChange(pars=(14,))
Docstring:     
基础选股策略:根据股票以前n天的股价变动比例作为选股因子

策略参数:
    n: int, 股票历史数据的选择期
信号类型:
    PT型:百分比持仓比例信号
信号规则:
    在每个选股周期使用以前n天的股价变动比例作为选股因子进行选股
    通过以下策略属性控制选股方法:
    *max_sel_count:     float,  选股限额,表示最多选出的股票的数量,默认值:0.5,表示选中50%的股票
    *condition:         str ,   确定股票的筛选条件,默认值'any'
                                'any'        :默认值,选择所有可用股票
                                'greater'    :筛选出因子大于ubound的股票
                                'less'       :筛选出因子小于lbound的股票
                                'between'    :筛选出因子介于lbound与ubound之间的股票
                                'not_between':筛选出因子不在lbound与ubound之间的股票
    *lbound:            float,  执行条件筛选时的指标下界, 默认值np.-inf
    *ubound:            float,  执行条件筛选时的指标上界, 默认值np.inf
    *sort_ascending:    bool,   排序方法,默认值: False,
                                True: 优先选择因子最小的股票,
                                False, 优先选择因子最大的股票
    *weighting:         str ,   确定如何分配选中股票的权重
                                默认值: 'even'
                                'even'       :所有被选中的股票都获得同样的权重
                                'linear'     :权重根据因子排序线性分配
                                'distance'   :股票的权重与他们的指标与最低之间的差值(距离)成比例
                                'proportion' :权重与股票的因子分值成正比

策略属性缺省值:
默认参数:(14,)
数据类型:close 收盘价,单数据输入
采样频率:月
窗口长度:150
参数范围:[(2, 150)]
策略不支持参考数据,不支持交易数据
File:           ~/Library/CloudStorage/OneDrive-Personal/Projects/PycharmProjects/qteasy/qteasy/built_in.py
Type:           type
Subclasses:    

8.3. 複数の戦略の組み合わせ

qteasy では、Operator トレーダー オブジェクトは、グループ内の任意の数の取引戦略を同時に実行できます。実行中、これらの各戦略は必要な履歴データを個別に取得し、異なる取引シグナルを個別に生成します。これらのシグナルは一連の取引シグナルに結合され、統一された方法で実行されます。

ユーザーはこの機能を使用して、トレーダー オブジェクトで異なる焦点を当てた複数の取引戦略を同時に実行できます。たとえば、1 つの取引戦略は個々の株式の株価を監視し、株価に基づいて選択シグナルを生成します。2 番目の取引戦略は、特に広範な市場の傾向を監視する責任を負い、より広範な市場の傾向に基づいて全体的なポジションを決定します。 3 番目の取引戦略は、特にストップロスとストッププロフィット、および特定の時間でのストップロスを担当します。最終的な取引シグナルは主に最初の取引戦略に基づいていますが、2 番目の戦略によって制限され、必要に応じて 3 番目の戦略によって完全に制御されます。

あるいは、ユーザーは、複数の戦略が包括的な戦略で独立して取引の決定を下す「委員会」戦略を簡単に策定することができ、最終的な取引シグナルはすべてのサブ戦略で構成される「委員会」の投票によって決定されます。投票方法には、単純多数決、絶対多数決、加重投票結果などがあります。

上記の組み合わせた取引戦略では、個々の取引戦略は非常にシンプルで定義が簡単ですが、それらを組み合わせることでより大きな効果を生み出すことができます。同時に、各サブ戦略は独立しており、複雑で包括的な取引戦略に自由に組み合わせることができます。これにより、ゼロから戦略を繰り返し開発する必要がなくなります。サブ戦略を再配置して再結合し、その組み合わせ方法を再定義するだけで、一連の複雑で包括的な取引戦略を迅速に構築できます。これにより、取引戦略の構築効率が大幅に向上し、サイクルが短縮されます。時は金なり。

取引シグナルの混合とは、取引シグナルに対してさまざまな操作または機能を実行することを指します。これは、単純な論理演算や加算/減算から複雑なカスタム関数まで多岐にわたります。最終出力取引シグナルが意味のあるものである限り、ndarray に適用できる関数はどれも取引シグナルを混合するために使用できます。

戦略の組み合わせ方法を定義します blender

Operator トレーダー オブジェクトでは、すべての取引戦略を戦略グループに割り当てる必要があります。グループ内に複数の戦略がある場合は、blender を定義する必要があります。 blender が明示的に定義されておらず、ストラテジーの数が 1 を超える場合、qteasy は、Operator の実行時にデフォルトの blender を作成します。ただし、マルチ戦略セットアップを正しく実行するには、ユーザーが自分で blender を定義する必要があります。

blender_str はユーザー定義の組み合わせ式です。ユーザーはこの式を使用して、さまざまな取引戦略をどのように組み合わせるかを決定します。この結合式は、算術演算子、論理演算子、関数、およびその他のシンボルを使用して、ストラテジ信号の結合方法を指定します。 blender 式には次の要素を含めることができます。

blender 式でサポートされている記号は次のとおりです。

要素

説明

戦略番号

s0, s1...

s で始まり数字で終わる文字列。この数字は、Group の戦略のインデックスであり、その戦略によって生成される取引シグナルを表します。

数字

-1.35

任意の有効な数値、式演算に含まれる数値

オペレーター

+

+ - * / ^ を含む数値演算子

論理演算子

and

&/~ および and/or/not などの論理演算子がサポートされています

機能

sum()

サポートされている機能は次の表にあります。

括弧

()

グループ運用

blenderの例

Operator オブジェクト (シリアル番号 s0/s1/s2) に 3 つの取引戦略がある場合、次の方法で定義された blender は正当で使用可能であり、Operator.set_blender() を使用して blender を設定します。

算術演算子を使用して定義された Blender 式

's0 + s1 + s2'

この場合、3 つの取引戦略によって生成された取引シグナルが合計されて、最終的な取引シグナルになります。戦略 0 の結果が 10% 購入、戦略 1 の結果が 10% 購入、戦略 2 の結果が 30% 購入の場合、最終結果は 50% 購入になります。

論理演算子を使用して定義された Blender 式:

's0 and s1 and s2'

この場合、最終的な取引シグナルは、取引戦略 1、2、および 3 がすべて取引シグナルを生成した場合にのみ形成されます。たとえば、戦略 1 の結果が買い、戦略 2 の結果が買い、戦略 3 に取引シグナルがない場合、最終結果は取引シグナルなしとなります。

Blender 式には、括弧やいくつかの関数を含めることもできます。

'max(s0, s1) + s2'

戦略 1 と 2 の結果の最大値と戦略 3 の結果の合計が最終的な取引シグナルとなることを意味します。戦略 1 の結果が 10% 購入、戦略 2 の結果が 20% 購入、戦略 3 の結果が 30% 購入の場合、最終結果は 50% 購入になります。

戦略は Blender 式内で複数回出現でき、純粋な数値もサポートされます。

'(0.5 * s0 + 1.0 * s1 + 1.5 * s2) / 3 * min(s0, s1, s2)'

上記のblender 式の意味: まず 3 つの戦略シグナルの加重平均を計算し (重みはそれぞれ 0.5、1.0、1.5)、次に 3 つのシグナルの最小値を乗算します。

Blender 式の関数パラメータは関数名で定義されます。

'clip_-0.5_0.5(s0 + s1 + s2) + pos_2_0.2(s0, s1, s2)'

上記のblender 式は 2 つの異なる関数演算を定義しており、最終結果は結果を加算することで得られます。最初の機能はレンジ クリッピングで、3 セットの戦略信号を加算した後、-0.5 未満と 0.5 より大きい信号値がクリッピングされ、計算結果が取得されます。 2 番目の機能はポジション判定機能で、ポジションが 0.2 より大きい 3 セットのシグナルの期間をカウントし、それらを「ロング ポジション」として定義し、各期間における 3 つの戦略におけるロング ポジション推奨の数をカウントします。 3 つ以上のストラテジーがロング ポジション推奨を保持している場合は、フル ポジションのロング ポジションが出力され、それ以外の場合は空のポジションが出力されます。

blender 式では次の関数がサポートされています。

機能

表現例

説明

abs

abs(s0)

絶対値機能
すべての売買シグナルの絶対値を計算します
売買シグナルは1つだけ入力可能

avg

avg(s0, s1, ...)

平均値機能
全取引シグナルの平均値を計算
入力シグナル数は無制限

avgpos

avgpos_N_T(s0, s1, ...)

平均累積関数
売買シグナルがポジション目標シグナルの場合、同時に生成される空でないポジションシグナル(出力シグナル絶対値>T)の数をカウントします。ショート/ロング信号の数が N より大きい場合は、すべてのショート/ロング信号の平均値を出力し、それ以外の場合は 0 を出力します。
入力信号の数は無制限です。

ceil

ceil(s0)

天井機能
売買シグナル切り上げ
売買シグナルは1つだけ入力可能

clip

clip_U_L(s0)

クリップ機能
範囲を超えたシグナル値をクリップし、関数名で上限と下限の範囲を定義
売買シグナルは1つだけ入力可能

combo

combo(s0, s1, ...)

コンボバリュー機能
全取引シグナルの合計を出力
入力シグナル数は無制限

committee

cmt_N_T(s0, s1, ...)

委員会関数(累積ポジション関数posに相当))
売買シグナルが目標ポジションシグナルの場合、空でないポジションシグナル(出力シグナル絶対値>T)が同時にいくつ発生するかをカウントします。ロング/ショート信号の数が N より大きい場合、-1/1 を出力します。それ以外の場合は 0 を出力します。
入力信号の数は無制限です

exp

exp(s0)

exp関数
eのシグナルパワーを計算
取引シグナルは1つだけ入力可能

floor

floor(s0)

フロア関数
売買シグナル切り捨て
売買シグナルは1つだけ入力可能

log

log(s0)

対数関数
eを底とした対数値を計算します
売買シグナルは1つだけ入力可能

log10

log10(s0)

10を底とする対数関数
10を底とした対数値を計算します
売買シグナルは1つだけ入力可能

max

max(s0, s1, ...)

最大値機能
全取引シグナルの最大値を計算
入力シグナル数は無制限

min

min(s0, s1, ...)

最小値機能
全取引シグナルの最小値を計算
入力シグナル数は無制限

pos

pos_N_T(s0, s1, ...)

累積ポジション機能
売買シグナルがポジション対象シグナルの場合、同時に生成される空でないポジションシグナル(出力信号絶対値>T)の数をカウントします。ロング/ショート信号数がNより多い場合は-1/1を出力、そうでない場合は0を出力します。
入力信号数は無制限です。

position

position_N_T(s0, s1, ...)

累積ポジション機能
売買シグナルがポジション対象シグナルの場合、同時に生成される空でないポジションシグナル(出力信号絶対値>T)の数をカウントします。ロング/ショート信号数がNより多い場合は-1/1を出力、そうでない場合は0を出力します。
入力信号数は無制限です。

pow

pow(s0, s1)

べき関数
最初の取引シグナルの 2 番目のシグナル パワー、つまり sig0^sig1 を計算します
入力シグナルの数は 2 つまでです

power

power(s0, s1)

べき関数
最初の取引シグナルの 2 番目のシグナル パワー、つまり sig0^sig1 を計算します
入力シグナルの数は 2 つまでです

sqrt

sqrt(s0)

平方根関数
売買シグナル平方根
売買シグナルは1つだけ入力可能

str

str_T(s0, s1, ...)

強度累積関数
すべての売買シグナルを合計し、シグナル強度がTを超えた場合は1を出力、そうでない場合は0を出力
入力シグナルの数は無制限

strength

strength_T(s0, s1, ...)

強度累積関数
すべての売買シグナルを合計し、シグナル強度がTを超えた場合は1を出力、そうでない場合は0を出力
入力シグナルの数は無制限

sum

sum(s0, s1, ...)

コンボバリュー機能
全取引シグナルの合計を出力
入力シグナル数は無制限

unify

unify(s0)

均一関数
取引シグナルを正規化し、各行の合計が 1 になるように同じ行の取引シグナルを比例的にスケールします
取引シグナルは 1 つだけ入力できます

vote

vote_N_T(s0, s1, ...)

投票機能(累積ポジション機能に相当)
売買シグナルがポジション対象シグナルの場合、同時に生成される空でないポジションシグナル(出力信号絶対値>T)の数をカウントします。ロング/ショート信号数がNより多い場合は-1/1を出力、そうでない場合は0を出力します。
入力信号数は無制限です。

次のメソッドを使用して、戦略の blender を設定または取得できます。

operator.set_blender(blender_str=None, group_id=None)

blender を設定するには、式 blender_str を直接渡します。この式は自動的に解析され、取引戦略を組み合わせるために使用されます。 set_blender() を使用する場合、group_id パラメーターを使用して、この blender がどの戦略グループに対応するかを指定できます。 group_id が指定されていない場合、デフォルトでこの blender がすべての戦略グループに使用されます。

operator.view_blender()

blender を表示します。 Note that, for readability, the strategy codes s0, s1, and s2 in the blender expression will be automatically replaced with the specific strategy IDs, as shown in the example below:

>>> op = qt.Operator('dma, macd, trix')
>>> op.set_blender('(0.5 * s0 + 1.0 * s1 + 1.5 * s2) / 3 * min(s0, s1, s2)', group_id='Group_1')
>>> op.view_blender()

operator.view_blender() は、キーが戦略グループ ID であり、値がブレンダー式である辞書を出力します。 Blender 式では、s0s1s2 はすでに特定の戦略 ID に置き換えられています。

出力は次のとおりです。

{'Group_1': '(0.5 * dma + 1.0 * macd + 1.5 * trix) / 3 * min(dma, macd, trix)'}

view_blender() を呼び出すときに group_id パラメータを指定すると、その戦略グループのブレンダー式のみが出力されます。

>>> op.view_blender(group_id='Group_1')

出力は次のとおりです。

'(0.5 * dma + 1.0 * macd+ 1.5 * trix) / 3 * min(dma, macd, trix)'

上記の例 s0s1s2 は、dmamacdtrix に置き換えられますが、Operator に複数の同一の戦略が含まれている場合は、区別するために異なる戦略 ID が自動的に割り当てられます。

>>> op = qt.Operator('dma, dma, dma')
>>> op.set_blender('(0.5 * s0 + 1.0 * s1 + 1.5 * s2) / 3 * min(s0, s1, s2)')
>>> op.view_blender('Group_1')

出力は次のとおりです。

'(0.5 * dma_0 + 1.0 * dma_1 + 1.5 * dma_2) / 3 * min(dma_0, dma_1, dma_2)'

blenderの使用例

blender がどのように機能するかを示すために、以下の例が使用されます。

トレーダー オブジェクトを生成し、5 つの DMA 取引戦略を同時に実行しますが、5 つの取引戦略には異なる調整可能なパラメーターがあります。この時点で、トレーダーは 5 つの同じ取引ロジックを同時に実行していることがわかりますが、これら 5 つの取引ロジックは異なるパラメーターで構成されているため、同じ入力条件下では異なる取引シグナルが生成されます。これは、5 つの取引戦略にはそれぞれ重点があり、長期的な変数を捉えるのが得意な戦略もあれば、短期のトレンドを追跡するのが得意な戦略もあるということです。

さて、同じ 5 つの取引戦略ですが、3 つの異なる例を使用して 3 つの異なる混合方法を示します。これは、同じ取引戦略と取引パラメーターであっても、同じ履歴間隔で異なる混合方法も最終的な取引結果に影響を与える可能性があることを示します。

第 1 のブレンド方法: 加重平均ブレンド

最初の混合方法では、5 つの取引戦略の結果の加重平均がとられます。各取引戦略の重みは次のとおりです。

  • s0: 重さ0.8

  • s1: 重量1.2

  • s2: 重量 2.0

  • s3: 重量0.5

  • s4: 重量1.5

上記の加重平均ブレンドを実現するには、次の blender 式を定義できます。これは、まず 5 つの取引戦略の結果にそれぞれの重みを乗算し、次に重みの合計 (つまり 5) で割って加重平均の結果を取得することを意味します。

(0.8*s0+1.2*s1+2*s2+0.5*s3+1.5*s4)/5

次に、この blender 式をトレーダー オブジェクトに設定し、戦略を実行して、バックテスト結果を取得します。

# 创建一个交易员对象,同时运行五个相同的dma交易策略,这些交易策略运行方式相同,但是设置不同的参数后,会产生不同的交易信号。我们通过不同的策略组合方式,得到不同的回测结果
op = qt.Operator('dma, dma, dma, dma, dma')
# 分别给五个不同的交易策略设置不同的策略参数,使他们产生不同的交易信号
op.set_parameter(stg_id=0, par_values=(132, 200, 24))
op.set_parameter(stg_id=1, par_values=(124, 187, 51))
op.set_parameter(stg_id=2, par_values=(103, 81, 16))
op.set_parameter(stg_id=3, par_values=(48, 111, 148))
op.set_parameter(stg_id=4, par_values=(104, 127, 58))

op.set_blender('(0.8*s0+1.2*s1+2*s2+0.5*s3+1.5*s4)/5')

# 运行策略
res = qt.run(op, mode=1, invest_start='20160405', invest_end='20210201')

結果のバックテスト レポートは次のとおりです: 年率リターン 5.51%、シャープ レシオ 0.44。バックテスト レポートの解釈方法については、チュートリアル セクション 3 の関連コンテンツを参照してください。

ここでは、トレーディング戦略のパフォーマンスを向上させる方法には焦点を当てていません。代わりに、同じ取引戦略が異なるブレンド方法でどのように異なるバックテスト結果を生成するかに焦点を当てており、バックテスト結果の違いは完全に異なるブレンド方法に起因しています。

====================================
|                                  |
|         BACKTEST REPORT          |
|                                  |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 171.1 ms
time consumption for operation back testing:  3.2 ms
investment starts on      2016-04-05 15:00:00
ends on                   2021-01-29 15:00:00
Total looped periods:     4.8 years.
-------------operation summary:------------
Only non-empty shares are displayed, call 
"loop_result["oper_count"]" for complete operation summary
          Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH   370      354    724   88.1%     -0.0%     11.9%  

Total operation fee:     ¥    3,847.81
total investment amount: ¥  100,000.00
final value:              ¥  129,535.45
Total return:                    29.54% 
Avg Yearly return:                5.51%
Skewness:                         -0.90
Kurtosis:                         12.22
Benchmark return:                63.94% 
Benchmark Yearly return:         10.80%

------strategy loop_results indicators------ 
alpha:                           -0.060
Beta:                             1.311
Sharp ratio:                      0.440
Info ratio:                      -0.041
250 day volatility:               0.125
Max drawdown:                    18.49% 
    peak / valley:        2018-01-26 / 2019-01-03
    recovered on:         2019-03-05


==================END OF REPORT===================

png

上の利益曲線チャートを注意深く調べると、チャートの背景がさまざまな色合いの緑色のストライプで描かれていることに気づくでしょう。これらの縞は、その期間におけるポジションの比率を表します。白は空のポジション、つまり株式をまったく保有していないことを表し、最も濃い緑色は株式を 100% 保有していることを表します。中央の緑色は位置比率0~100%を表し、位置比率が高くなるほどストライプの色が濃くなります。

5 つの取引戦略の出力は加重平均として結合されるため、いずれかの戦略の出力が変化すると、最終的な取引シグナルも変化します。これにより、バックテスト期間全体の取引数も非常に頻繁になり (合計 370 回の売りオペレーションと 354 回の買いオペレーション)、ポジション比率も 0% から 100% の間で頻繁に変動します。

チャートから、取引履歴期間全体でさまざまな緑色の色合いがあることがわかります。各保有間隔を注意深く調べると、これらの間隔の保有率が、その時点での 5 つの取引戦略の混合結果に正確に対応していることがわかります。すべての取引戦略がフルポジションを購入することを「満場一致で決定」した場合、加重平均の結果は 100% 買いとなりますが、1 つ以上の戦略が空のポジションを保持することを決定している限り、最終的な加重平均の結果は株式の特定の割合を保持することになり、これは 5 つの戦略シグナルの加重平均結果と等しくなります。最終的な結果は、ポジション率は 0% から 100% の間で変動し、完全に空のポジションと完全にフルのポジションの時間は長くありません。

これは、空ポジションによって一方的な下落相場を完全に回避することはできないことを意味しますが、常に一定のポジションを維持することで上昇チャネルをよりよく把握できるようになります。

一方、ポジションが柔軟に調整されるため、一方向の下落相場ではポジション (緑色の深さ) が明らかに低くなり、上昇相場ではポジションが高くなっていることがわかります。これはまさに予想通りです。

次に、まったく異なるブレンド方法を見てみましょう。

第二回配合方法:委員会投票

このブレンダーでは、同じ 5 つの取引戦略で「委員会」を形成し、平等な投票を通じてポジションを決定します。ポジションは、「黒か白か」の 2 つの結果 (フル ポジションまたは空のポジション) のいずれかである必要があります。式は次のとおりです。

この時点で、blender_str でサポートされている特別な関数、「コミッティー関数」、cmt_N_T(s0, s1, ...) を使用する必要があります。この関数は、非フラット信号 (信号の絶対値 > T) を同時に生成するストラテジの数が N より大きい場合、完全に投資されたロング (1) または完全に投資されたショート (-1) を出力します。それ以外の場合はフラット (0) を出力します。したがって、N=3、T=0 の場合、式は次のようになります。

cmt_3_0(s0, s1, s2, s3, s4)

これは、5 つの取引戦略で構成される委員会を作成することに相当します。少なくとも 3 つの戦略が同時に完全投資のロングポジションを推奨する場合にのみ、委員会は完全投資のロング推奨を出力します。それ以外の場合は、フラット (ポジションなし) の推奨事項が出力されます。

したがって、最終結果は、ポジション比率が 100% (3 つ以上の戦略が完全投資の推奨を出力する場合) または 0% (3 つ未満の戦略が完全投資の推奨を出力する場合) になります。一方的な下落相場では、ポジション比率は 100% または 0% のいずれかであり、中間の状態はありません。トレーダー Operator は、基本的に、5 人のメンバーからなる投資委員会の投票に基づいてポジションを決定するトレーディング戦略を実行しています。各委員は(パラメーターが異なるため)独自の意見を持っていますが、最終的な決定は多数決によって決定されます。

op.set_blender('cmt_3_0(s0, s1, s2, s3, s4)')  # 将委员会混合函数设置为blender表达式
# 运行策略
res = qt.run(op, mode=1)

結果は、年率リターン6.43、シャープレシオ0.487となりました。

====================================
|                                  |
|         BACKTEST REPORT          |
|                                  |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 179.3 ms
time consumption for operation back testing:  3.2 ms
investment starts on      2016-04-05 15:00:00
ends on                   2021-01-29 15:00:00
Total looped periods:     4.8 years.
-------------operation summary:------------
Only non-empty shares are displayed, call 
"loop_result["oper_count"]" for complete operation summary
          Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH    10       9      19   57.2%     -0.0%     42.8%  

Total operation fee:     ¥      452.82
total investment amount: ¥  100,000.00
final value:              ¥  135,022.14
Total return:                    35.02% 
Avg Yearly return:                6.43%
Skewness:                         -0.74
Kurtosis:                         11.60
Benchmark return:                63.94% 
Benchmark Yearly return:         10.80%

------strategy loop_results indicators------ 
alpha:                           -0.034
Beta:                             1.001
Sharp ratio:                      0.487
Info ratio:                      -0.026
250 day volatility:               0.138
Max drawdown:                    22.60% 
    peak / valley:        2019-04-19 / 2020-07-24
    recovered on:         Not recovered!


==================END OF REPORT===================

png

お気づきかと思いますが、今回の出力は前回とは大きく異なっています。前回のバックテストでは、ポジション比率が徐々に変化しました (リターン チャートの背景にある緑の帯の陰影がポジション比率を表します)。一方、今回は黒か白か (全額投資かフラットのいずれか) で、取引数も大幅に減り、合計 9 回の買いと 10 回の売りだけです。取引ログを注意深く分析すると、3 つの取引戦略が全額投資に賛成票を投じた場合にのみ全額投資されることがわかります。残りの時間は平らなままです。したがって、一方向の下降市場では、株価曲線は直線になります。しかし、全額投資した場合、株価が下落した場合、ポジションを適切に削減しても損失を減らす方法はありません。

次に、私たちは依然としてこの委員会を使用していますが、現在、正職に 2 票が投じられている限り、最終的な職は正職となります。

第三の配合方法:委員会投票

3 番目のポートフォリオ構築方法: まだ委員会戦略ですが、完全に投資されたロング ポジションを出力するための投票しきい値が 2 票に変更されます。つまり、2 つの戦略がロングを出力する必要があると判断する限り、ロングを出力します。

op.set_blender('pos_2_0(s0, s1, s2, s3, s4)')
# 运行策略
res = qt.run(op, mode=1)

結果は以下の通りです:年率リターン8.46%、シャープレシオ0.612

====================================
|                                  |
|         BACKTEST REPORT          |
|                                  |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 180.0 ms
time consumption for operation back testing:  3.5 ms
investment starts on      2016-04-05 15:00:00
ends on                   2021-01-29 15:00:00
Total looped periods:     4.8 years.
-------------operation summary:------------
Only non-empty shares are displayed, call 
"loop_result["oper_count"]" for complete operation summary
          Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH    12       10     22   71.5%     -0.0%     28.5%  

Total operation fee:     ¥      548.27
total investment amount: ¥  100,000.00
final value:              ¥  147,914.95
Total return:                    47.91% 
Avg Yearly return:                8.46%
Skewness:                         -0.64
Kurtosis:                          8.61
Benchmark return:                63.94% 
Benchmark Yearly return:         10.80%

------strategy loop_results indicators------ 
alpha:                           -0.018
Beta:                             1.001
Sharp ratio:                      0.612
Info ratio:                      -0.018
250 day volatility:               0.154
Max drawdown:                    22.34% 
    peak / valley:        2019-04-19 / 2020-07-24
    recovered on:         Not recovered!


==================END OF REPORT===================

png

2 番目のチャートと 3 番目のチャートを比較すると、フル ポジションの間隔が明らかに長くなっていることがわかります。これは、フル ポジションを獲得するために以前は 3 票が必要だった戦略が、現在は 2 票のみで済むため、フル ポジションを達成するのが容易になっているためです。

8.4. 要約

さて、ここまでで、取引戦略をどのように組み合わせることができるかについて予備的な理解ができたはずです。私たちのチュートリアルは続きます: qteasy では、必要な取引戦略を実装するためのさらに多くの方法を提供します。実際、qteasy のコアは、高速バックテストと高速実行に役立つベクトル化された戦略エンジンとして設計されていますが、それでも十分な柔軟性が考慮されています。理論的には、想像できるあらゆる種類の取引戦略を実装できます。

一方、qteasy のバックテスト フレームワークは、非常に多くの特別な設計も行っており、「将来の機能」を取引戦略に不用意にインポートすることを完全に回避し、バックテスト中に取引戦略が完全に過去のデータに基づいていることを保証します。同時に、多くの前処理技術と JIT 技術を使用してカーネルの主要な関数をコンパイルし、C 言語と同等の実行速度を実現します。

ただし、理論的に無限の可能性のあるトレーディング戦略を実現するには、組み込みのトレーディング戦略と戦略ブレンディングだけを使用するだけでは十分ではない可能性があります。一部の特定の取引戦略、または一部の特に複雑な取引戦略は、組み込みの戦略ブレンディングでは作成できません。これには、qteasy が提供するStrategy 基本クラスを使用して、特定のルールに基づいてカスタム取引戦略を作成する必要があります。

qteasy チュートリアルの次のセクションでは、例を使用して、カスタム取引戦略の作成方法、戦略の基本パラメーターの定義方法、戦略に必要なデータ型の定義方法、取引シグナルを生成するロジックの設定方法を紹介します。