資源の読み込みに... 荷物...

ダイナミック・グリッド・トレンドフォローする定量的な取引戦略

作者: リン・ハーンチャオチャン開催日:2024年3月22日 16:03:09
タグ:

img

概要

この戦略は,前もって設定された価格範囲内で複数のグリッドラインを分割し,価格がグリッドラインに当たると自動的にポジションを開き,販売時にポジションを閉じて,変動する市場から利益を得ること.同時に,この戦略は,グリッドラインの位置を動的に調整する機能も有し,最近の価格動向に応じてグリッドレイアウトを適応的に最適化することができます.

戦略原則

この戦略の基本原則は以下のとおりです.

  1. まず,グリッドの上下境界とグリッド線の数をユーザー設定に基づいて決定します.境界は固定値または最近の高低または移動平均値に基づいて自動的に計算できます.

  2. 定義された境界内では,価格範囲をいくつかのグリッドに分けます.グリッドラインは,購入または販売価格に対応します.

  3. 価格が各グリッドラインに達すると,グリッドラインに対応するポジションが既に保持されているかどうかをチェックします.そうでない場合は,ポジションを開いて購入し,そうであれば,ポジションを閉じて販売します.

  4. 比較的高い価格で販売し,低い価格で購入することで,価格は変動するときに戦略は継続的に利益を得ることができます.

  5. 同時に,ユーザが自動境界調整機能を有効にする場合,グリッドラインの位置は,グリッドレイアウトを最適化するために,最近の価格高値や低値,または設定された移動平均値に応じて適応的に調整されます.

この戦略は,上記の原則によって,変動する価格傾向において,自動的な低価格購入と高価格販売を実現し,傾向に応じて利益ポイントを調整し,全体的な収益を向上させることができます.

利点分析

このダイナミック・グリッド戦略には以下の利点があります.

  1. 高い適応性.パラメータ設定によって異なる市場や品種に適応し,変動する市場に適応できる.

  2. 高度な自動化.戦略は厳格な数学論理と明確なポジション開閉点に基づいているため,完全に自動化された取引を達成し,主観的な感情的干渉を減らすことができます.

  3. 制御可能なリスク ネットワークの数とネットワーク境界などのパラメータを設定することで,各取引のリスク露出は効果的に制御され,全体的なリスクは受け入れられる範囲内にとどまります

  4. トレンド適応性. ネットワークの境界を動的に調整する機能が戦略に追加されるため,グリッドは価格の動向を追及し,最適化され,トレンド市場の収益性を向上させる.

  5. 格子取引は基本的に価格変動の高い投下と低い吸い込みであるため,価格が変動を維持する限り,この戦略は利益を維持することができます.

リスク分析

この戦略には明らかな利点がありますが,いくつかのリスクもあります.

  1. トレンドリスク:価格が強烈な一方的なトレンドでグリッド境界を突破した場合,この戦略の利益空間は限られ,大きなリトラセシションに直面する可能性があります.

  2. パラメータ最適化の難しさ.この戦略にはグリッドの数,初期境界線,ダイナミック境界線パラメータなど,多くのパラメータがあります.異なるパラメータ組み合わせは戦略のパフォーマンスに大きな影響を与え,実際の最適化の難しさは小さくありません.

  3. 格子戦略は基本的に高頻度戦略であり,非常頻繁なポジションの開設と閉じる,これは取引コストの上昇と潜在的なスライドリスクを意味します.

  4. 市場状況に強い依存性.この戦略は変動する市場に強く依存する.価格が急激な一方的な傾向に入ると,この戦略は大きな引き下げに直面する可能性が高い.

これらのリスクを考えると,次の側面から改善が可能である. 戦略のスタートアップのフィルター条件としてトレンド判断指標を追加し,パラメータ検索スペースと方法を最適化し,ファンド管理とポジション制御ロジックを導入し,トレンドブレークスルー閉鎖ロジックを増やすなど. これらの最適化によって,この戦略の堅牢性と収益性がさらに向上することができます.

