FMZ Quant: Une analyse des exemples de conception des exigences communes sur le marché des crypto-monnaies (I)

Auteur:Je ne sais pas., Créé: 2023-12-19 16:02:58, Mis à jour: 2024-01-02 21:21:58

img

Dans l'espace de négociation d'actifs de crypto-monnaie, l'obtention et l'analyse de données de marché, les taux de requête et la surveillance des mouvements d'actifs de compte sont toutes des opérations critiques.

1. Comment écrire le code pour obtenir la monnaie avec la plus forte augmentation en 4 heures sur Binance Spot?

Lorsque vous écrivez un programme de stratégie de trading quantitative sur la plateforme FMZ, la première chose que vous devez faire lorsque vous rencontrez une exigence est de l'analyser.

  • Quel langage de programmation utiliser? Le plan est d'utiliser Javascript pour le mettre en œuvre.
  • Exige des cotations au comptant en temps réel dans toutes les devises La première chose que nous avons faite lorsque nous avons vu l'exigence était de chercher le document de l'API de Binance pour savoir s'il y avait des cotations agrégées (il est préférable d'avoir des cotations agrégées, il faut beaucoup de travail pour chercher une par une). Nous avons trouvé l'interface des citations agrégées:GET https://api.binance.com/api/v3/ticker/priceJe suis désolée. Sur la plateforme FMZ, utilisez leHttpQueryune fonction permettant d'accéder à l'interface du ticker d'échange (interface publique ne nécessitant pas de signature).
  • Besoin de compter les données pour une période de fenêtre mobile de 4 heures Conceptualiser comment concevoir la structure du programme statistique.
  • Calculer les fluctuations de prix et les trier En pensant à l'algorithme des fluctuations de prix, est-ce:price fluctuations (%) = (current price - initial price) / initial price * 100dans %.

Après avoir résolu le problème et défini le programme, nous avons commencé à concevoir le programme.

Conception du code

var dictSymbolsPrice = {}

function main() {
    while (true) {
        // GET https://api.binance.com/api/v3/ticker/price
        try {
            var arr = JSON.parse(HttpQuery("https://api.binance.com/api/v3/ticker/price"))
            if (!Array.isArray(arr)) {
                Sleep(5000)
                continue 
            }
            
            var ts = new Date().getTime()
            for (var i = 0; i < arr.length; i++) {
                var symbolPriceInfo = arr[i]
                var symbol = symbolPriceInfo.symbol
                var price = symbolPriceInfo.price

                if (typeof(dictSymbolsPrice[symbol]) == "undefined") {
                    dictSymbolsPrice[symbol] = {name: symbol, data: []}
                }
                dictSymbolsPrice[symbol].data.push({ts: ts, price: price})
            }
        } catch(e) {
            Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
        }
        
        // Calculate price fluctuations
        var tbl = {
            type : "table",
            title : "Price fluctuations",
            cols : ["trading pair", "current price", "price 4 hours ago", "price fluctuations", "data length", "earliest data time", "latest data time"],
            rows : []
        }
        for (var symbol in dictSymbolsPrice) {
            var data = dictSymbolsPrice[symbol].data
            if (data[data.length - 1].ts - data[0].ts > 1000 * 60 * 60 * 4) {
                dictSymbolsPrice[symbol].data.shift()
            }

            data = dictSymbolsPrice[symbol].data
            dictSymbolsPrice[symbol].percentageChange = (data[data.length - 1].price - data[0].price) / data[0].price * 100
        }

        var entries = Object.entries(dictSymbolsPrice)
        entries.sort((a, b) => b[1].percentageChange - a[1].percentageChange)

        for (var i = 0; i < entries.length; i++) {
            if (i > 9) {
                break
            }   
            var name = entries[i][1].name
            var data = entries[i][1].data
            var percentageChange = entries[i][1].percentageChange
            var currPrice = data[data.length - 1].price
            var currTs = _D(data[data.length - 1].ts)
            var prePrice = data[0].price
            var preTs = _D(data[0].ts)
            var dataLen = data.length

            tbl.rows.push([name, currPrice, prePrice, percentageChange + "%", dataLen, preTs, currTs])
        }
        
        LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
        Sleep(5000)
    }
}

Analyse du code

    1. Structure des donnéesvar dictSymbolsPrice = {}: Un objet vide pour stocker des informations sur les prix pour chaque paire de négociation. La clé est le symbole de la paire de négociation, et la valeur est un objet contenant le nom de la paire de négociation, un tableau de données sur les prix et des informations sur les fluctuations des prix.
    1. Fonction principale 2.1 Boucle infinie
while (true) {
    // ...
}

Le programme surveille en permanence les prix des paires de trading de l'API Binance à travers une boucle infinie. 2.2. Obtenir des informations sur les prix

var arr = JSON.parse(HttpQuery("https://api.binance.com/api/v3/ticker/price"))

Obtenez les informations actuelles sur le prix de la paire de trading via l'API Binance. Si le retour n'est pas un tableau, attendez 5 secondes et réessayez. 2.3 Mise à jour des données relatives aux prix

for (var i = 0; i < arr.length; i++) {
    // ...
}

Iterer à travers le tableau des informations de prix obtenues et mettre à jour les données dans dictSymbolsPrice. Pour chaque paire de négociation, ajouter l'horodatage et le prix actuels au tableau de données correspondant. 2.4 Traitement des exceptions

} catch(e) {
    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}

