Les ressources ont été chargées... Je charge...

Commerce quantitatif de crypto-monnaie pour les débutants - vous rapprocher de la crypto-monnaie quantitative (5)

Auteur:FMZ~Lydia, Créé: 2022-08-03 16:08:50, Mis à jour: 2023-09-21 21:07:02

img

Dans l'article précédent, nous avons expliqué l'analyse de la logique de trading d'une stratégie de grille simple.

  • Analyse de la logique du trading Comme nous l'avons mentionné dans l'article précédent, vous pouvez déclencher une action de trading en traversant chaque ligne de grille et en jugeant le prix actuel au-dessus ou en dessous.

    Le premier détail que nous devons considérer est la conception de la grille infinie.createNetCette fonction génère une structure de données de grille avec un nombre fini de lignes de grille. alors que se passe-t-il si le prix dépasse les limites de cette structure de données de grille (au-delà de la ligne de grille supérieure où le prix est le plus élevé, et la ligne de grille inférieure où le prix est le plus bas) lorsque la stratégie est en cours d'exécution? Donc nous devons d'abord ajouter un mécanisme d'extension à la structure de données de la grille.

    Commençons à écrire la fonction principale de la stratégie, qui est le code où la stratégie commence à exécuter

    var diff = 50                                 // Global variables and grid spacing can be designed as parameters for easy explanation. We write this parameter into the code.
    function main() {
        // After the real bot starts running, execute the strategy code from here
        var ticker = _C(exchange.GetTicker)       // To get the latest market data ticker, please refer to the FMZ API documentation for the structure of the ticker data: https://www.fmz.com/api#ticker
        var net = createNet(ticker.Last, diff)    // The function we designed in the previous article to construct the grid data structure initially, here we construct a grid data structure net
    
        while (true) {                            // Then the program logic enters this while infinite loop, and the strategy execution will continue to execute the code within the {} symbol here.
            ticker = _C(exchange.GetTicker)       // The first line of the infinite loop code section, get the latest market data and update it to the ticker variable
            // Check the grid range
            while (ticker.Last >= net[net.length - 1].price) {
                net.push({
                    buy : false,
                    sell : false,
                    price : net[net.length - 1].price + diff,
                })
            }
            while (ticker.Last <= net[0].price) {
                var price = net[0].price - diff
                if (price <= 0) {
                    break
                }
                net.unshift({
                    buy : false,
                    sell : false,
                    price : price,
                })
            }
            
            // There are other codes...
        }
    }
    

    Pour rendre la structure de données de grille extensible, voici le code (extrait du code ci-dessus):

          // Check the grid range
          while (ticker.Last >= net[net.length - 1].price) {   // If the price exceeds the grid line of the highest price of the grid
              net.push({                                       // Just add a new grid line after the grid line with the highest price of the grid
                  buy : false,                                 // Initialize sell marker
                  sell : false,                                // Initialize buy marker
                  price : net[net.length - 1].price + diff,    // dd a grid spacing to the previous highest price
              })
          }
          while (ticker.Last <= net[0].price) {                // If the price is lower than the grid line of the lowest price of the grid
              var price = net[0].price - diff                  // Different from adding upwards, it should be noted that the price of adding new grid lines downwards cannot be less than or equal to 0, so it is necessary to judge here
              if (price <= 0) {                                // Less than or equal to 0 will not be added, jump out of this loop
                  break
              }
              net.unshift({                                    // Add a new grid line just before the grid line with the lowest price of the grid
                  buy : false,
                  sell : false,
                  price : price,
              })
          }
    

    L'étape suivante consiste à examiner comment mettre en œuvre le déclencheur de négociation spécifiquement.

    var diff = 50
    var amount = 0.002       // Add a global variable, which can also be designed as a parameter. Of course, for the sake of simplicity, we also write it in the strategy code.
                             // This parameter controls the trade volume each time a trade is triggered on the grid line
    function main() {
        var ticker = _C(exchange.GetTicker)
        var net = createNet(ticker.Last, diff)
        var preTicker = ticker       // Before the main loop (fixed loop) starts, set a variable to record the last market data
        while (true) {
            ticker = _C(exchange.GetTicker)
            // Check the grid range
            while (ticker.Last >= net[net.length - 1].price) {
                net.push({
                    buy : false,
                    sell : false,
                    price : net[net.length - 1].price + diff,
                })
            }
            while (ticker.Last <= net[0].price) {
                var price = net[0].price - diff
                if (price <= 0) {
                    break
                }
                net.unshift({
                    buy : false,
                    sell : false,
                    price : price,
                })
            }  
    
            // Retrieve grid
            for (var i = 0 ; i < net.length ; i++) {     // Iterate over all grid lines in the grid data structure
                var p = net[i]
                if (preTicker.Last < p.price && ticker.Last > p.price) {         // Above the SMA, sell, the current node has already traded, regardless of SELL BUY, it will no longer be traded
                    if (i != 0) {
                        var downP = net[i - 1]
                        if (downP.buy) {
                            exchange.Sell(-1, amount, ticker)
                            downP.buy = false 
                            p.sell = false 
                            continue
                        }
                    }
                    if (!p.sell && !p.buy) {
                        exchange.Sell(-1, amount, ticker)
                        p.sell = true
                    }
                } else if (preTicker.Last > p.price && ticker.Last < p.price) {  // Below the SMA, buy
                    if (i != net.length - 1) {
                        var upP = net[i + 1]
                        if (upP.sell) {
                            exchange.Buy(-1, amount * ticker.Last, ticker)
                            upP.sell = false 
                            p.buy = false 
                            continue
                        }
                    }
                    if (!p.buy && !p.sell) {
                        exchange.Buy(-1, amount * ticker.Last, ticker)
                        p.buy = true 
                    } 
                }
            }
            preTicker = ticker    // Record the current market data in preTicker, and in the next cycle, use it as a comparison between the "previous" market data and the latest one to judge whether to be above the SMA or below the SMA.
            Sleep(500)
        }
    }  
    

    On peut constater que:

    • Condition de passage au-dessus des lignes de la grille:preTicker.Last < p.price && ticker.Last > p.price
    • Condition de passage sous les lignes de la grille:preTicker.Last > p.price && ticker.Last < p.price

    Voici ce que nous disions dans le post précédent:

