3
Suivre
1444
Abonnés

Tutoriel de base sur la rédaction de stratégies de plateforme quantitative FMZ (à lire absolument)

Créé le: 2019-08-13 17:47:27, Mis à jour le: 2021-08-06 10:29:46
comments   33
hits   69033

[TOC] Ce tutoriel contient les connaissances de base de l’écriture de stratégies, y compris l’introduction de l’API, les retours, les graphiques, etc. Après avoir appris ce tutoriel de base, l’utilisateur sera en mesure de maîtriser l’utilisation de l’API de base et d’écrire une stratégie stable pour le disque dur.Début de la plateforme de quantification des inventeurs de FMZ 。

Les anciens tutoriels:Les inventeurs ont quantifié les stratégies de FMZ.COM pour écrire un manuel d’utilisation complet 2.0 (tutoriel), ce tutoriel répertorie de nombreux articles et vous est recommandé de le parcourir.

Une première explication de la stratégie

Détails de l’API

L’interface de programmation d’applications (API) est une interface de programmation d’applications (API) qui permet aux applications de se connecter à l’échangeur via une API pour effectuer automatiquement des transactions ou d’autres fonctions selon l’intention de la conception.

Il existe actuellement deux principaux protocoles d’interface pour les échanges de crypto-monnaie: REST et Websocket. Le protocole REST nécessite un accès unique pour chaque donnée obtenue. Par exemple, l’API de l’échange de simulation wex.app, ouverte directement dans le navigateur https://api.wex.app/api/v1/public/ticker?market=BTC_USDT, donne le résultat suivant:

{"data:{"buy":"11351.73","high":"11595.77","last":"11351.85","low":"11118.45","open":"11358.74","quoteVol":"95995607137.00903936","sell":"11356.02","time":1565593489318,"vol":"3552.5153"}}

Cela vous permet de voir les transactions les plus récentes avec la paire BTC_USDT, qui change chaque fois qu’elle est mise à jour.market=Les paramètres de paires de transactions spécifiques peuvent être modifiés pour obtenir d’autres données de paires de transactions. Pour les interfaces publiques, telles que le marché, toutes les personnes peuvent y accéder, donc aucune vérification n’est requise, tandis que certaines interfaces, telles que les commandes et les comptes d’acquisition, nécessitent la vérification de l’identité de l’utilisateur, qui doit être signée à l’aide de l’API-KEY. Websocket est un mode d’abonnement, après l’envoi du contenu nécessitant un abonnement, l’échange envoie les données mises à jour au programme, sans avoir besoin de revenir à chaque fois, donc plus efficace.

La plateforme de trading quantitatif FMZ est encapsulée dans l’interface REST de chaque plateforme, et utilise un format d’appel et de données unifié pour simplifier et généraliser la programmation de stratégies. La plateforme de trading quantitatif FMZ peut facilement prendre en charge Websocket, qui sera détaillé dans le prochain tutoriel.

Langues de programmation différentes

La plupart des documents de l’API de la plate-forme FMZ sont basés sur JavaScript, mais en raison de l’emballage, il n’y a pratiquement aucune différence entre les langues, il suffit de faire attention aux problèmes de grammaire. C ++ est un peu spécial, les tutoriels ultérieurs auront une introduction spécialisée.

Comme il existe des versions différentes de Python, il est possible de spécifier une version au début du programme, comme#!Python2,#!Python3Attention: JavaScript a été récemment mis à niveau vers la grammaire ES6, les personnes intéressées peuvent en apprendre davantage. Ci-dessous, le code Python et Javascript qui fonctionnent de la même manière, mais avec des différences grammaticales, est présenté. La documentation de l’API ne donne que des exemples de Javascript, ce tutoriel prend en compte les cas d’utilisation spéciaux de Python.

#python代码
def main():
    while True:
        Log(exchange.GetAccount().Balance)
        Sleep(2000)
#相应的Js代码
function main(){
    while(true){
        Log(exchange.GetAccount().Balance)
        Sleep(2000)
    }
}

Recommandations de ressources

  • La documentation de l’API de la plateforme FMZ est disponible ici: https://www.fmz.com/api
  • Si vous souhaitez recevoir des signaux de tradingview et effectuer des transactions sur FMZ, vous pouvez consulter cet article: https://www.fmz.com/digest-topic/5533
  • Une introduction rapide à Javascript, Python, des stratégies simples à écrire sans une grammaire compliquée, avec seulement quelques concepts de base à maîtriser, à apprendre en même temps que ce tutoriel: https://www.fmz.com/bbs-topic/382 https://www.fmz.com/bbs-topic/417
  • La documentation en langue mac est très pratique pour les stratégies de tendance.
  • Un exemple d’appel en C++ qui peut être consulté par ceux qui s’intéressent à C++, mais qui est difficile à déboguer car ce n’est pas un langage interprétatif: https://www.fmz.com/strategy/61533
  • Le cours de trading quantifié de la monnaie numérique de NetEase Cloud Classroom, produit officiel de FMZ, ne coûte que 20 yuans, est riche en détails, adapté aux débutants.Lien vers le cours
  • Il existe des stratégies pédagogiques adaptées à l’entrée en cours et à l’apprentissage de l’écriture marginale de base.
  • Le code source détaillé de la stratégie: https://www.fmz.com/bbs/s:tag: %E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%901

Outils de débogage

La plate-forme de quantification FMZ fournit un outil de débogage pour le débogage de l’interface API, https://www.fmz.com/m/debug 。 Le débogage ne prend en charge que JavaScript, ne peut être exécuté que pendant un certain temps, et le débogage de l’interface de l’échange peut être effectué sans créer de disque fixe。 Les données retournées seront retournées en tant que résultats, le code du débogage n’est pas sauvegardé。 Dans ce tutoriel, vous pouvez tester simultanément avec le débogage。 Tutoriel de base sur la rédaction de stratégies de plateforme quantitative FMZ (à lire absolument)

L’architecture de la procédure stratégique

Comme les procédures de stratégie, elles doivent être exécutées dans l’ordre du code, mais la particularité est qu’il doit y avoir une fonction principale. Comme la stratégie doit être exécutée sans interruption, il faut généralement un cycle plus un temps d’arrêt. Comme la fréquence d’accès à toutes les API de la transaction est limitée, le temps d’arrêt doit être ajusté en conséquence.

Les autres fonctions spéciales sont les suivantes:

  • onexit ((() est une fonction de balayage de queue de sortie normale, dont la durée maximale est de 5 minutes. Elle peut être indéterminée, et si elle est dépassée, une erreur d’interrupt est signalée.
  • onerror() La fonction de sortie pour une exception, dont la durée maximale est de 5 minutes, ne peut pas être déclarée。
  • init (() est une fonction d’initialisation qui est appelée automatiquement au début de l’exécution de la stratégie, mais qui ne peut pas être déclarée.
function onTick(){
   var ticker = exchange.GetTicker()
   var account = exchange.GetAccount()
    //在这里写策略逻辑,将会每6s调用一次
}
function main(){
    while(true){
        onTick()
        Sleep(6000)
    }
}

L’exemple précédent montre que si une erreur d’accès au réseau peut entraîner l’arrêt direct de la stratégie, si vous voulez une stratégie similaire au redémarrage automatique qui ne s’arrête pas, vous pouvez utiliser la stratégie en continu avec le cycle principal tolérant les erreurs de la stratégie de capture de l’essai (ne pas utiliser le test de retour). Bien sûr, il est recommandé de le faire uniquement lorsque la stratégie est stable, sinon toutes les erreurs ne seront pas signalées et il sera difficile de trier les problèmes de la stratégie.

function onTick(){
   var ticker = exchange.GetTicker()
   var account = exchange.GetAccount()
    //在这里写策略逻辑,将会每6s调用一次
}
function main(){
    try{
        while(true){
           onTick()
           Sleep(6000)
       }
    }catch(err){
        Log(err)
    }
}

L’API de la bourse est présentée

Échanges et paires de transactions

Il est nécessaire d’indiquer une paire d’échanges et une paire de transactions lors de l’appel de n’importe quelle API associée à une plate-forme.exchangeL’objet est représenté par:exchange.GetTicker()Ce qui est obtenu est le ticker de marché de cette paire d’échanges.

La plate-forme FMZ prend en charge l’ajout simultané de plusieurs paires d’échanges, comme BTC et ETH sur un même compte d’échange, ou BTC et ETH sur un autre compte d’échange. Notez que des comptes différents sur le même échange peuvent également être ajoutés simultanément, en fonction de la distinction des étiquettes ajoutées au site FMZ.exchangesLes ensembles sont représentés par l’ordre de création du disque dur:exchanges[0]exchanges[1]… et ainsi de suite. Le format des paires de transactions est le suivant:BTC_USDTLe BTC est la monnaie de transaction et l’USDT est la monnaie de référence.

Tutoriel de base sur la rédaction de stratégies de plateforme quantitative FMZ (à lire absolument)

Évidemment, si nous avons beaucoup de paires de transactions à gérer, cette méthode peut être gênante, mais nous pouvons utiliser SetCurrency pour échanger des paires de transactions, commeexchange.SetCurrency("BTC_USDT")Pour l’instant,exchangeLes paires de transactions liées deviennentBTC_USDTLe changement de paire d’opérations sera valable jusqu’à la prochaine fois qu’il sera appelé.Remarque: la dernière mise à jour de support pour les paires de transactions de commutationVoici un exemple concret.

var symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT"]
var buyValue = 1000
function main(){
  for(var i=0;i<symbols.length;i++){
      exchange.SetCurrency(symbols[i])
      var ticker = exchange.GetTicker()
      var amount = _N(buyValue/ticker.Sell, 3)
      exchange.Buy(ticker.Sell, amount)
      Sleep(1000)
  }
}

L’accès à des interfaces ouvertes

Comme l’exemple ci-dessus, les interfaces de trading sont généralement des interfaces publiques et accessibles à tous. Les interfaces de trading habituelles sont: obtenir des tickers de trading, obtenir la profondeur, obtenir des enregistrements de ligne K, obtenir des enregistrements de transactions. Le trading est la base de la stratégie pour effectuer des jugements de transaction, qui seront présentés ci-dessous un par un, il est préférable de pouvoir essayer par vous-même dans un outil de débogage.

Les interfaces sont généralementInfochamps, qui représentent les chaînes de données initiales retournées par l’échange, qui peuvent être utilisées pour compléter des informations supplémentaires, qui ont été précédemment analysées, en utilisant JavaScriptJSON.parse()Il est possible d’utiliser la bibliothèque json.TimeLe champ indique le délai de la demande, qui peut être utilisé pour juger du retard.

Il est possible d’accéder à l’interface API sur le disque dur et de revenir en arrière en cas d’échec.nullPython est de retour.NoneLa tolérance aux erreurs est très importante, car les données utilisées dans un disque dur peuvent être endommagées et causer l’arrêt du disque dur.

GetTicker

L’interface la plus couramment utilisée pour obtenir des informations sur les tendances actuelles du marché est le prix de la dernière transaction, le prix d’achat et de vente, le volume des transactions récentes, etc. Le prix de la transaction peut être déterminé en fonction des informations de ticker avant de passer une commande.{"Info:{}, "High":5226.69, "Low":5086.37,"Sell":5210.63, "Buy":5208.5, "Last":5208.51, "Volume":1703.1245, "OpenInterest":0, "Time":1554884195976}

function main() {
    var ticker = exchange.GetTicker()
    Log(ticker) //在调试工具中 return ticker 。可以看到具体的结果。
    Log('上次成交价: ',ticker.Last, '买一价: ', ticker.Buy)
}

GetDepth

Vous pouvez utiliser cette interface pour calculer le prix d’impact. Voici un résultat de retour réel. Par exemple, Asks indique que les tickets sont vendus en groupes de 1 tonne et 2 tonnes, respectivement. Le prix augmente donc. Bids indique que les tickets sont achetés en groupes de 1 tonne et 2 tonnes, respectivement.

{
    "Info":null,
    "Asks":[
        {"Price":5866.38,"Amount":0.068644},
        {"Price":5866.39,"Amount":0.263985},
        ......
        ]
    "Bids":[
        {"Price":5865.13,"Amount":0.001898},
        {"Price":5865,"Amount":0.085575},
        ......
        ],
    "Time":1530241857399
}

Voici un exemple d’utilisation de l’accès en profondeur aux titres:

function main() {
    var depth = exchange.GetDepth()
    Log('买一价个: ', depth.Bids[0].Price, '卖一价格: ', depth.Asks[0].Price)
}

GetRecords

Obtenir les lignes K, l’une des interfaces les plus couramment utilisées, qui renvoient à la fois des informations sur les prix de longue durée, pour calculer la base de divers indicateurs. La longueur des lignes K ne peut pas être spécifiée si la période par défaut n’est pas spécifiée.

exchange.SetMaxBarLen(Len)Il est possible de définir le nombre de lignes K à obtenir pour la première fois (supporté par certaines bourses) et le nombre maximal de lignes K à obtenir.Par exemple:exchange.SetMaxBarLen(500)

GetRecords peut spécifier une période: PERIOD_M1:1 minutes, PERIOD_M5:5 minutes, PERIOD_M15:15 minutes, PERIOD_M30:30 minutes, PERIOD_H1:1 heures, PERIOD_D1:1 jours.exchange.GetRecords(PERIOD_M1)◦ Après avoir mis à niveau le dernier hôte, il prend en charge les cycles personnalisés, le nombre de secondes de cycles de transmission directe est utilisé comme paramètre, la personnalisation au niveau de la minute est synthétisée en fonction de la ligne K de 1 minute, la ligne K inférieure à 1 minute est synthétisée via GetTrades ((), les futures sur les marchandises sont synthétisées en fonction de tick, ◦Attention, vous trouverez des choses similaires dans le tutoriel.PERIOD_M1Les variables en majuscules, qui sont les variables globales par défaut de la FMZ, peuvent être enregistrées par les personnes intéressées.

Exemple de données retournées:

[
    {"Time":1526616000000,"Open":7995,"High":8067.65,"Low":7986.6,"Close":8027.22,"Volume":9444676.27669432},
    {"Time":1526619600000,"Open":8019.03,"High":8049.99,"Low":7982.78,"Close":8027,"Volume":5354251.80804935},
    {"Time":1526623200000,"Open":8027.01,"High":8036.41,"Low":7955.24,"Close":7955.39,"Volume":6659842.42025361},
    ......
]

Exemple d’une ligne K iodée:

function main(){
    var close = []
    var records = exchange.GetRecords(PERIOD_H1)
    Log('total bars: ', records.length)
    for(var i=0;i<records.length;i++){
        close.push(records[i].Close)
    }
    return close
}

GetTrades

Obtenir des données de transaction pour une certaine période (et non ses propres données de transaction) n’est pas pris en charge par certaines bourses.

Obtenir un compte pour effectuer des transactions

Ces interfaces ne sont pas directement accessibles car elles sont liées aux comptes et nécessitent l’utilisation de la signature API-KEY. La plateforme FMZ a été traitée automatiquement en arrière-plan et peut être utilisée directement.

Obtenir un compte GetAccount

Obtenir les informations de compte. Une des interfaces les plus utilisées, appelée avant de passer commande pour éviter un solde insuffisant. Retourne les résultats suivants:{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}❚ où Stocks est le solde disponible en monnaie de transaction de la paire de transactions, FrozenStocks est le solde gelé des commandes non exécutées, Balance est le solde disponible en monnaie de cotation, et FrozenBalance est le solde gelé. Si la paire de transactions estBTC_USDTLes stocks désignent le BTC et les soldes désignent l’USDT.

Notez que le résultat retourné est celui de la paire de transactions spécifiée, que les informations sur les autres devises du compte de transaction se trouvent dans le champ Info et que les opérations sur plusieurs paires de transactions ne doivent pas être appelées plusieurs fois.

Un disque dur qui imprime en permanence la valeur totale des transactions en cours:

function main(){
    while(true){
        var ticker = exchange.GetTicker()
        var account = exchange.GetAccount()
        var price = ticker.Buy
        var stocks = account.Stocks + account.FrozenStocks
        var balance = account.Balance + account.FrozenBalance
        var value = stocks*price + balance
        Log('Account value is: ', value)
        LogProfit(value)
        Sleep(3000)//sleep 3000ms(3s), A loop must has a sleep, or the rate-limit of the exchange will be exceed
        //when run in debug tool, add a break here
    }
}

Acheter sous le nom de Buy

Voici le prix:exchange.Buy(Price, Amount)ouexchange.Buy(Price, Amount, Msg),Price est le prix, Amount est la quantité, Msg est une chaîne supplémentaire qui peut être affichée dans le journal du disque dur, mais pas obligatoirement. Cette méthode est appelée pending order, et si la transaction n’est pas terminée immédiatement, elle génère une commande inachevée.null, pour vérifier l’état de la commande.

Si vous achetez à un prix bas, le prix est égal à 1, et le montant est égal à la valeur de la commande, commeexchange.Buy(-1, 0.5)La transaction est correcte.ETH_BTC, qui représente le prix du marché pour acheter 0,5 BTC d’ETH. Certaines bourses ne prennent pas en charge le cours du marché, ni la rétroaction à terme.

Toutes les demandes de précision de prix et de quantité de transactions partielles sont disponibles_N()Les fonctions de précision sont contrôlées. Pour les transactions à terme, Buy et Sell ont d’autres significations, qui seront présentées séparément.

Voici un exemple d’achat à prix réduit:

function main(){
    while(true){
        var ticker = exchange.GetTicker()
        var price = ticker.Sell
        if(price >= 7000){
            exchange.Buy(_N(price+5,2), 1, 'BTC-USDT')
            break
        }
        Sleep(3000)//Sleep 3000ms
    }
    Log('done')
}

Vente à la baisse

Le prix d’achat est le même que celui de la vente. Le prix de vente est le même que celui de la vente.exchange.Sell(-1, 0.2), représentant le prix de vente de 0,2 ETH.

GetOrder pour obtenir une commande

Obtenir des informations sur les commandes en fonction de l’identifiant de commande. Interface courante, mode d’appelexchange.GetOrder(OrderId),OrderId est l’identifiant de la commande, qui est renvoyé au moment de la commande.Attention au type de commandeTypeLes champs et le statut de la commandeStatusLes valeurs réelles sont numériques et représentent des significations différentes, mais ne sont pas utiles à la mémoire. La FMZ utilise des constantes globales pour représenter ces valeurs, comme celles des commandes non exécutées.StatusLa valeur de 0 est égale àORDER_STATE_PENDINGToutes ces constantes sont disponibles dans la documentation.◦ Retourner le résultat:

{
    "Id":125723661, //订单id
    "Amount":0.01, //订单数量
    "Price":7000, //订单价格
    "DealAmount":0, //已成交数量
    "AvgPrice":0, //成交均价
    "Status":0, // 0:未完全成交, 1:已成交, 2:已撤单
    "Type":1,// 订单类型,0:买单, 1:卖单
    "ContractType":"",//合约类型,用于期货交易
    "Info":{} //交易所返回原始信息
    }
}

Une stratégie pour acheter un nombre spécifique de pièces:

function main(){
    while(true){
        var amount = exchange.GetAccount().Stocks
        var ticker = exchange.GetTicker()
        var id = null
        if(5-amount>0.01){
            id = exchange.Buy(ticker.Sell, Math.min(5-amount,0.2))
        }else{
            Log('Job completed')
            return //return the main function, bot will stop
        }
        Sleep(3000) //Sleep 3000ms
        if(id){
            var status = exchange.GetOrder(id).Status
            if(status == 0){ //这里也可以用 status == ORDER_STATE_PENDING 来判断。
                exchange.CancelOrder(id)
            }
        }
    }
}

GetOrders n’a pas encore livré de commande

Obtenir la liste des transactions en cours pour toutes les commandes en attente. Si aucune commande en attente n’est retournée, retourner l’arbre vide. La liste des commandes est un résultat spécifique tel que GetOrder.

Exemple d’annulation d’une transaction en cours pour toutes les commandes:

function CancelAll(){
    var orders = exchange.GetOrders()
    for(var i=0;i<orders.length;i++){
        exchange.CancelOrder(orders[i].Id) // cancel order by orderID
    }
}
function main(){
    CancelAll()
    while(true){
        //do something
        Sleep(10000)
    }
}

Le démenti de la commande

Annuler une commande en fonction de l’id de la commande.exchange.CancelOrder(OrderId)。 annulation réussie retourne true, sinon retourne false。 Attention, si la commande a été entièrement passée, l’annulation échouera。

Les contrats à terme et les contrats à durée indéterminée

Les opérations à terme de monnaie numérique diffèrent un peu des opérations en espèces. Les fonctions de transactions en espèces décrites ci-dessus s’appliquent également aux opérations à terme. Avant de procéder à des opérations à terme de monnaie numérique, il faut se familiariser avec les opérations manuelles sur le site et comprendre les concepts de base, tels que l’ouverture de position, l’élimination de position, la totalité de la position, l’élimination de la position, le levier, la perte de position, les gains et les pertes flottants, les garanties et les formules de calcul correspondantes.

Les contrats à durée indéterminée sont similaires aux contrats à terme, mais sans la notion de détention simultanée d’un espace libre.

Si l’échange prend en charge simultanément des contrats à terme en espèces, comme les contrats à terme OKEX et Huobi, il est nécessaire de sélectionner séparément dans l’interface de l’échange l’option OKEX et l’option Huobi.

Type de contrat de définition

La première étape du trading à terme consiste à définir le contrat à négocier, par exemple dans le cas des futures OKEX, en choisissant une paire de transactions BTC lors de la création d’un portefeuille ou d’une revue. Le code doit également être configuré comme contrat de la semaine en cours, de la semaine prochaine ou trimestriel.invalid contract typeContrairement aux paires de change, les contrats à terme sont souvent couverts par des monnaies de change telles que le BTC. Les paires de change qui ajoutent du BTC sont généralement représentées par des paires de change BTC_USD couvertes par du BTC. S’il existe des contrats à terme qui sont couverts par de l’USDT, il est nécessaire de créer des paires de change BTC_USDT.Une fois la paire de transactions configurée, il faut également configurer des types de contrats spécifiques, tels que permanents, hebdomadaires, hebdomadaires, etc. Une fois le contrat configuré, il est possible d’effectuer des opérations d’acquisition, d’achat et de vente.

Il existe des contrats de base de pièces et de base USDT tels que Binance, OKEX, HuobiDM, etc. Il est nécessaire de les différencier lors de l’ajout de contrats de configuration de disque dur. Les paramètres spécifiques sont les suivants:

//OKEX期货
exchange.SetContractType("swap")        // 设置为永续合约
exchange.SetContractType("this_week")   // 设置为当周合约
exchange.SetContractType("next_week")   // 设置为次周合约
exchange.SetContractType("quarter")     // 设置为季度合约

//HuobiDM
exchange.SetContractType("this_week")   // 设置为当周合约 
exchange.SetContractType("next_week")   // 设置为次周合约
exchange.SetContractType("quarter")     // 设置为季度合约
exchange.SetContractType("swap")        // 设置为永续合约

//币安期货
exchange.SetContractType("swap")   // 设置为永续合约,注意币本位和USDT本位都存在永续
exchange.SetContractType("quarter")   // 设置为当季合约
exchange.SetContractType("next_quarter")  // 设置为次季合约

//BitMEX
exchange.SetContractType("XBTUSD")    // 设置为永续合约
exchange.SetContractType("XBTM19")  // 具体某个时间结算的合约,详情登录BitMEX查询各个合约代码

//GateIO
exchange.SetContractType("swap")      // 设置为永续合约,不设置默认为swap永续合约。 

//Deribit
exchange.SetContractType("BTC-27APR18")  // 具体某个时间结算的合约,详情参看Deribit官网。

GetPosition détient une position

Obtenir une liste d’informations sur les positions actuelles, OKEX ((OKCOIN) futures peuvent être transmises dans un paramètre, en spécifiant le type de contrat à obtenir. Si aucune position est conservée, retourne la liste vide[]Les informations de détention sont renvoyées comme suit:

Type de données Nom de la variable illustrer

La structure initiale renvoyée par l’échangeur d’object OKCoin est de 10 ou 20, OK Futures retourne le mode de stockage total à 10, car l’API native ne le prend pas en charge. “number” signifie “montant” et “réserve”, OKCoin signifie “nombre de contrats” Le nombre de points de congélation. Le nombre de dépôts et le prix de dépôt. Le numéro de la marge de garantie est gelé. Le nombre de bénéfices est le nombre de bénéfices réalisés par une position pleine de BTC/LTC. Le nombre de bénéfices est le nombre de bénéfices réalisés par une position pleine de OKCoin. Le PD_SHORT correspond à la position vide du jour précédent, PD_LONG correspond à la position vide du jour précédent, PD_SHORT correspond à la position vide du jour précédent, PD_SHORT correspond à la position vide du jour précédent, et PD_SHORT correspond à la position vide du jour précédent. Le type de transmission spécifique du paramètre SetContractType

function main(){
    exchange.SetContractType("this_week");
    var position = exchange.GetPosition();
    if(position.length>0){ //特别要注意引用前要先判断position长度再引用,否则会出错
        Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
            position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,"ContractType:", position[0].ContractType)
    }
}

Période de clôture des positions futures

Pour cela, il faut d’abord définir la taille du levier et le mode d’appel:exchange.SetMarginLevel(10)Le nombre 10 signifie que le levier est multiplié par 10, et la taille de levier soutenue par le levier correspond à la taille de levier correspondant à l’échange.Attention, le levier doit être configuré sur le marché et le code doit être cohérent avec le marché, sinon il y aura des erreurs│ ou non, en utilisant le levier par défaut │ La direction de la transaction est définie, puis le mode d’appel:exchange.SetDirection(Direction)La banque a également déclaré que le taux d’intérêt de la transaction était de 0,3%.Contrairement aux contrats à terme, si un contrat à durée indéterminée n’a pas de concept de détention simultanée de positions sur le marché, c’est-à-dire qu’il n’est pas permis de détenir une position sur un seul poste, la détention sur le marché de positions sur le marché sera automatiquement libérée.buyetsellDisponible. Si la position bi-directionnelle est prise en charge, une configuration est nécessaire.closebuy,closebuyLes liens spécifiques:

Opérations Paramètre de SetDirection Fonction de commande
Ouvrir une position exchange.SetDirection(“buy”) exchange.Buy()
Périmètre exchange.SetDirection(“closebuy”) exchange.Sell()
La mise en place d’une position exchange.SetDirection(“sell”) exchange.Sell()
Pénurie exchange.SetDirection(“closesell”) exchange.Buy()

Enfin, il y a le code de position d’ouverture et de clôture spécifique, le montant de la commande varie selon les bourses, par exemple, les contrats à terme huobi sont par tranche, 100 dollars par tranche. Attention, les contrats à terme ne supportent pas le prix du marché.

function main(){
    exchange.SetContractType("this_week")    // 举例设置 为OKEX期货 当周合约
    price = exchange.GetTicker().Last
    exchange.SetMarginLevel(10) //设置杠杆为10倍 
    exchange.SetDirection("buy") //设置下单类型为做多 
    exchange.Buy(price+10, 20) // 合约数量为20下单 
    pos = exchange.GetPosition()
    Log(pos)
    Log(exchange.GetOrders()) //查看是否有未成交订单
    exchange.SetDirection("closebuy"); //如果是永续合约,直接设置exchange.SetDirection("sell")
    exchange.Sell(price-10, 20)
}

Voici un exemple de stratégie spécifique pour une position complètement nulle:

function main(){
    while(true){
        var pos = exchange.GetPosition()
        var ticker = exchange.GetTicekr()
        if(!ticker){
            Log('无法获取ticker')
            return
        }
        if(!pos || pos.length == 0 ){
            Log('已无持仓')
            return
        }
        for(var i=0;i<pos.length;i++){
            if(pos[i].Type == PD_LONG){
                exchange.SetContractType(pos[i].ContractType)
                exchange.SetDirection('closebuy')
                exchange.Sell(ticker.Buy, pos[i].Amount - pos[i].FrozenAmount)
            }
            if(pos[i].Type == PD_SHORT){
                exchange.SetContractType(pos[i].ContractType)
                exchange.SetDirection('closesell')
                exchange.Buy(ticker.Sell, pos[i].Amount - pos[i].FrozenAmount)
            }
        }
        var orders = exchange.Getorders()
        Sleep(500)
        for(var j=0;j<orders.length;j++){
            if(orders[i].Status == ORDER_STATE_PENDING){
                exchange.CancelOrder(orders[i].Id)
            }
        }
    }
}

Le trading de devises numériques

Il est nécessaire de passer en compte à effet de levier dans le code, le reste est identique à la transaction en espèces.

En utilisant exchange.IO (“trade_margin”) pour passer en mode compte à puce, les commandes et les actifs de compte à puce accéderont à l’interface de levier de l’échange. Il est possible de revenir au mode de compte ordinaire en utilisant exchange.IO (“trade_normal”).

Les échanges suivants sont pris en charge:

  • OKEX V3: Le modèle de compte à effet de levier est différent de celui des paires de transactions ordinaires, certaines paires de transactions peuvent ne pas l’être.
  • Bitcoin: Le modèle de compte à effet de levier est différent de celui des paires ordinaires, certaines paires ne le sont pas.
  • ZB: les fonds peuvent être transférés en tant que QC, le secteur de négociation à effet de levier, l’indépendance des fonds entre les différentes paires de transactions, c’est-à-dire le nombre de pièces QC sous la paire de négociation ETH_QC, qui n’est pas visible dans BTC_QC
  • FCoin
  • Nom de l’entreprise: Binance

Commodité à terme

Il existe une grande différence entre le trading à terme de marchandises et le trading à terme de devises numériques. Tout d’abord, le temps de négociation des futures sur marchandises est court, les devises numériques sont négociées 24 heures sur 24; le protocole des futures sur marchandises n’est pas une API REST courante; la fréquence des transactions et les limites de nombre de transactions des futures sur marchandises, les devises numériques sont très souples, etc.

Les fournisseurs de services de négociation programmée ont demandé une licence logicielle aux différents fournisseurs de services de négociation à terme. Les utilisateurs peuvent utiliser la licence logicielle sans avoir à demander directement. Les fournisseurs de services de négociation à terme peuvent consulter la liste des demandes de FMZ. Les utilisateurs peuvent consulter la liste des demandes de FMZ sans avoir à demander directement.

Grâce à l’architecture de la plate-forme FMZ, les utilisateurs peuvent également ajouter plusieurs comptes de courtier à terme et réaliser certaines fonctionnalités que d’autres logiciels de négociation programmée de futures sur les marchandises ne peuvent pas, telles que la synthèse de ticks à haute fréquence, voir https://www.fmz.com/bbs-topic/1184

Cadre politique

Tout d’abord, comme il ne s’agit pas d’une transaction 24h et nécessite une opération de connexion, il est nécessaire de juger de l’état du lien avant de procéder à la transaction.exchange.IO("status")pourtrueSi vous n’avez pas réussi à vous connecter à l’échange. Si vous n’avez pas réussi à vous connecter à l’échange. Si vous n’avez pas réussi à vous connecter à l’API._C(exchange.SetContractType,"MA888")Le débarquement a été effectué dans un endroit très calme, où l’on a pu voir des personnes.

Le code d’acquisition et de négociation des futures sur marchandises est le même que celui des futures sur monnaie numérique, mais il y a des différences et des points à prendre en compte.

function main(){
    _C(exchange.SetContractType,"MA888") //没登陆成功是无法订阅合约的,最好重试一下
    while(true){
        if(exchange.IO("status")){
            var ticker = exchange.GetTicker()
            Log("MA888 ticker:", ticker)
            LogStatus(_D(), "已经连接CTP !")//_D获取事件
        } else {
            LogStatus(_D(), "未连接CTP !")
            Sleep(1000)
        }
    }
}

Il est recommandé d’utiliser le trading de la base de données de commodities futures (voir plus loin), le code est alors très simple et n’a pas besoin de traiter de détails fastidieux.

function main() {
    // 使用了商品期货类库的CTA策略框架
    $.CTA(Symbols, function(st) {
        var r = st.records
        var mp = st.position.amount
        var symbol = st.symbol
        /*
        r为K线, mp为当前品种持仓数量, 正数指多仓, 负数指空仓, 0则不持仓, symbol指品种名称
        返回值如为n: 
            n = 0 : 指全部平仓(不管当前持多持空)
            n > 0 : 如果当前持多仓,则加n个多仓, 如果当前为空仓则平n个空仓,如果n大于当前持仓, 则反手开多仓
            n < 0 : 如果当前持空仓,则加n个空仓, 如果当前为多仓则平n个多仓,如果-n大于当前持仓, 则反手开空仓
            无返回值表示什么也不做
        */
        if (r.length < SlowPeriod) {
            return
        }
        var cross = _Cross(TA.EMA(r, FastPeriod), TA.EMA(r, SlowPeriod));
        if (mp <= 0 && cross > ConfirmPeriod) {
            Log(symbol, "金叉周期", cross, "当前持仓", mp);
            return Lots * (mp < 0 ? 2 : 1)
        } else if (mp >= 0 && cross < -ConfirmPeriod) {
            Log(symbol, "死叉周期", cross, "当前持仓", mp);
            return -Lots * (mp > 0 ? 2 : 1)
        }
    });
}

Mode d’acquisition des données CTP

Les futures sur marchandises utilisent le protocole CTP, tous les mouvements et les transactions d’ordres ne sont informés qu’une fois qu’il y a un changement, tandis que la recherche d’ordres, de comptes et de positions est une recherche active. Il convient donc à la stratégie de haute fréquence d’écriture actionnée par événement.GetTickerGetDepthGetRecordsIl y a toujours des données en cache pour obtenir les dernières données. Il n’y a pas de données en attente de données, donc la stratégie peut ne pas utiliser Sleep. Lorsque la situation change, les ticker, la profondeur et les enregistrements sont mis à jour.

Si vous voulez obtenir des données à chaque fois que vous obtenez des informations, même des données anciennes, vous pouvez passer en mode de mise à jour instantanée des informations.exchange.IO("mode", 0)Les stratégies ne peuvent plus être écrites comme étant actionnées par des événements, il faut ajouter un événement SLeep pour éviter un cycle de mort rapide. Certaines stratégies de faible fréquence peuvent utiliser ce mode, la stratégie est simple à utiliser.exchange.IO("mode", 1)Vous pouvez réinitialiser le mode de cache par défaut.

Si vous utilisez un contrat individuel, vous pouvez utiliser le mode par défaut. Cependant, si vous utilisez plusieurs contrats, il est possible qu’un contrat ne soit pas mis à jour, ce qui entraîne un blocage de l’interface de mise à jour, et que les autres contrats ne soient pas mis à jour. Pour résoudre ce problème, vous pouvez utiliser le mode de mise à jour immédiate, mais sans écrire de stratégie haute fréquence.exchange.IO("wait")Si plusieurs objets d’échange sont ajoutés, ce qui est rare dans les futures sur marchandises, il est possible d’utiliserexchange.IO("wait_any")L’Index retourné indique l’index de la bourse qui a été renvoyée.

Le changement de tick a été envoyé à:{Event:"tick", Index:交易所索引(按实盘上交易所添加顺序), Nano:事件纳秒级时间, Symbol:合约名称} La commande a été envoyée à:{Event:"order", Index:交易所索引, Nano:事件纳秒级时间, Order:订单信息(与GetOrder获取一致)}

À ce stade, la structure de la stratégie peut être écrite comme suit :

function on_tick(symbol){
    Log("symbol update")
    exchange.SetContractType(symbol)
    Log(exchange.GetTicker())
}

function on_order(order){
    Log("order update", order)
}

function main(){
    while(true){
        if(exchange.IO("status")){ //判断链接状态
            exchange.IO("mode", 0)
            _C(exchange.SetContractType, "MA888")//订阅MA,只有第一次是真正的发出订阅请求,接下来都是程序切换,不耗时间。
            _C(exchange.SetContractType, "rb888")//订阅rb
            while(true){
                var e = exchange.IO("wait")
                if(e){
                    if(e.event == "tick"){
                        on_tick(e.Symbol)
                    }else if(e.event == "order"){
                        on_order(e.Order)
                    }
                }
           }
        }else{
            Sleep(10*1000)
        }
    }
}

Différence entre les futures sur les marchandises et les monnaies numériques

Notez également la différence entre les futures sur les marchandises et les échanges de devises numériques. Comme GetDepth, il n’y a en fait qu’un seul niveau de profondeur (les frais de profondeur de 5 niveaux sont coûteux), et GetTrades n’obtient pas d’historique de transaction (ils sont basés sur des simulations de changement de position, pas de véritable enregistrement de transaction). Les futures sur les marchandises ont des limites d’aval et d’arrêt.

Créer un contrat

exchange.IO ((“instruments”): renvoie la liste de tous les contrats de l’échange sous la forme d’un dictionnaire. exchange.IO (((“products”): renvoie la liste de tous les produits de l’échange sous forme de dictionnaire. exchange.IO ((“subscribed”): renvoie les contrats qui ont été souscrits, le format est le même, il ne prend en charge que les disques fixes.

Les futures CTP traditionnellesContractTypeIl s’agit de l’identifiant du contrat, en majuscules ou en minuscules.exchange.SetContractType("au1506")Les contrats en série sont des contrats de code 888 tels que MA888, les contrats en série d’indices 000 tels que MA000, 888 et 000 sont des contrats de contrats virtuels qui ne supportent que la rétro-mesure, et les contrats physiques ne supportent que l’acquisition.Cependant, le langage Mac peut manipuler les contrats de dominance, et le programme change automatiquement de position, c’est-à-dire qu’il efface les positions non dominantes et crée de nouvelles positions sur les positions dominantes.

Si la connexion n’est pas réussie, le contrat ne peut pas être configuré, mais il revient immédiatement, donc vous pouvez réessayer avec _C, sachant que la connexion CTP est terminée. Une fois la connexion réussie, la réinitialisation du contrat ne prend pas de temps et ne génère pas de véritable accès au réseau.

Ouverture et clôture des positions

SetDirectionLes directions sont disponibles.buy, closebuy, sell, closesellQuatre paramètres, plus de produits à termeclosebuy_todayetclosesell_todayIl a dit: “Je ne suis pas d’accord.closebuy/closesellPour les futures à terme, il suffit de distinguer les variétés de la période précédente de la période actuelle et de la période antérieure, ce qui peut affecter les frais de traitement, il est donc nécessaire de donner la priorité à la période précédente. Pour les futures traditionnelles CTP, il est possible de définir un deuxième paramètre de 1 ou 2 ou 3 piles, respectivement, pour les piles de spéculation, les piles de profit et les piles de protection, sans configurer de spéculation implicite.Les opérations spécifiques d’achat et de vente, d’acquisition de positions, d’acquisition d’ordres, de retrait de factures, d’acquisition de comptes sont les mêmes que les transactions à terme de devises numériques, voir le chapitre précédent.

Opérations Paramètre de SetDirection Fonction de commande
Ouvrir une position exchange.SetDirection(“buy”) exchange.Buy()
Périmètre exchange.SetDirection(“closebuy”) exchange.Sell()
La mise en place d’une position exchange.SetDirection(“sell”) exchange.Sell()
Pénurie exchange.SetDirection(“closesell”) exchange.Buy()

L’exemple ci-dessous est une fonction de placement fixe. Attention, cet exemple est trop simple, mais il faut également considérer une série de questions telles que si vous êtes dans le temps de négociation, comment faire un test d’achat, quelle est la quantité de commande maximale, si la fréquence est trop élevée, en particulier si le cours est en baisse ou en rupture de stock.Il est recommandé d’utiliser une bibliothèque de classe bien emballée sur la plate-forme.Il est recommandé d’apprendre le code source de la bibliothèque.

function Cover(contractType, amount, slide) {
    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType != contractType) {
            continue;
        }
        var depth = _C(e.GetDepth);
        if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
            exchange.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
            exchange.Sell(depth.Bids[0]-slide, amount, contractType, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
        } else {
            exchange.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
            exchange.Buy(depth.Asks[0]+slide, amount, contractType, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
        }
    }
}

Commodity Futures prend en charge les types d’ordres personnalisés (soutenu par le disque dur, non pris en charge par la rétroaction), spécifie le mode de stockage ultérieur, ajoutée dans le coffre_Le fond de la coque, par exemple.

exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")

Les suffixes spécifiques sont:

  • ioc est terminé immédiatement, sinon annuler THOST_FTDC_TC_IOC
  • gfs Cette section est valide THOST_FTDC_TC_GFS
  • gfd est valide le jour même THOST_FTDC_TC_GFD
  • gtd valide avant la date spécifiée THOST_FTDC_TC_GTD
  • gtc valable avant révocation
  • gfa La collecte des enchères est valide

Interface facile à utiliser

Par défaut, l’interface CTP est activée dans le Commodity Futures Trading, et si nécessaire, elle peut être remplacée par l’interface EasyPay. La même méthode d’appel est utilisée via l’emballage FMZ. La différence est que les comptes, les commandes et les dépôts sont en mode de poussée, de sorte que le conservateur maintient ces données localement et ne renvoie pas immédiatement la demande lors de l’appel de l’interface correspondante.

Les types de commandes personnalisées de l’EasyShare sont les suivants:

  • gfd est valide le jour même TAPI_ORDER_TIMEINFORCE_GFD
  • gtc est valide avant la révocation TAPI_ORDER_TIMEINFORCE_GTC
  • gtd valide avant la date spécifiée TAPI_ORDER_TIMEINFORCE_GTD
  • La partie fak est acquise et la partie restante est annulée
  • ioc est terminé immédiatement, ou annulé TAPI_ORDER_TIMEINFORCE_FAK
  • TAPI_ORDER_TIMEINFORCE_FOK: Fok n’a pas réussi à conclure complètement sa transaction et a annulé la totalité de sa transaction

Fonctions globales couramment utilisées

Le journal Log et la diffusion sur WeChat

Dans l’interface du disque dur, un journal Log, suivi d’une chaîne de caractères et d’un caractère @, le message est envoyé dans la file d’attente de l’expéditeur, et est envoyé directement après avoir lié WeChat ou Telegram.Log('推送到微信@')

La couleur du journal est personnalisableLog('这是一个红色字体的日志 #ff0000')#ff0000Pour les couleurs RGB, 16 chiffres

Tous les fichiers journaux existent dans la base de données sqlit sur disque dans le répertoire de l’hôte. Ils peuvent être téléchargés et ouverts avec le logiciel de la base de données, et peuvent également être utilisés pour copier la récupération de la sauvegarde (le nom de la base de données est identique à l’id du disque).

LogProfit imprime les résultats

Enregistrer les gains et tracer une courbe de gains sur l’interface du disque, qui peut être conservée après le redémarrage du disque.LogProfit(1000)AttentionLogProfitLes paramètres de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur.

Affichage de la barre d’état LogStatus (avec le tableau)

Etant donné que les journaux sont sauvegardés et mis à jour, si vous avez besoin d’une seule information qui n’est pas sauvegardée, vous pouvez utiliserLogStatusfonction.LogStatusLes paramètres sont des chaînes de caractères qui peuvent également être utilisés pour représenter des informations de tableaux.

Voici un exemple d’un tableau montrant l’emplacement de l’état du disque:

var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]}; 
LogStatus('`' + JSON.stringify(table) + '`'); // JSON序列化后两边加上`字符, 视为一个复杂消息格式(当前支持表格) 
LogStatus('第一行消息\n`' + JSON.stringify(table) + '`\n第三行消息'); // 表格信息也可以在多行中出现 
LogStatus('`' + JSON.stringify([table, table]) + '`'); // 支持多个表格同时显示, 将以TAB显示到一组里 
LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n'); // 上下排列显示多个表

Le sommeil.

Les paramètres sont des millisecondes, commeSleep(1000)Une seconde pour le repos. En raison de la limitation de la fréquence d’accès à toutes les transactions, la stratégie générale consiste à ajouter du temps de repos à la boucle morte.

_G Pour sauvegarder les données

Si vous souhaitez conserver des informations durables, vous pouvez les supprimer de votre disque dur et les réinitialiser._GIl s’agit d’un outil très pratique qui permet d’enregistrer le contenu sérialisé en JSON._GLa fonction est écrite dansonexit()Ainsi, chaque fois que la stratégie est arrêtée, les informations nécessaires sont automatiquement enregistrées. Si vous souhaitez conserver plus de données formatées, vous pouvez utiliser le fichier de sauvegarde._Les fonctions G sont moins utiles et peuvent être écrites directement dans une base de données en Python.

function onexit(){
    _G('profit', profit)
}
function main(){
    _G("num", 1); // 设置一个全局变量num, 值为1 s
    _G("num", "ok"); // 更改一个全局变量num, 值为字符串ok 
    _G("num", null); // 删除全局变量 num 
    _G("num"); // 返回全局变量num的值,如果不存在返回null

    var profit = 0
    if(_G('profit')){
        profit = _G('profit')
    }
}

_Fonction de précision N

Pour contrôler la précision des prix et des quantités lors de la commande, FMZ a intégré la fonction N pour déterminer le nombre de petits chiffres à conserver, comme_N(4.253,2)Le résultat est de 4,25.

_C. Renouvellement automatique

L’API de l’échange d’appels ne garantit pas le succès à chaque fois qu’elle est utilisée._C est une fonction qui réessaie automatiquement. Elle appelle la fonction spécifiée jusqu’à ce qu’elle soit renvoyée avec succès._C(exchange.GetTicker), l’intervalle de répétition par défaut est de 3 secondes. La fonction_CDelay peut être appelée pour contrôler l’intervalle de répétition, par exemple _CDelay(1000), et la fonction_C de changement est recommandée pour un intervalle de répétition de 1 seconde.GetTicker(),exchange.GetDepth,GetTrade,GetRecords,GetAccount,GetOrders, GetOrderLe C++ est un langage de programmation qui permet d’accéder à des données de manière transparente et transparente, et d’enregistrer les données de manière transparente.

CancelOrderImpossible d’utiliser la fonction_C, car les retraits échouent pour diverses raisons. Si une unité a été achetée, la retraite retourne l’échec, et l’utilisation de la fonction_C entraîne des essais répétés.

_Les fonctions C peuvent aussi être transmises en arguments, et sont utilisées dans des fonctions personnalisées.

function main(){
    var ticker = _C(exchange.GetTicker)
    var depth = _C(exchange.GetDepth)
    var records = _C(exchange.GetRecords, PERIOD_D1) //传入参数
}

_D fonction de date

Appel direct_D()Renvoie la chaîne de caractères de l’heure actuelle, comme:2019-08-15 03:46:14。 Si elle est appelée pendant le test, elle renvoie le temps de test. Vous pouvez utiliser la fonction _D pour déterminer le temps, par exemple:_D().slice(11) > '09:00:00':

_D(timestamp,fmt), qui convertit la colonne de temps ms en une chaîne de temps, comme_D(1565855310002)Le paramètre fmt est le format temps, par défaut.yyyy-MM-dd hh:mm:ss

F