13. Klassische Grid-Trading-Strategie

Referenzquelle: docs/_joinquant_migration_source/Example_13_classic grid trading.ipynb Erste Markdown-Zelle.

Diese Strategie ist eine klassische Grid-Trading-Strategie. Die Zielaktie ist Gree Electric Appliances (000651.SZ). Beim ersten Durchlauf werden 1000 Aktien gekauft und gehalten. Der aktuelle Kaufpreis (gerundet auf 0,1 Yuan) dient als Basis-Grid. Die Kauf- und Verkaufs-Grids werden anhand dieser Grid-Größe berechnet. Die Strategie wird alle 5 Minuten ausgeführt. Sobald der Aktienkurs das Kauf- oder Verkaufs-Grid erreicht, wird ein Handelssignal generiert und das Grid aktualisiert.

Beispiel:

  • Unter der Annahme, dass der aktuelle Basispreis 30 Yuan beträgt, die Rastergröße 0,5 Yuan, der Verkaufspreis 30,5 Yuan und der Kaufpreis 29,5 Yuan beträgt.

  • Sobald der Kurs die Verkaufsgrenze von 30,5 Yuan erreicht, wird ein Verkaufssignal generiert, 200 Aktien werden verkauft und die Basisgrenze wird auf 30,5 Yuan aktualisiert. Gleichzeitig werden eine neue Verkaufsgrenze von 31 Yuan und eine Kaufgrenze von 30 Yuan berechnet.

Die für das Backtesting verwendete Aktie ist: 000651.SZ Gree Electric Appliances.

Der Backtesting-Zeitraum erstreckt sich vom 1. Januar 2023 bis zum 1. März 2023.

Da die Parameter des Strategierasters nach jedem Trade aktualisiert werden, kann diese Strategie nur schrittweise getestet werden. Zur Generierung von Handelssignalen verwendet diese Strategie den Signaltyp 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()

Die Ergebnisse des Backtests lauten wie folgt:

     ====================================
     |                                  |
     |       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