img

Le fait de juger s'il faut être au-dessus ou en dessous de la SMA n'est que la première étape pour juger si une commande peut être passée, et il est également nécessaire de juger des marques dans les données de la ligne de la grille.

Si elle est supérieure à la SMA, on estime que le prix est inférieur à la ligne de grille actuelle et à la marque d'achat sur la ligne de grille la plus proche. Si la valeur de la marque d'achat est vraie, cela signifie que la ligne de grille précédente a été achetée et que la marque d'achat précédente a été réinitialisée à false, et la marque de vente de la ligne de grille actuelle réinitialisée à false.

Après avoir jugé les conditions, s'il n'y a pas de déclencheur, continuez à juger. Si les marques d'achat / vente sur la ligne de grille actuelle sont toutes deux fausses, cela signifie que la ligne de grille actuelle peut être échangée. Comme elle est au-dessus de la SMA, nous effectuerons une opération de vente ici. Après l'exécution, marquez la marque de vente de la ligne de grille actuelle comme vraie.

La logique de traitement est la même pour être en dessous de la SMA (à gauche pour les débutants à penser ici).

Retour à l'analyse de la stratégie

Afin de voir certaines données pendant le backtesting, une fonctionshowTblest écrit pour afficher les données.

function showTbl(arr) {
    var tbl = {
        type : "table", 
        title : "grid",
        cols : ["grid information"],
        rows : []
    }
    var arrReverse = arr.slice(0).reverse()
    _.each(arrReverse, function(ele) {
        var color = ""
        if (ele.buy) {
            color = "#FF0000"
        } else if (ele.sell) {
            color = "#00FF00"
        }
        tbl.rows.push([JSON.stringify(ele) + color])
    })
    LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`", "\n account Information:", exchange.GetAccount())
}

Code de stratégie complet:

/*backtest
start: 2021-04-01 22:00:00
end: 2021-05-22 00:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"OKEX","currency":"ETH_USDT","balance":100000}]
*/

var diff = 50
var amount = 0.002
function createNet(begin, diff) {
    var oneSideNums = 10
    var up = []
    var down = []
    for (var i = 0 ; i < oneSideNums ; i++) {
        var upObj = {
            buy : false,
            sell : false, 
            price : begin + diff / 2 + i * diff,
        }
        up.push(upObj)

        var j = (oneSideNums - 1) - i
        var downObj = {
            buy : false,
            sell : false,
            price : begin - diff / 2 - j * diff,
        }
        if (downObj.price <= 0) {  // The price cannot be less than or equal to 0
            continue
        }
        down.push(downObj)
    }

    return down.concat(up)
}

function showTbl(arr) {
    var tbl = {
        type : "table", 
        title : "grid",
        cols : ["grid Information"],
        rows : []
    }
    var arrReverse = arr.slice(0).reverse()
    _.each(arrReverse, function(ele) {
        var color = ""
        if (ele.buy) {
            color = "#FF0000"
        } else if (ele.sell) {
            color = "#00FF00"
        }
        tbl.rows.push([JSON.stringify(ele) + color])
    })
    LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`", "\n account Information:", exchange.GetAccount())
}