最適化方向

上記の分析に基づき,この戦略の最適化方向は主に以下の通りである.

  1. トレンドフィルタリング条件を導入する. 戦略開始前には,移動平均値,ADXなど,トレンド判断指標を追加する. 変動する市場条件でのみ戦略を開始し,トレンド市場のリトラセシオンリスクを効果的に避けるためにトレンド市場を監視する.

  2. パラメータ検索を最適化する.遺伝子アルゴリズム,粒子群アルゴリズムなど,グリッドパラメータを最適化するためのインテリジェントアルゴリズムを使用して,最適なパラメータ組み合わせを自動的に見つけ,最適化効率と品質を改善する.

  3. リスク制御ロジックを強化する.リスク管理ロジックを戦略に追加する.例えば,価格変動に応じてグリッド幅を動的に調整し,閉鎖を誘発する最大リトレースドレッシングを設定するなど,リスクをよりよく制御する.

  4. トレンドストップ・ロスを導入する.グリッド境界の一定のパーセントのようなトレンドブレークスルーストップ・ロスのラインを設定する.価格がストップ・ロスのラインを突破すると,トレンド市場の大きなリトレースを避けるためにすべてのポジションを閉じる.

  5. トランザクション実行を最適化.より高度なオーダータイプとオーダーアルゴリズムを採用し,トランザクションの頻度とコストを最小限に抑え,実行効率を向上させるなど,トランザクション実行リンクを最適化する.

上記の最適化により,この戦略の適応性,安定性,収益性が全面的に向上し,実際の取引ニーズに近づけることができます.

概要

一般的に,このダイナミックグリッドトレンドフォロー戦略は,グリッドトレード原理に基づく中高周波量的なトレード戦略であり,ダイナミックな調整とトレンド適応メカニズムを統合している.その利点は強い適応性,高度な自動化程度,制御可能なリスク,良いトレンド適応性,安定した勝利率にある.同時に,トレンドリスク,パラメータ最適化の困難,頻繁な取引,市場状況への強い依存などのリスクも備わっている.これらの問題を考慮して,トレンドフィルタリング,パラメータ最適化,リスク強化,トレンドストップ損失制御,取引最適化などの側面から改善を図ることができ,戦略の全体的なパフォーマンスを向上させる.

格子取引という考え自体は比較的成熟した実用的な定量的な方法である.この戦略に動的な最適化とトレンド適応メカニズムを追加することで,古典的な格子取引の利点が拡張され発展した.投資家に変動する市場で新しい定量的な取引のアイデアと可能性を提供している.さらなる最適化と改善により,この戦略は優れた中高周波定量的な取引ツールになると予想されている.


