9. qteasy のカスタム戦略

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

  • 財務データの取得、クリーニング、保管、処理、可視化、および使用

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

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

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

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

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

9.1. 始める前に

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

QTEASY ドキュメント では、組み込み取引戦略の使用、カスタム戦略の作成などに関する詳細情報を見つけることができます。 qteasy の基本的な使用法に慣れていない場合は、そこにアクセスして詳細な手順を参照してください。

9.2. この章の対象

qteasyのカーネルは高速性と高速性を両立するフレームワークとして設計されています

一方、qteasy のバックテスト フレームワークも、トレーディング戦略に不用意に「将来の関数」をインポートすることを完全に回避するように特別に設計されており、バックテスト中にトレーディング戦略が完全に過去のデータに基づいていることを保証します。また、多くの前処理技術と JIT テクノロジを使用してカーネルの主要な関数をコンパイルし、C に匹敵する実行速度を実現します。

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

この章では、qteasyの取引戦略基本クラスを紹介し、これらの基本クラスに基づいて自分だけの取引戦略を作成する方法を、いくつかの具体例を通して詳しく説明します。進歩的にするために、比較的単純な例から始めます。

9.3. カスタム戦略を構築する

クオンツ取引のワークフローでは、取引戦略は実際には、既知の情報を入力として受け取り、一連の論理的演繹を通じて取引の決定を出力する関数です。専門学校、トレードス​​タイル、分析手法に関係なく、トレード戦略の最も基本的な定義はこれです。

在此処插入图片描写

例えば:

  • テクニカル アナリストは、過去の株価 (入力データ) を使用してテクニカル指標 (論理的推論) を計算し、売買の決定 (取引の決定) を行います。

  • バリュー投資家は、上場企業のさまざまな指標 (入力データ) を使用して、企業の成長可能性を分析し (論理的演繹)、どの銘柄を売買するかを決定します (取引上の決定)。

  • マクロアナリストは、たとえ株価に興味がなくても、話題のニュースや市場センチメント(入力データ)を参照し、市場全体の傾向を分析(論理的演繹)し、市場に参入するかどうかを決定(取引判断)する必要があります。

  • 高頻度または超高頻度の裁定取引では、短期的な価格のリアルタイムの変化 (入力データ)、裁定領域のサイズの分析 (論理的推論)、およびオペレーションへの迅速な介入 (取引の決定) も必要です。

トレーディング戦略が少数の投資商品を高頻度で追跡する場合、それは「タイミングトレーディング戦略」と呼ばれます。低頻度で多数の投資商品を追跡する場合、それは「銘柄選択戦略」と呼ばれます。

つまり、すべてのクオンツ取引は、定期的に実行される一連の論理演繹であり、実行されるたびに入力として最新のデータが抽出され、一連の取引決定が出力されます*。このように繰り返し実行することで、安定した取引操作の流れが形成されますが、これは取引戦略の抽象的な概念にすぎません。

9.4. qteasyStrategy 戦略クラスを使用する

qteasy 取引戦略は上記の概念に基づいて定義されます。 qteasy によって定義された戦略クラスは、データと取引ロジックのキャリアです。 Strategy クラスを継承し、独自の戦略クラスを定義し、戦略に必要なデータとこのクラス内で戦略の実装ロジックを指定することで、カスタム取引戦略を作成できます。

したがって、qteasy の設計では、取引戦略には次の 4 つの核となる要素が含まれます。

戦略と戦略グループの実行タイミング

  • 戦略の実行タイミング —— 戦略がいつ実行されるか、および実行される頻度は戦略グループによって決定されます。 Operator に戦略を追加する場合、パラメーター run_freq および run_timing を指定できます。これら 2 つのパラメータを組み合わせることで、戦略の実行タイミングが決まります。

戦略の調整可能なパラメーターと履歴データ

