13. グリッドトレーディング戦略

参照元:docs/_joinquant_migration_source/Example_13_classic grid trading.ipynb 最初のMarkdownセル。

この戦略は古典的なグリッド取引戦略です。この戦略は、格力電器株 000651.SZ を対象に実施される。この戦略を初めて実行するときは、1000 株を購入して保持します。同時に、現在の買値(0.1元に四捨五入)がベンチマークグリッドとして設定され、グリッドサイズに応じて売りグリッドと買いグリッドが計算されます。次に、戦略は 5 分ごとに実行されます。株価が買いグリッドまたは売りグリッドに接触すると、取引シグナルが生成され、グリッドが更新されます。

例えば:

  • 現在のベンチマークグリッドが30元、グリッドサイズが0.5元、売りグリッドが30.5元、買いグリッドが29.5元であると仮定します。

  • 価格が30.5元の売りグリッドに接触すると、売りシグナルが生成され、200株が売却され、ベンチマークグリッドが30.5元に更新されます。同時に、新しい売りグリッド31元と買いグリッド30元が計算されます。

バックテスト対象: 000651.SZ グリー電器

バックテスト期間:2023年1月1日~2023年3月1日

戦略グリッドのパラメータは取引ごとに更新されるため、この戦略は段階的にバックテストすることしかできないことに注意してください。取引シグナルの生成を容易にするために、戦略では VS シグナル タイプを使用します。

import qteasy as qt
import pandas as pd
import numpy as np
from qteasy import Parameter, StgData


class GridTrade(qt.RuleIterator):

    def __init__(self):
        super().__init__(
            name='GridTrade',
            description='网格交易策略,价格触发网格后交易并更新基准网格',
            pars=[
                Parameter((0.2, 2.0), name='grid_size', par_type='float', value=0.5),
                Parameter((100, 1000), name='trade_batch', par_type='int', value=200),
                Parameter((0.0, 10000.0), name='base_grid', par_type='float', value=0.0),
            ],
            data_types=StgData('close', freq='5min', asset_type='ANY', window_length=60),
            use_latest_data_cycle=False,
        )

    def realize(self):

        # 读取当前保存的策略参数,首次运行时base_grid参数为0,此时买入1000股并设置当前价格为基准网格
        grid_size, trade_batch, base_grid = self.get_pars('grid_size', 'trade_batch', 'base_grid')

        # 读取最新价格
        price = self.get_data('close_ANY_5min')[-1]

        # 计算当前价格与当前网格的偏离程度,判断是否产生交易信号
        if base_grid <= 0.01:
            # 基准网格尚未设置,此时为首次运行,首次买入1000股并设置基准网格为当前价格(精确到0.1元)
            result = float(trade_batch * 5)
            base_grid = np.round(price / 0.1) * 0.1
        elif price - base_grid > grid_size:
            # 触及卖出网格线,产生卖出信号
            result = -float(trade_batch)  # 交易信号等于交易数量,必须使用VS信号类型
            # 重新计算基准网格
            base_grid += grid_size
        elif base_grid - price > grid_size:
            # 触及买入网格线,产生买入信号
            result = float(trade_batch)
            # 重新计算基准网格
            base_grid -= grid_size
        else:
            result = 0.0

        # 使用新的基准网格更新交易参数
        self.par_values = (grid_size, trade_batch, base_grid)

        return result

alpha = GridTrade()

op = qt.Operator(alpha, signal_type='VS')  # 交易信号等于交易数量,必须使用VS信号类型
op.op_type = 'stepwise'  # 需要动态更新策略参数,必须使用'stepwise'交易类型
res = qt.run(op, mode=1,
       asset_type='E',
       asset_pool='000651.SZ',
       benchmark_asset='000651.SZ',
       trade_batch_size=100,
       sell_batch_size=1,
       trade_log=True,
       invest_start='20230101',
       invest_end='20230301',
       backtest_price_adj='none',
      )
print()

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

     ====================================
     |                                  |
     |       BACK TESTING RESULT        |
     |                                  |
     ====================================

qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 0.0 ms
time consumption for operation back looping:  839.9 ms

investment starts on      2023-01-03 09:30:00
ends on                   2023-02-28 15:00:00
Total looped periods:     0.2 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
000651.SZ    13       8      21   93.0%      0.0%      7.0%   

Total operation fee:     ¥       63.36
total investment amount: ¥  100,000.00
final value:              ¥  104,070.64
Total return:                      inf% 
Avg Yearly return:                 inf%
Skewness:                          3.79
Kurtosis:                         52.19
Benchmark return:                 9.23% 
Benchmark Yearly return:         77.74%

------strategy loop_results indicators------ 
alpha:                              inf
Beta:                               inf
Sharp ratio:                       -inf
Info ratio:                       0.005
250 day volatility:               0.003
Max drawdown:                     0.80% 
    peak / valley:        2023-01-30 / 2023-02-06
    recovered on:         2023-02-20

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

png