/*backtest
start: 2024-03-01 00:00:00
end: 2024-03-21 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("(IK) Grid Script", overlay=true, pyramiding=14, close_entries_rule="ANY", default_qty_type=strategy.cash, initial_capital=100.0, currency="USD", commission_type=strategy.commission.percent, commission_value=0.1)
i_autoBounds    = input(group="Grid Bounds", title="Use Auto Bounds?", defval=true, type=input.bool)                             // calculate upper and lower bound of the grid automatically? This will theorhetically be less profitable, but will certainly require less attention
i_boundSrc      = input(group="Grid Bounds", title="(Auto) Bound Source", defval="Hi & Low", options=["Hi & Low", "Average"])     // should bounds of the auto grid be calculated from recent High & Low, or from a Simple Moving Average
i_boundLookback = input(group="Grid Bounds", title="(Auto) Bound Lookback", defval=250, type=input.integer, maxval=500, minval=0) // when calculating auto grid bounds, how far back should we look for a High & Low, or what should the length be of our sma
i_boundDev      = input(group="Grid Bounds", title="(Auto) Bound Deviation", defval=0.10, type=input.float, maxval=1, minval=-1)  // if sourcing auto bounds from High & Low, this percentage will (positive) widen or (negative) narrow the bound limits. If sourcing from Average, this is the deviation (up and down) from the sma, and CANNOT be negative.
i_upperBound    = input(group="Grid Bounds", title="(Manual) Upper Boundry", defval=0.285, type=input.float)                      // for manual grid bounds only. The upperbound price of your grid
i_lowerBound    = input(group="Grid Bounds", title="(Manual) Lower Boundry", defval=0.225, type=input.float)                      // for manual grid bounds only. The lowerbound price of your grid.
i_gridQty       = input(group="Grid Lines",  title="Grid Line Quantity", defval=8, maxval=15, minval=3, type=input.integer)       // how many grid lines are in your grid

f_getGridBounds(_bs, _bl, _bd, _up) =>
    if _bs == "Hi & Low"
        _up ? highest(close, _bl) * (1 + _bd) : lowest(close, _bl)  * (1 - _bd)
    else
        avg = sma(close, _bl)
        _up ? avg * (1 + _bd) : avg * (1 - _bd)

f_buildGrid(_lb, _gw, _gq) =>
    gridArr = array.new_float(0)
    for i=0 to _gq-1
        array.push(gridArr, _lb+(_gw*i))
    gridArr

f_getNearGridLines(_gridArr, _price) =>
    arr = array.new_int(3)
    for i = 0 to array.size(_gridArr)-1
        if array.get(_gridArr, i) > _price
            array.set(arr, 0, i == array.size(_gridArr)-1 ? i : i+1)
            array.set(arr, 1, i == 0 ? i : i-1)
            break
    arr

var upperBound      = i_autoBounds ? f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, true) : i_upperBound  // upperbound of our grid
var lowerBound      = i_autoBounds ? f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, false) : i_lowerBound // lowerbound of our grid
var gridWidth       = (upperBound - lowerBound)/(i_gridQty-1)                                                       // space between lines in our grid
var gridLineArr     = f_buildGrid(lowerBound, gridWidth, i_gridQty)                                                 // an array of prices that correspond to our grid lines
var orderArr        = array.new_bool(i_gridQty, false)                                                              // a boolean array that indicates if there is an open order corresponding to each grid line

var closeLineArr    = f_getNearGridLines(gridLineArr, close)                                                        // for plotting purposes - an array of 2 indices that correspond to grid lines near price
var nearTopGridLine = array.get(closeLineArr, 0)                                                                    // for plotting purposes - the index (in our grid line array) of the closest grid line above current price
var nearBotGridLine = array.get(closeLineArr, 1)                                                                    // for plotting purposes - the index (in our grid line array) of the closest grid line below current price
strategy.initial_capital = 50000
for i = 0 to (array.size(gridLineArr) - 1)
    if close < array.get(gridLineArr, i) and not array.get(orderArr, i) and i < (array.size(gridLineArr) - 1)
        buyId = i
        array.set(orderArr, buyId, true)
        strategy.entry(id=tostring(buyId), long=true, qty=(strategy.initial_capital/(i_gridQty-1))/close, comment="#"+tostring(buyId))
    if close > array.get(gridLineArr, i) and i != 0
        if array.get(orderArr, i-1)
            sellId = i-1
            array.set(orderArr, sellId, false)
            strategy.close(id=tostring(sellId), comment="#"+tostring(sellId))

if i_autoBounds
    upperBound  := f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, true)
    lowerBound  := f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, false)
    gridWidth   := (upperBound - lowerBound)/(i_gridQty-1)
    gridLineArr := f_buildGrid(lowerBound, gridWidth, i_gridQty)

closeLineArr    := f_getNearGridLines(gridLineArr, close)
nearTopGridLine := array.get(closeLineArr, 0)
nearBotGridLine := array.get(closeLineArr, 1)







もっと