qteasy の取引戦略には、調整可能なパラメーターという特別な設計もあります。調整可能なパラメータは、移動平均期間、銘柄選択ランキングの銘柄数など、戦略の実行中に継続的に調整されるパラメータです。これらのパラメータは戦略のパフォーマンスに直接影響するため、パラメータを調整して最適なパラメータの組み合わせを見つけ、それによって最高のパフォーマンスを達成したいと考えています。 qteasy は、調整可能なパラメーターを定義するための非常に便利なインターフェイスを提供します。ユーザーは、ストラテジーの属性に任意の数の調整可能なパラメーターを定義し、各調整可能なパラメーターの名前、値の範囲、データ型などを指定できます。これらの定義された調整可能なパラメーターは自動的に戦略実装関数に渡され、ユーザーはこれらのパラメーターを直接使用して取引ロジックを実装できます。

  • 戦略の調整可能なパラメータ — 移動平均期間、銘柄選択ランキングの銘柄数など、戦略で調整する必要があるパラメータ。これらのパラメータは戦略のパフォーマンスに直接影響するため、パラメータを調整して最適なパラメータの組み合わせを見つけ、それによって最高のパフォーマンスを達成したいと考えています。 qteasy は、調整可能なパラメーターを定義するための非常に便利なインターフェース Parameters を提供します。ユーザーは、ストラテジーの属性に任意の数の調整可能なパラメーターを定義し、各調整可能なパラメーターの名前、値の範囲、データ型などを指定できます。これらの定義された調整可能なパラメーターは自動的に戦略実装関数に渡され、ユーザーはこれらのパラメーターを直接使用して取引ロジックを実装できます。

戦略とその実行ロジックに必要なデータ

  • 戦略に必要なデータ — 戦略に必要なデータ入力。たとえば、過去 10 日間の毎日のローソク足 (K ライン) データが必要ですか、それとも過去 1 年間の PER が必要ですか?戦略に必要なデータの量は、Strategy.data_types 属性を介して完全に自由に定義できます。ユーザーは、qt.StgData() オブジェクトを使用して、あらゆる種類のデータ入力を定義できます。データ頻度とウィンドウの長さは両方とも戦略属性を介して完全に自由に定義でき、qteasy はこれらの定義に従ってデータを自動的にパッケージ化し、戦略の実装関数にフィードします。

  • 戦略実行ロジック —— 戦略の実装ロジックは、Strategy.realize() メソッドをオーバーライドすることで実現されます。ユーザーは入力データを使用して取引シグナルを生成する方法を自由に定義できます。

戦略の出力シグナル

qteasy を使用すると、ユーザーはさまざまなタイプの取引シグナルを定義できます: PT PS VS など。ユーザーは、さまざまなタイプの取引戦略を実装する必要に応じて、さまざまなタイプの取引シグナルを選択できます。売買シグナルの意味を以下に簡単に説明します。さまざまな種類の取引シグナルの詳細については、取引シグナル を参照してください。

  • PT タイプの信号 —— 位置のパーセンテージを表します。出力は 0 ~ 1 の値で、保持するポジションの割合を示します。たとえば、出力 0.5 はポジションの 50% を保持することを意味します。 0 は何も保持しないことを意味します。 1 は全額投資を意味します。

  • PS シグナル — 取引パーセンテージを表します。出力は -1 ~ 1 の値で、売買するポジションの割合を示します。たとえば、出力 0.5 はポジションの 50% を買うことを意味し、-0.5 はポジションの 50% を売ることを意味し、0 はアクションがないことを意味します。

  • VS 型シグナル —— 取引数量を表します。出力数は売買する株数を示します。たとえば、500 は 500 株を買うことを意味し、-300 は 300 株を売ることを意味します。

上記の戦略に関連する情報を除き、他のすべての作業は qteasy によって実行され、すべての取引データは戦略属性に従って ndarray 配列に自動的にパッケージ化され、簡単に抽出して使用できます。同じ取引戦略は、ライブ操作中に取引データを自動的に抽出し、定義された戦略に従って取引シグナルを生成し、バックテスト中に履歴データを自動的に抽出し、履歴データスライスを生成しますが、将来の機能は形成されません。同時に、すべての取引データが

したがって、qteasy での戦略のカスタマイズは非常に簡単です。

  • __init__() このメソッドでは、ストラテジーの名前、説明、そして最も重要な調整可能なパラメーター、データ型などを含む、ストラテジーのすべてのパラメーターを定義します。これらのパラメーターは、qteasy によって自動的に認識され、ストラテジーの実行時に直接使用できます。

  • realize() このメソッドで戦略の実行ロジックを定義します。履歴データを抽出し、データに基づいて取引シグナルを生成します。

ここに画像の説明を挿入

カスタム戦略には、上記の戦略属性に加えて、調整可能なパラメーターなど、組み込み取引戦略と同じ基本属性もあります。これらは組み込み取引戦略のものと同じであるため、ここでは繰り返しません。

9.5. 3 つの異なるカスタム戦略基本クラスがあります

