Pour les débutants, vérifiez Je vous emmène à la négociation quantitative de crypto-monnaie (5)

Auteur:Je suis désolée., Créé: 2022-04-18 17:20:53, mis à jour: 2022-04-18 17:30:27

Pour les débutants, vérifiez Je vous emmène à la négociation quantitative de crypto-monnaie (5)

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, tant que vous traversez chaque ligne de grille de la grille et jugez que le prix actuel traverse la ligne de grille vers le haut ou vers le bas, l'action de trading peut être déclenchée.

    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, lorsque la stratégie est en cours d'exécution, 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)? Nous devons d'abord ajouter un mécanisme d'extension à la structure de données de la grille.

    Commencez à écrire la fonction principale de la stratégie, et la fonction principale est le code où la stratégie commence à exécuter.

    var diff = 50                                 // global variable, the grid interval, can be designed as parameter; for an easy explanation, we write it in an infinite loop 
    function main() {
        // After the bot starts running, execute the strategy code from here
        var ticker = _C(exchange.GetTicker)       // obtain the latest ticker data in the market; for the ticker data structure, you can refer to FMZ API documentation: https://www.fmz.com/api#ticker
        var net = createNet(ticker.Last, diff)    // the function to initially construct the grid data structure we designed in the previous article; here we construct a grid data structure net
    
        while (true) {                            // then, the program logic enters the while infinite loop, and the strategy will repeatedly execute the code within the {} symbol from here
            ticker = _C(exchange.GetTicker)       // the first line of the infinite loop code gets the latest market quote data, and updates it to the variable ticker 
            // 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,
                })
            }
            
            // the code is not completed...
        }
    }
    

    Il s'agit du code qui rend la structure de données de grille extensible (extrait du code ci-dessus):

          // check the grid range 
          while (ticker.Last >= net[net.length - 1].price) {   // if the price exceeds the grid line with the highest price in the grid,
              net.push({                                       // add a new grid line after the grid line with the highest price in the grid
                  buy : false,                                 // initialize the sell mark 
                  sell : false,                                // initialize the buy mark 
                  price : net[net.length - 1].price + diff,    // add a grid interval on the basis of the previous highest price
              })
          }
          while (ticker.Last <= net[0].price) {                // if the price is lower than the grid line with the lowest price in the grid,
              var price = net[0].price - diff                  // distinguished from adding upwards, you should notice the price of the newly added grid line downwards cannot be less than or equal to 0, so you need to judge here 
              if (price <= 0) {                                // do not add when the price is less than or equal to 0, and break the loop 
                  break
              }
              net.unshift({                                    // add a new grid line before the grid line with the lowest price in the grid 
                  buy : false,
                  sell : false,
                  price : price,
              })
          }
    

    Ensuite, nous devons examiner comment mettre en œuvre le déclencheur de négociation.

    var diff = 50
    var amount = 0.002       // add a global variable, which can also be designed as a parameter; for easy explanation, we can write it in an infinite loop 
                             // the parameter controls the trading amount on the grid line each time the trading is triggered 
    function main() {
        var ticker = _C(exchange.GetTicker)
        var net = createNet(ticker.Last, diff)
        var preTicker = ticker       // before the start of the main (infinite) loop, set a variable, to record the market quotes of last time 
        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,
                })
            }  
    
            // index the grid 
            for (var i = 0 ; i < net.length ; i++) {     // traverse all grid lines in the grid data structure 
                var p = net[i]
                if (preTicker.Last < p.price && ticker.Last > p.price) {         // upcross, and sell; when the current node has been traded, no matter SELL or BUY, no more trade
                    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) {  // downcross, and 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 quotes in preTicker, which will be used as the "last" market quote data to compare with the new one in next loop, to judge upcross and downcross 
            Sleep(500)
        }
    }  
    

    Vous pouvez voir:

    • Condition de passage en amont de la ligne du réseau:preTicker.Last < p.price && ticker.Last > p.price
    • condition de traverser la ligne du réseau:preTicker.Last > p.price && ticker.Last < p.price

    C'est ce dont nous avons parlé dans l'article précédent:

    img

    Le jugement de l'envergure ou de l'envergure est seulement la première étape pour déterminer si l'ordre et le commerce doivent être effectués, et la marque dans les données de la ligne de la grille doit également être jugée.

    S'il est à l'envers, jugez si le prix est inférieur à la ligne de grille actuelle, ainsi qu'à la marque d'achat sur la dernière ligne de grille; si la valeur de la marque d'achat est vraie, cela signifie que la dernière ligne de grille a été achetée, et réinitialisez la marque d'achat de la dernière ligne de grille comme fausse, et réinitialisez la marque de vente de la ligne de grille actuelle comme fausse.

    Après avoir jugé les conditions mentionnées tout à l'heure, si elles ne sont pas déclenchées, le continuer à juger. Si la marque d'achat et la marque de vente de la ligne de la grille actuelle sont à la fois fausses, cela signifie que la ligne de la grille actuelle peut négocier; car il est en amont, ici nous exécutons l'opération de vente, et marquer la marque de vente de la ligne de la grille comme vrai après l'exécution.

    La logique de traitement de la descente est la même. (les novices peuvent y penser par eux-mêmes.)

Retour complet sur la stratégie

Afin de voir certaines données pendant le backtest, 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,
            })
        }

        // index grid 
        for (var i = 0 ; i < net.length ; i++) {
            var p = net[i]
            if (preTicker.Last < p.price && ticker.Last > p.price) {         // upcross, and sell; when the current node has been traded, no matter SELL or BUY, no more trade
                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) {  // downcross, and 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)
    }
}

Le test de stratégie:

img

img

img

Vous pouvez 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 rendement 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 se maintenir pour l'équilibrer, tandis que la stratégie de réseau des contrats à terme est plus risquée et doit définir les paramètres de réseau de manière conservatrice.


Plus de