function main() {
    var ticker = _C(exchange.GetTicker)
    var net = createNet(ticker.Last, diff)
    var preTicker = ticker 
    while (true) {
        ticker = _C(exchange.GetTicker)
        // Check the grid range
        while (ticker.Last >= net[net.length - 1].price) {
            net.push({
                buy : false,
                sell : false,
                price : net[net.length - 1].price + diff,
            })
        }
        while (ticker.Last <= net[0].price) {
            var price = net[0].price - diff
            if (price <= 0) {
                break
            }
            net.unshift({
                buy : false,
                sell : false,
                price : price,
            })
        }

        // Retrieve grid
        for (var i = 0 ; i < net.length ; i++) {
            var p = net[i]
            if (preTicker.Last < p.price && ticker.Last > p.price) {         // Being above the SMA, sell, the current node has already traded, regardless of SELL BUY, it will no longer be traded
                if (i != 0) {
                    var downP = net[i - 1]
                    if (downP.buy) {
                        exchange.Sell(-1, amount, ticker)
                        downP.buy = false 
                        p.sell = false 
                        continue
                    }
                }
                if (!p.sell && !p.buy) {
                    exchange.Sell(-1, amount, ticker)
                    p.sell = true
                }
            } else if (preTicker.Last > p.price && ticker.Last < p.price) {  // Being below the SMA, buy
                if (i != net.length - 1) {
                    var upP = net[i + 1]
                    if (upP.sell) {
                        exchange.Buy(-1, amount * ticker.Last, ticker)
                        upP.sell = false 
                        p.buy = false 
                        continue
                    }
                }
                if (!p.buy && !p.sell) {
                    exchange.Buy(-1, amount * ticker.Last, ticker)
                    p.buy = true 
                } 
            }
        }

        showTbl(net)
        preTicker = ticker 
        Sleep(500)
    }
}

Test de stratégie:

img

img

img

Nous pouvons donc voir les caractéristiques de la stratégie du réseau, quand il y a un marché tendance, il y aura une grande perte flottante, et le profit va rebondir dans un marché volatil. Par conséquent, la stratégie de réseau n'est pas sans risque. La stratégie au comptant peut encore être déplacée par, tandis que la stratégie de réseau des contrats à terme est plus risquée et doit être réglée de manière prudente pour les paramètres de réseau.


Relationnée

Plus de