qteasy では 3 つの異なる戦略クラスが提供されており、ユーザーがさまざまな状況に合わせてカスタム戦略を作成しやすくなっています。

  • GeneralStg: 一般取引戦略クラス。ユーザーは、realize() メソッドですべての取引資産に対する取引決定シグナルを提供する必要があります。

  • FactorSorter: ファクター銘柄選択クラス。ユーザーはrealize() メソッドで銘柄選択ファクターを定義するだけでよく、オブジェクト属性を通じて複数の銘柄選択アクションを実装できます。

  • RuleIterator: ルール反復子クラス。ユーザーは銘柄選択ルールまたは銘柄のタイミング ルールを定義するだけでよく、同じルールがすべての銘柄に周期的に適用され、異なる銘柄は異なるパラメータを定義できます。

3 つのトレーディング戦略基本クラスはまったく同じ属性とメソッドを持ちます。唯一の違いは、realize() メソッドの定義です。

ここで、いくつかの進歩的な例を通してカスタム戦略を作成する方法を学びましょう。

9.6. 二重移動平均タイミング取引戦略を定義する

最初の例は、最も単純な二重移動平均タイミング トレーディング戦略であり、最も古典的なタイミング トレーディング戦略です。この移動平均タイミング戦略には 2 つの調整可能なパラメータがあります。

  • FMA 高速移動平均期間

  • SMA 低速移動平均期間 この戦略は、過去の期間の終値に基づいて、上記 2 つの期間によって生成される単純移動平均を計算します。 2 つの移動平均が交差すると、取引シグナルが生成されます。

  • 高速移動平均が上限を下から上に超えると、完全な買いシグナルが発行されます。

  • 高速移動平均が上限を上から下まで横切ると、完全な売りシグナルが発行されます。

ここに画像の説明を挿入

この戦略のロジックは非常にシンプルです。では、この戦略をどのように定義すればよいのでしょうか?まず、どのタイプの取引戦略基本クラスを使用するかを決定する必要があります。多くの場合、3 つの取引戦略基本クラスをすべて使用して同じ取引戦略を生成できますが、一部の基本クラスは特定のタイプの戦略に対して事前に定義を行っており、これにより戦略のコードがさらに簡素化されます。この戦略は典型的なタイミング戦略であり、異なる投資商品に同じルールを適用する戦略タイプであるため、RuleIterator 戦略クラスを使用して戦略を確立できます。次の例では、他の 2 つの戦略クラスについて説明します。

ここで、この戦略の 3 つの主要な要素を明確にしましょう。

  • 戦略のタイミング —— 簡単にするために、この戦略は毎日の終わりに実行されると定義します。

  • 戦略に必要なデータ ——2 つの移動平均を計算するには、戦略を実行するたびに過去の終値 (“close”) が必要です。また、SMA 低速移動平均を計算するには、少なくとも SMA 日分の履歴データが必要です。

  • 戦略のロジック ——終値を抽出した後、まず 2 つの移動平均を計算し、次に直近の日の移動平均が上下にクロスしたかどうかを判断します。具体的には、昨日と今日の2つの移動平均価格の相対関係を比較することです。昨日の SMA が FMA よりも大きく、今日の SMA が FMA よりも小さい場合、それは FMA が SMA を下からクロスしたことを意味し、完全な買いシグナルが生成されるはずです。このシグナルは 1 です。状況がまったく逆の場合は、完全売りシグナル -1 が出力されます。それ以外の場合は 0 が出力され、売買シグナルはありません。

上記の準備ができたら、ストラテジ コードがどのように定義されるかを見てみましょう。基本的な戦略コードの最初のステップは、戦略基本クラス (ここでは RuleIterator) を継承し、カスタム クラスを作成することです。

from qteasy import RuleIterator
from qteasy import Parameter, StgData

class Cross_SMA(RuleIterator):

    # 策略的属性定义在__init__()方法中
    def __init__(self):
        super().__init__(
        )

    # 策略的具体实现代码写在策略的realize()函数中
    def realize(self):
        """策略的具体实现代码:
        """
        pass

OK、上記の数行のコードは、最初のカスタム取引戦略のフレームワーク全体です。このフレームワークで属性を入力しロジックを補足すると、完全な取引戦略が完成します。やり方は?まず、この戦略の最も基本的な属性 (名前、説明、調整可能なパラメーター) を定義します。

名前と説明は両方とも戦略に関する情報であり、後で呼び出すときに戦略の目的を理解するのに便利です。好みに応じてそれらを定義できます。より重要な属性は、調整可能なパラメーターです。

