Une stratégie de grille dynamique adaptative à court terme basée sur

Auteur:ChaoZhang est là., Date: 2024-03-19 14:19:12 Les résultats de l'enquête
Les étiquettes:

img

Résumé

Il s'agit d'une stratégie de trading de grille dynamique adaptative à court terme basée sur Pine Script. L'idée de base de cette stratégie est de calculer automatiquement les limites supérieures et inférieures d'une grille en fonction des hauts et des bas des prix récents ou d'une moyenne mobile simple, puis de diviser cette plage uniformément en plusieurs lignes de grille. Lorsque le prix atteint une certaine ligne de grille, il ouvrira une position longue ou fermera une position à ce niveau. De cette façon, la stratégie peut ouvrir et fermer continuellement des positions dans un marché de plage pour capturer l'écart de prix. En même temps, en ajustant dynamiquement les limites de la grille, elle peut également s'adapter à différentes tendances du marché.

Principes de stratégie

  1. Calculer les limites de la grille. Selon le choix de l'utilisateur, les limites peuvent être calculées à partir des points les plus élevés et les plus bas des bougies N récentes, avec la possibilité d'élargir ou de réduire la plage d'un pourcentage; ou elles peuvent être basées sur la moyenne mobile simple des prix de clôture des bougies N récentes, avec la possibilité de définir les ratios d'écart vers le haut et vers le bas.

  2. Selon le nombre de lignes de grille, divisez la plage de grille uniformément pour générer un tableau des prix des lignes de grille.

  3. Si le prix de clôture actuel est inférieur à un prix de ligne de grille et qu'il n'y a pas de position sur cette ligne de grille, ouvrez une position longue à ce niveau. De cette façon, lorsque le prix atteint des lignes de grille plus élevées, il continuera à ajouter des positions.

  4. Si le prix de clôture actuel est supérieur à un prix de la ligne de la grille et qu'il y a une position sur la ligne de la grille ci-dessous, fermez la position longue sur la ligne de la grille inférieure. De cette façon, lorsque le prix baisse, il continuera à réduire les positions.

  5. Si la fonction de grille dynamique est sélectionnée, les limites supérieures et inférieures de la grille et le tableau des lignes de grille seront recalculés sur chaque bougie, de sorte que la grille puisse constamment s'adapter aux changements du marché.

Analyse des avantages

  1. Une grande adaptabilité. La stratégie de négociation de la grille peut s'adapter à la fois aux marchés de plage et de tendance. Dans un marché de plage, la stratégie de la grille peut ouvrir et fermer en permanence des positions pour gagner l'écart de prix; dans un marché de tendance, parce que la grille suit le mouvement des prix, elle peut également maintenir une certaine position pour obtenir des gains de tendance.

  2. La taille de la position de chaque ouverture est déterminée par le nombre de grilles, de sorte que l'exposition au risque unique est faible et contrôlable.

  3. Cette stratégie peut fonctionner entièrement automatiquement sans intervention manuelle, ce qui convient aux investisseurs qui ont besoin de rendements stables à long terme.

  4. Paramètres flexibles: les utilisateurs peuvent régler de manière flexible le nombre de lignes de réseau, les paramètres de réseau dynamique, etc. en fonction des caractéristiques du marché afin d'optimiser les performances de la stratégie.

Analyse des risques

  1. Risque de cygne noir. En cas de crash du marché extrême, si le prix baisse directement en dessous de la ligne de grille la plus basse, la stratégie sera pleinement positionnée et fera face à un plus grand retrait. Pour réduire ce risque, une condition de stop-loss peut être définie pour fermer toutes les positions une fois que la perte atteint un seuil.

  2. Si la densité de la grille est trop élevée, l'écart entre l'ouverture et la fermeture sera très faible et les coûts de transaction peuvent éroder la plupart des gains. Si la largeur de la grille est trop grande, le ratio d'ouverture unique est élevé et l'exposition au risque est grande. Les caractéristiques de l'actif sous-jacent doivent être soigneusement évaluées pour sélectionner les paramètres de la grille appropriés.

  3. Risque de base. Cette stratégie définit les conditions d'ouverture et de clôture en fonction du prix actuel. Dans les marchés tels que les contrats à terme, si le prix du contrat diffère considérablement du prix sous-jacent, les prix d'ouverture et de clôture réels peuvent différer considérablement des attentes.

Directions d'optimisation

  1. Ajouter un filtre de tendance. Les stratégies de grille ne fonctionnent pas bien sur les marchés à tendance unilatérale. Les indicateurs de tendance peuvent être ajoutés comme filtre, par exemple en activant uniquement la grille lorsque l'ADX est en dessous d'un seuil, et en fermant la grille lorsque la tendance est évidente, en tenant uniquement des positions unilatérales.

  2. Optimisation du signal. D'autres signaux peuvent être superposés sur la base de la grille, tels que la grille + moyenne mobile, c'est-à-dire que l'ouverture et la fermeture sont principalement déterminées par la grille, mais seulement des positions ouvertes lorsque le prix franchit une certaine moyenne mobile, sinon ne pas ouvrir de positions. Cela peut réduire le coût d'ouverture et de fermeture fréquentes.

  3. Gestion de la position. Actuellement, la position de chaque grille dans la stratégie est fixe. Elle peut être réglée de manière à réduire de manière appropriée la position de chaque grille lorsque le prix est éloigné du prix moyen du marché et à augmenter la position lorsqu'elle est proche du prix moyen du marché pour améliorer l'efficacité de l'utilisation du capital.

  4. Densité de grille adaptative. Ajustez dynamiquement la densité de grille en fonction de la volatilité des prix. Lorsque la volatilité est élevée, le nombre de grilles peut être augmenté de manière appropriée; lorsque la volatilité est faible, le nombre de grilles peut être réduit. Cela peut optimiser la largeur du réseau et améliorer l'utilisation du capital.

Résumé

Grâce à des grilles dynamiques adaptatives, cette stratégie peut fréquemment ouvrir et fermer des positions pour gagner des spreads de prix sur les marchés en marge, et peut également maintenir un certain degré de direction d'exposition sur les marchés tendance pour obtenir des gains de tendance. Il s'agit d'une stratégie quantitative à moyen et long terme avec une forte adaptabilité. En définissant raisonnablement la grille déclenchant la logique et la gestion des positions, des rendements stables peuvent être obtenus. Cependant, il est nécessaire de prêter attention aux risques de conditions de marché extrêmes et d'écart de prix, ce qui nécessite de définir des conditions d'arrêt-perte appropriées à contrôler. En outre, il y a encore une marge d'optimisation dans la définition des paramètres et la gestion des risques. La robustesse et la rentabilité de la stratégie peuvent être améliorées en introduisant le filtrage de tendance, la superposition des signaux, la gestion de la position, la densité de la grille adaptative et d'autres moyens. En résumé, bas


// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © jcloyd

//@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)

Plus de