Capturez les exceptions et enregistrez les informations d'exception pour vous assurer que le programme peut continuer à s'exécuter. 2.5. Calculer les fluctuations des prix

for (var symbol in dictSymbolsPrice) {
    // ...
}

Iterer à travers dictSymbolsPrice, calculer les fluctuations de prix de chaque paire de négociation et supprimer les données les plus anciennes si elles sont plus longues que 4 heures. 2.6. Trier et générer des tableaux

var entries = Object.entries(dictSymbolsPrice)
entries.sort((a, b) => b[1].percentageChange - a[1].percentageChange)

for (var i = 0; i < entries.length; i++) {
    // ...
}

Sortir les paires de négociation par ordre décroissant de leurs fluctuations de prix et générer un tableau contenant des informations sur les paires de négociation. 2.7. sortie et retard du journal

LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
Sleep(5000)

Sortez le tableau et l'heure actuelle sous forme de journal et attendez 5 secondes pour poursuivre le prochain tour de la boucle.

Le programme obtient les informations de prix en temps réel de la paire de négociation via l'API Binance, calcule ensuite les fluctuations de prix et les expédie au journal sous forme de tableau.

Test en cours d'exécution de négociation en direct

img

Étant donné que les données ne peuvent être recueillies que peu à peu au début, il n'est pas possible de calculer les fluctuations de prix sur une base continue sans recueillir suffisamment de données pour une fenêtre de 4 heures.

2. Vérifiez la gamme complète de taux de financement pour les contrats libellés en U de Binance

La vérification du taux de financement est similaire au code ci-dessus, tout d'abord, nous devons vérifier la documentation de l'API de Binance pour trouver l'interface liée au taux de financement.

GET https://fapi.binance.com/fapi/v1/premiumIndex

Mise en œuvre du code

Puisqu'il y a tellement de contrats, nous exportons les 10 plus grands taux de financement ici.

function main() {
    while (true) {
        // GET https://fapi.binance.com/fapi/v1/premiumIndex
        try {
            var arr = JSON.parse(HttpQuery("https://fapi.binance.com/fapi/v1/premiumIndex"))
            if (!Array.isArray(arr)) {
                Sleep(5000)
                continue 
            }
            
            arr.sort((a, b) => parseFloat(b.lastFundingRate) - parseFloat(a.lastFundingRate))
            var tbl = {
                type: "table",
                title: "Top 10 funding rates for U-denominated contracts",
                cols: ["contracts", "funding rate", "marked price", "index price", "current rate time", "next rate time"],
                rows: []
            }
            for (var i = 0; i < 9; i++) {
                var obj = arr[i]
                tbl.rows.push([obj.symbol, obj.lastFundingRate, obj.markPrice, obj.indexPrice, _D(obj.time), _D(obj.nextFundingTime)])
            }
            LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
        } catch(e) {
            Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
        }
        Sleep(1000 * 10)
    }
}

La structure des données retournées est la suivante, et vérifiez la documentation de Binance, elle montre que le dernier taux de financement est le taux de financement que nous voulons.

{
    "symbol":"STMXUSDT",
    "markPrice":"0.00883606",
    "indexPrice":"0.00883074",
    "estimatedSettlePrice":"0.00876933",
    "lastFundingRate":"0.00026573",
    "interestRate":"0.00005000",
    "nextFundingTime":1702828800000,
    "time":1702816229000
}

Test en cours d'exécution en direct:

img

Obtenir les taux de financement du contrat d'échange OKX de la version Python

Un utilisateur a demandé une version Python de l'exemple, et c'est pour l'échange OKX. Voici un exemple:

Les données renvoyées par l'interfacehttps://www.okx.com/priapi/v5/public/funding-rate-all?currencyType=1:

{
    "code":"0",
    "data":[
        {
            "fundingTime":1702828800000,
            "fundingList":[
                {
                    "instId":"BTC-USDT-SWAP",
                    "nextFundingRate":"0.0001102188733642",
                    "minFundingRate":"-0.00375",
                    "fundingRate":"0.0000821861465884",
                    "maxFundingRate":"0.00375"
                } ...

Code spécifique:

import requests
import json
from time import sleep
from datetime import datetime

def main():
    while True:
        # https://www.okx.com/priapi/v5/public/funding-rate-all?currencyType=1
        try:
            response = requests.get("https://www.okx.com/priapi/v5/public/funding-rate-all?currencyType=1")
            arr = response.json()["data"][0]["fundingList"]
            Log(arr) 
            if not isinstance(arr, list):
                sleep(5)
                continue

            arr.sort(key=lambda x: float(x["fundingRate"]), reverse=True)

            tbl = {
                "type": "table",
                "title": "Top 10 funding rates for U-denominated contracts",
                "cols": ["contracts", "next rate", "minimum", "current", "maximum"],
                "rows": []
            }

            for i in range(min(9, len(arr))):
                obj = arr[i]
                row = [
                    obj["instId"],
                    obj["nextFundingRate"],
                    obj["minFundingRate"],
                    obj["fundingRate"],
                    obj["maxFundingRate"]
                ]
                tbl["rows"].append(row)
            
            LogStatus(_D(), "\n", '`' + json.dumps(tbl) + '`')

        except Exception as e:
            Log(f"Error: {str(e)}")

        sleep(10)

Test en cours d'exécution en direct:

img

Résultats

Ces exemples fournissent des idées de conception de base et des méthodes d'appel, le projet réel peut devoir apporter des modifications et des extensions appropriées en fonction des besoins spécifiques.


Plus de