このカスタム戦略では、高速移動平均と低速移動平均の計算パラメーターを調整できるようにしたいと考えています。これら 2 つのパラメーターは高速移動平均と低速移動平均の特定の位置に直接影響し、2 つの移動平均の交点に直接影響し、異なる買いポイントと売りポイントを形成します。次の 2 つの図を参照してください。これらの図は、同じ銘柄の異なる速度移動平均の交差を同時に示しています。移動平均の計算期間が異なると、発生する買いポイントと売りポイントが全く異なります。

ここに画像の説明を挿入 上図の移動平均期間は 15 日/40 日で、3 つの買いシグナルと 2 つの売りシグナルを生成します。 ここに画像の説明を挿入 上図の移動平均期間は 5 日/50 日で、2 つの買いシグナルと 1 つの売りシグナルを生成します

移動平均期間はストラテジーのパフォーマンスに直接影響するため、当然のことながら、ストラテジーのパフォーマンスを最高にするための移動平均期間の最適な組み合わせ (パラメーターの組み合わせ) を見つけたいと考えます。この目標を達成するために、qteasy では、ユーザーがこれらのパラメーターを「調整可能なパラメーター」として定義できるようにし、最適なパラメーターを見つけるための最適化アルゴリズムを提供します。すべての組み込み取引戦略では、調整可能なパラメーターの数と意味が定義されており、ユーザーが変更することはできません。ただし、カスタム戦略では、ユーザーには大きな自由があります。理論的には、戦略実行プロセスで使用される変数はどれも、調整可能なパラメーターとして定義できます。

ここでは、高速移動平均と低速移動平均の期間を調整可能なパラメーターとして定義し、次のように戦略属性で定義します。

ストラテジーの調整可能なパラメーターは、Parameter オブジェクトを使用して定義されます。これらのオブジェクトを使用して、各調整可能なパラメーターの名前、値の範囲、データ型などを指定できます。これらの定義された調整可能なパラメーターは戦略実装関数に自動的に渡され、ユーザーはそれらを直接使用して取引ロジックを実装できます。

pars=[Parameter((10, 100), data_type='int', name='fast', value=30),
      Parameter((10, 100), data_type='int', name='slow', value=60)],  # 策略默认参数是快均线周期30, 慢均线周期60

戦略に必要なデータを定義する

戦略に必要なデータは、StgData オブジェクトによって決まります。 qteasy では、各データ型オブジェクトは一意の ID、データ頻度、および資産タイプによって識別できます。データ ウィンドウの長さを指定することもできます。

データが定義されると、qteasy はウィンドウ内のデータを自動的にパッケージ化し、戦略 realize() 関数に送信します。バックテスト中にすべての履歴データが同じルールに従って一連のデータ ウィンドウにパッケージ化される場合、realize() 関数によって受信される履歴データの形式と処理方法は完全に同じになり、ライブ操作とバックテスト操作の一貫性が確保され、バックテスト中に発生する可能性のある将来の機能も回避されます。

ここに画像の説明を挿入

StgData データ型の定義は次のとおりです。過去 201 日間の毎日の終値が必要です。 201 日分の終値が必要な理由は、調整可能なパラメーターの最大範囲を 200 と定義したためです。期間 200 の移動平均を計算するには、201 日分の終値が必要です。

data_types=[StgType('close', asset_type='ANY', freq='d', window_length=201)]  # 策略基于收盘价计算均线,因此数据类型为'close',历史数据的频率为日,历史数据窗口长度为201,每一次交易信号都是由它之前前201天的历史数据决定的

上記で定義されたデータ型に基づいて、qteasy はこの戦略に一意の ID close_ANY_d を割り当てます。この ID を使用すると、戦略実装機能で履歴データを取得できます。履歴データを取得する方法については後ほど紹介します。

これで、カスタム取引戦略の重要な属性がすべて定義されました。次に、戦略の実装を定義します。

カスタム取引戦略の実現: realize()

realize() メソッドでは、3 つのことを行う必要があり、それらを 1 つずつ解決します。

  • 履歴データの取得

  • 調整可能なパラメータを取得する

  • アルゴリズムを作成し、出力を定義する

履歴データと調整可能なパラメータ値を取得します。

前述したように、この戦略の調整可能なパラメーターは移動平均のルックバック期間です。したがって、調整可能パラメーターを計算期間として使用するには、調整可能パラメーターの値と特定の履歴データを取得する必要があります。

realize() メソッドでは、調整可能なパラメーターと履歴データを非常に簡単に取得できます。それぞれ self.get_data()self.get_pars() を使用します。どちらの方法でも、複数のデータ系列またはパラメータを一度に取得できます。取得された値は tuple に解凍され、ユーザーはこれを直接使用できます。

def realize(self):
    """策略的具体实现代码
    """
    close = self.get_data('close_ANY_d')  # 通过数据ID获取数据:最近201天的收盘价
    f, s = self.get_pars('fast', 'slow')  # 读取快均线(fast)和慢均线(slow)的计算周期

これで、戦略ロジックの実装に必要な要素がすべて準備できたので、戦略ロジックの実装を開始できます。

まず、2 セットの移動平均を計算する必要があります。ユーザーがta-lib ライブラリをインストールしている場合は、ta-libSMA 関数を直接呼び出して移動平均を計算できます。インストールされていない場合でも、大きな問題はありません。qteasy は、SMA 関数の ta-lib フリー バージョンを提供しており (すべてのテクニカル指標に ta-lib フリー バージョンがあるわけではありません。詳細については、リファレンス ドキュメント を参照してください)。これは、直接インポートして使用できます。

def realize(self, h, **kwargs):
    """策略的具体实现代码
    """
    ...
    from qteasy.tafuncs import sma
    # 使用qt.sma计算简单移动平均价
    s_ma = sma(close, s)
    f_ma = sma(close, f)
    # 为了考察两条均线的交叉, 计算两根均线昨日和今日的值,以便判断
    s_today, s_last = s_ma[-1], s_ma[-2]
    f_today, f_last = f_ma[-1], f_ma[-2]

移動平均を計算すると、realize メソッドで戦略の出力、つまり取引の決定を直接定義できます。

RuleIterator クラス戦略の場合、戦略が同時に動作する銘柄の数に関係なく、定義する必要があるのは「ルール反復」と呼ばれる 1 セットのルールのみであるため、取引の決定を表す数値を出力するだけで済みます。この番号は、qteasy によって異なる取引注文に自動的に変換されます。変換ルールは、Operator オブジェクトの動作モードによって決まります。これについては前のチュートリアルで紹介されているため、ここでは繰り返しません。

この例では、トレーディング戦略によって出力されるシグナルが、投資商品に投資する総資産の割合を表すように計画しています。次に、買うべき日に取引シグナル「1」を生成し、売るべき日に取引シグナル「-1」を生成し、取引したくない場合は「0」を出力するだけです。

def realize(self, h, **kwargs):
    """策略的具体实现代码
    """
    ...
    if (f_last < s_last) and (f_today > s_today):  
        # 当快均线自下而上穿过上边界(即昨日快均线低于慢均线,而今天高于于慢均线),发出全仓买入信号
        return 1
    elif (f_last > s_last) and (f_today < s_today): 
        # 当快均线自上而下穿过上边界(即昨日快均线高于慢均线,而今天低于于慢均线),发出全部卖出信号
        return -1
    else:  # 其余情况不产生任何信号
        return 0

これで、戦略の定義が完了しました。 qteasy はすべての複雑な作業を舞台裏で完了し、ユーザーは戦略のデータとロジックの定義を解決することに集中するだけで済みます。完全なコードは次のとおりです (スペースを節約するために、すべてのコメントは削除されています)。

from qteasy import RuleIterator, Parameter, StgData
from qteasy.tafuncs import sma
# 创建双均线交易策略类
class Cross_SMA_PS(RuleIterator):
    def __init__(self):
        super().__init__(
            name='CROSSLINE',  # 策略的名称
            description='快慢双均线择时策略',  # 策略的描述
            pars=[Parameter((10, 100), par_type='int', name='fast', value=30),
                  Parameter((10, 100), par_type='int', name='slow', value=60)],
            data_types=[StgData('close', freq='d', asset_type='ANY', window_length=201)],
        )

    def realize(self):
        
        close = self.get_data('close_ANY_d')  # 通过数据ID获取数据:最近201天的收盘价
        f, s = self.get_pars('fast', 'slow')  # 读取快均线(fast)和慢均线(slow)的计算周期
        
        # 使用qt.sma计算简单移动平均价
        s_ma = sma(close, s)
        f_ma = sma(close, f)
        # 为了考察两条均线的交叉, 计算两根均线昨日和今日的值,以便判断
        s_today, s_last = s_ma[-1], s_ma[-2]
        f_today, f_last = f_ma[-1], f_ma[-2]
        
        if (f_last < s_last) and (f_today > s_today):  
            # 当快均线自下而上穿过上边界(即昨日快均线低于慢均线,而今天高于于慢均线),发出全仓买入信号
            return 1
        elif (f_last > s_last) and (f_today < s_today): 
            # 当快均线自上而下穿过上边界(即昨日快均线高于慢均线,而今天低于于慢均线),发出全部卖出信号
            return -1
        else:  # 其余情况不产生任何信号
            return 0

次に、このカスタム戦略を組み込みの取引戦略と同じように使用できます。

新しい Operator オブジェクトを作成する必要があります。その作成時に、作成したばかりの Cross_SMA ストラテジを Operator に追加し、このストラテジの信号タイプを PS として指定します。これは、Operator に、PS ルールを使用して取引戦略によって生成されたシグナルを解釈するように指示します。

op = qt.Operator(strategies=[Cross_SMA_PS()], signal_type='PS')

この戦略のバックテスト結果を見てみましょう。

最初の戦略のバックテスト結果

戦略のバックテストのパラメーター設定は、組み込みの取引戦略の場合とまったく同じです。

op = qt.Operator([Cross_SMA_PS()], signal_type='PS')

# 设置op的策略参数
op.set_parameter(0, 
                 par_values= (20, 60)  # 设置快慢均线周期分别为20天、60天
                )

# 设置基本回测参数,开始运行模拟交易回测
res = qt.run(op, 
             mode=1,  # 运行模式为回测模式
             asset_pool='000300.SH',  # 投资标的为000300.SH即沪深300指数
             invest_start='20110101',  # 回测开始日期
             invest_end='20191231', # 回测结束日期
             visual=True  # 生成交易回测结果分析图
            )

バックテストの結果は以下の通りです。

ここに画像の説明を挿入

ここで、戦略の調整可能なパラメーターを変更して、バックテストを再度実行してみます。バックテストの間隔は前回と同じです。

op.set_parameter(0, 
                 par_values= (25, 166)  # 设置快慢均线周期分别为25天、166天
                )

# 设置基本回测参数,开始运行模拟交易回测,回测参数完全一样
res = qt.run(op, 
             mode=1,  # 运行模式为回测模式
             asset_pool='000300.SH',  # 投资标的为000300.SH即沪深300指数
             invest_start='20110101',  # 回测开始日期
             visual=True  # 生成交易回测结果分析图
            )

ご覧のとおり、パラメーターを変更した後、戦略のバックテスト結果が大幅に変化しました。戦略パラメーターを最適化する方法については、このチュートリアルの次の章を参照してください。

====================================
|                                  |
|         BACKTEST REPORT          |
|                                  |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 111.0 ms
time consumption for operation back testing:  2.1 ms
investment starts on      2011-01-04 15:00:00
ends on                   2019-12-30 15:00:00
Total looped periods:     9.0 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    6        7      13   46.8%     -0.0%     53.2%  

Total operation fee:     ¥      283.00
total investment amount: ¥  100,000.00
final value:              ¥  180,675.40
Total return:                    80.68% 
Avg Yearly return:                6.80%
Skewness:                         -1.01
Kurtosis:                         17.32
Benchmark return:                27.96% 
Benchmark Yearly return:          2.78%

------strategy loop_results indicators------ 
alpha:                           -1.011
Beta:                            -4.128
Sharp ratio:                      0.368
Info ratio:                       0.009
250 day volatility:               0.134
Max drawdown:                    31.58% 
    peak / valley:        2015-06-08 / 2015-07-08
    recovered on:         2018-01-22

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

ここに画像の説明を挿入

この時点で、簡単なカスタム タイミング取引戦略を実装しました。では、他の 2 つの戦略クラスはどのように実装すればよいでしょうか?次の章では、さらに多くの例を使用して説明します。

9.7. 要約

このセクションでは、qteasy における取引戦略の抽象的な定義について学び、取引戦略に含まれる基本要素とその定義方法を理解し、最も単純な例を通じてカスタムの双対移動平均取引戦略を作成しました。

次のステップとして、引き続きカスタム取引戦略を導入していきます。関連コンテンツが多いため、カスタム取引戦略に関連するチュートリアルは 3 章を占めます。次の章では、他の 2 つのカスタム戦略基本クラス (FactorSorter ファクター銘柄選択基本クラスと GeneralStg 一般戦略基本クラス) を使用してトレーディング戦略を作成する方法を学びます。次に、別の章を使用して、より複雑なカスタム取引戦略を紹介し、qteasy の柔軟性を示します。次のセクションでお会いしましょう!