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%90/1
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。

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.
É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 type。**Contrairement 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,closebuy。**Les 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.GetTicker、GetDepth、GetRecordsIl 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
Fonction d'indicateur TA
Pour certaines fonctions d'indicateur couramment utilisées, telles que MA\MACD\KDJ\BOLL et autres, la plate-forme FMZ est directement intégrée, les indicateurs spécifiques peuvent être consultés dans la documentation de l'API.
Il est préférable de déterminer la longueur de la ligne K avant d'utiliser la fonction d'indicateur.nullSi la longueur de K de l'entrée est de 100 et que la période de calcul de MA est de 10, alors les 9 premières valeurs sont nuls et les valeurs suivantes sont calculées normalement.
JavaScript prend également en charge la version complète de talib, en tant que support de bibliothèque tiers, appeléetalib.CCI(records)Pour Python, il est possible d'installer la bibliothèque talib par vous-même, mais il n'est pas possible de l'installer en utilisant simplement pip car il faut la compiler. Vous pouvez rechercher la méthode d'installation par vous-même.
Les fonctions de pointer peuvent être transmises dans n'importe quel tableau en plus des données de la ligne K.
function main(){
var records = exchange.GetRecords(PERIOD_M30)
if (records && records.length > 9) {
var ma = TA.MA(records, 14)
Log(ma)
}
}
Fonctions couramment utilisées dans JavaScript
Voici quelques fonctions JavaScript couramment utilisées sur le disque dur:
Date.now()Retourner à la barre de temps actuelleparseFloat()Transformer une chaîne de caractères en chiffres, par exempleparseFloat("123.21")parseInt()Transformer une chaîne en un nombre entiernum.toString()Transformer un nombre en une chaîne de caractères, num en une variable numériqueJSON.parse()formater des chaînes Json, commeJSON.parse(exchange.GetRawJSON())- Les fonctions de la bibliothèque Math de JavaScript sont les suivantes
Math.max(),Math.abs()Les opérations mathématiques courantes et autres, voir: https://www.w3school.com.cn/jsref/jsref_obj_math.asp - La base de données mathématique de tiers en JavaScript de FMZ est fournie par: https://mathjs.org/
- La bibliothèque d'underscore JavaScript tiers citée par FMZ est recommandée pour faciliter la gestion de nombreux Js.
Bibliothèque de modèles
Il y a beaucoup de choses à prendre en compte pour écrire une stratégie en direct, comme acheter 5 pièces pour une simple fonction, nous devons prendre en compte: le solde actuel est-il suffisant? Quel est le prix de la commande? Quelle est la précision?
Les bibliothèques JavaScript de crypto-monnaie et de futures marchandises sont intégrées par défaut et ne doivent pas être répliquées. Les autres bibliothèques de modèles peuvent être trouvées sur la place des stratégies à l'adresse https://www.fmz.com/square/20/1. Les bibliothèques de modèles peuvent être copiées et sauvegardées, et les bibliothèques sélectionnées peuvent être utilisées lors de la création de votre propre stratégie.
Les fonctions de modèle JavaScript sont$Pour commencer, Python estextLe début.
Bibliothèque de transactions en monnaie numérique
L'adresse du code source: https://www.fmz.com/strategy/10989 , est déjà intégré et n'a pas besoin d'être copié. Les méthodes d'implémentation de fonctions spécifiques peuvent être directement référencées dans le code source.
Pour accéder au compte:
$.GetAccount(e)
Log($.GetAccount()); // 获取账户信息, 带容错功能
Log($.GetAcccount(exchanges[1]));
Je vous demande de retirer:
$.Buy/Sell(e, amount)
$.Buy(0.3); // 主交易所买入0.3个币
$.Sell(0.2); // 主交易所卖出0.2个币
$.Sell(exchanges[1], 0.1); // 次交易所卖出0.1个币
$.CancelPendingOrders(e, orderType)
$.CancelPendingOrders(); // 取消主交易所所有委托单
$.CancelPendingOrders(ORDER_TYPE_BUY); // 取消主交易所所有的买单
$.CancelPendingOrders(exchanges[1]); // 取消第二个交易所所有订单
$.CancelPendingOrders(exchanges[1], ORDER_TYPE_SELL); // 取消第二个交易所所有的卖单
Le jugement est croisé:
$.Cross(periodA, periodB) / $.Cross(arr1, arr2);
var n = $.Cross(15, 30);
var m = $.Cross([1,2,3,2.8,3.5], [3,1.9,2,5,0.6])
如果 n 等于 0, 指刚好15周期的EMA与30周期的EMA当前价格相等
如果 n 大于 0, 比如 5, 指15周期的EMA上穿了30周期的EMA 5个周期(Bar)
如果 n 小于 0, 比如 -12, 指15周期的EMA下穿了30周期的EMA 12个周期(Bar)
如果传给Cross不是数组, 则函数自动获取K线进行均线计算
如果传给Cross的是数组, 则直接进行比较
$.withdraw ((e, currency, address, amount, fee, password) est une fonction de retrait:
$.withdraw(exchange, "btc", "0x.........", 1.0, 0.0001, "***")
Bibliothèque des échanges à terme sur les marchandises
La bibliothèque de négociation à terme de marchandises est stable et recommandée. L'adresse du code source: https://www.fmz.com/strategy/12961 。 est intégrée et n'a pas besoin d'être copiée。
Bibliothèque du CTA
- Le disque dur mappe automatiquement l'indice à la continuité principale
- Le transfert est automatique.
- La rétroaction peut spécifier une mappage comme rb000/rb888, c'est-à-dire la mappage des transactions de l'indice rb à la continuité principale.
- On peut aussi le transposer à d'autres contrats, par exemple rb000/MA888 qui est la ligne K de l'indice de rb pour traiter la continuité de la force principale de MA.
function main() {
$.CTA("rb000,M000", function(r, mp) {
if (r.length < 20) {
return
}
var emaSlow = TA.EMA(r, 20)
var emaFast = TA.EMA(r, 5)
var cross = $.Cross(emaFast, emaSlow);
if (mp <= 0 && cross > 2) {
Log("金叉周期", cross, "当前持仓", mp);
return 1
} else if (mp >= 0 && cross < -2) {
Log("死叉周期", cross, "当前持仓", mp);
return -1
}
});
}
Exemple d'appel de classe
function main() {
var p = $.NewPositionManager();
p.OpenShort("MA609", 1);
p.OpenShort("MA701", 1);
Log(p.GetPosition("MA609", PD_SHORT));
Log(p.GetAccount());
Log(p.Account());
Sleep(60000 * 10);
p.CoverAll("MA609");
LogProfit(p.Profit());
Log($.IsTrading("MA609"));
// 多品种时使用交易队列来完成非阻塞的交易任务
var q = $.NewTaskQueue();
q.pushTask(exchange, "MA701", "buy", 3, function(task, ret) {
Log(task.desc, ret)
})
while (true) {
// 在空闲时调用poll来完成未完成的任务
q.poll()
Sleep(1000)
}
}
Galerie de dessins
Comme la fonction graphique originale est plus complexe, et sera présentée dans le prochain tutoriel, il est recommandé aux débutants d'utiliser directement la bibliothèque de classes graphiques, un diagramme de découpage graphique très simple, un diagramme de ligne K, etc. FMZ a une bibliothèque de classes simple intégrée, qui peut être vue sur la page d'édition de la stratégie. Si elle n'est pas intégrée, l'utilisateur doit la copier et la sauvegarder lui-même pour pouvoir sélectionner des références dans la stratégie.
Le projet de loi est en cours d'élaboration.
Le code source de la bibliothèque de lignes de dessin de Python est le suivant:
Par exemple:
function main() {
while (true) {
var ticker = exchange.GetTicker()
if (ticker) {
$.PlotLine('Last', ticker.Last) //可以同时画两条线,Last是这条线的名字
$.PlotLine('Buy', ticker.Buy)
}
Sleep(6000)
}
}
Paramètres de stratégie
Sous l'éditeur de stratégie, il y a un paramètre de stratégie, qui correspond à une variable globale de la stratégie, accessible à n'importe quel endroit du code. Les paramètres de stratégie peuvent être modifiés sur l'interface du disque dur et prendre effet après le redémarrage. Certains paramètres peuvent donc être définis comme paramètres et peuvent être modifiés sans modifier la stratégie.

- Nom de la variable: c'est-à-dire les numéros, les chaînes, les boîtes de commande, etc. de la figure ci-dessus, peuvent être utilisés directement dans le groupe de stratégie.
- décrire: Nom des paramètres dans l'interface de la stratégie, pour faciliter la compréhension de leur signification.
- À noter: une explication détaillée des paramètres, qui s'affiche lorsque la souris reste sur le paramètre.
- taper: Le type de ce paramètre est décrit ci-dessous.
- Par défaut: valeur par défaut de ce paramètre
Les types de chaînes de caractères et de chiffres sont faciles à comprendre et sont les plus couramment utilisés. La case déroulante affiche les options dans l'interface des paramètres.BTC|USDT|ETH, si USDT est sélectionné dans le menu déroulant de la page de paramètres, la valeur de SYMBOL dans la stratégie est l'index 1 de USDT. La case à cocher est une case à cocher, et la case à cocher est vraie, sinon elle est fausse.
Les paramètres peuvent être réglés de différentes manières: https://www.fmz.com/bbs-topic/1306
Backtesting de stratégie
Lorsque vous avez terminé de quantifier une stratégie, vous pouvez tester votre stratégie à l'aide de données historiques pour voir comment votre stratégie a été rentable dans les données historiques. Bien sûr, les résultats de la rétroanalyse sont à titre de référence seulement. La plate-forme quantitative FMZ prend en charge la rétroanalyse des devises numériques en espèces, des futures, des contrats à durée indéterminée BitMEX et des futures sur marchandises, dont les devises numériques soutiennent principalement les variétés dominantes.
Les tests JavaScript sont effectués dans le navigateur, les tests Python sont effectués sur les hôtes, et les hôtes publics sont fournis par la plate-forme. Les tests Mac ont besoin de paramètres supplémentaires, voir la documentation Mac.
Mécanisme de rétroaction
Le mécanisme de réévaluation onbar est basé sur des lignes K, c'est-à-dire que chaque ligne K génère un point de temps de réévaluation, à partir duquel des informations telles que le prix d'ouverture et de clôture, le volume des transactions de la ligne K actuelle, ainsi que des informations sur les lignes K historiques avant cette heure peuvent être obtenues. L'inconvénient de ce mécanisme est évident: sur une ligne K, un seul achat et une vente peuvent être générés, le prix de clôture étant généralement le prix de clôture de la ligne K.
La plate-forme FMZ résout les deux types de résouts: résous de niveau analogue et résous de niveau disque. La résous de niveau analogue génère un tick de simulation basé sur la période de la ligne K de base, qui génère 14 points de temps de résous sur chaque période de la ligne K de base.**Le niveau de disque réel est celui des ticks réellement collectés, environ une fois toutes les quelques secondes, et actuellement partiellement pris en charge par True Depth (contient 20 fichiers), True One-to-One.**Le mécanisme de rétroaction de la FMZ permet à la stratégie de négocier plusieurs fois sur une seule ligne K, évitant ainsi de conclure uniquement des transactions à cours liquide, plus précises et en tenant compte de la vitesse de rétroaction. Des instructions spécifiques peuvent être consultées: https://www.fmz.com/digest-topic/4009
Le cadre stratégique de la rétroaction est le même que celui du disque dur, c'est-à-dire qu'il s'agit d'une boucle morte. Comme la rétroaction est sautée à différents points de rétroaction, il est possible de ne pas utiliser Sleep, qui saute automatiquement au prochain point de temps à la fin d'une boucle.Sleep(10)Pour éviter la mort.
Capture d'écran de la réception
Le moteur de retesting est basé sur le prix d'achat et le prix de vente au moment de la retestation. Si le prix d'achat est supérieur à celui de la vente, une transaction est effectuée.
Paramètres de la page de retour
-
- La page de choix de la revue, à gauche la page d'édition de la stratégie.
-
- le début et la fin de la période de relevé, car les données ne sont pas complètes, le relevé peut commencer directement à partir de l'heure à laquelle les données sont disponibles.
-
- Retour à la réalité
GetRecords()La périodicité par défaut d'une fonction peut également être définie dans le code.
- Retour à la réalité
-
- Le choix du mécanisme de rétroaction.
-
- Afficher ou masquer les réglages de répétition.
-
- Le nombre maximal de journaux, de données de revenus, de données de graphiques, etc., afin d'éviter que trop de données entraînent un blocage du navigateur.
-
- Les ticks de fond sont générés en fonction de la période de la ligne K.
-
- Le dérapage des transactions.
-
- Tolérance aux erreurs, qui permet de simuler les erreurs de requête des API et de vérifier la tolérance des stratégies.
-
- est-ce que l'icône de tendance est dessinée, si la fonction d'indicateur de TA est utilisée dans la rétroanalyse, elle s'affiche sur l'icône, les ventes et les achats sont également marqués.
-
- Le réglage des frais
-
- Ajout d'échanges - paires et actifs.
-
- paramètre de retour de paramètres, si le paramètre est numérique et prend en charge un paramètre d'optimisation de touche, passe automatiquement par le paramètre de retour de paramètres selon une certaine plage.
Différences entre le détecteur et le disque dur
-
- Les seules fonctionnalités qui fonctionnent pour le retesting sont GetTicker et GetRecords, les autres qui ont une profondeur et une histoire de transaction ne sont pas authentiques (parce que le volume de données est trop important, le retesting au niveau du disque dur prend en charge ces données pour le moment, mais uniquement les données les plus récentes).
-
- Les échanges ajoutés sont des comptes indépendants et ne prennent pas en charge la commutation de paires. Il est donc impossible d'opérer deux paires de transactions dans un seul compte.
-
- Les requêtes en ligne ne peuvent pas être utilisées dans la rétroanalyse.
-
- La détection ne peut pas utiliser les extensions d'IO, mais seulement les API les plus basiques.
-
- La détection ne permet d'obtenir que des données standard, les données sur disques fixes comme Info n'existent pas.
-
- Il est possible que les commandes ne soient pas livrées lors de la revue, attention au blocage des commandes.
-
- Les futures de marchandises n'appuient pas le cours du marché.
La tolérance aux erreurs et les erreurs courantes
Comme nous l'avons mentionné plus haut, il est possible d'accéder à un disque dur en utilisant l'interface API et de revenir en arrière en cas de défaillance.nullSi vous utilisez les données de ce disque, vous risquez de faire une erreur et d'arrêter le disque, alors la stratégie est d'être tolérant.
Les méthodes de tolérance des erreurs courantes
Les causes les plus courantes:
- Erreur d'accès au réseau API, le délai d'expiration de l'accès à l'interface sera renvoyé à null, et l'utilisation de l'interface sera reportée.
- Les erreurs de limitation de l'échange, telles que la limitation de l'IP, l'exactitude des commandes, la fréquence d'accès, les erreurs de paramètres, l'insuffisance d'actifs, l'impossibilité de négocier sur le marché, la révocation d'ordres passés, etc. peuvent être consultées dans les documents API en fonction du code d'erreur.
- Les échanges retournent des données erronées, comme la profondeur de retour vide, les informations de compte retardées, les statuts de commande retardés, etc.
- Erreur de logique du programme
Avant d'utiliser l'API pour renvoyer des données, il faut déterminer si elles sont nulles ou non. Voici une méthode centralisée couramment utilisée:
//1.判断为null进行处理
var ticker = exchange.GetTicker();
while(ticker == null){
Log('ticker 获取出错');
ticker = exchange.GetTicker();
}
Log(ticker.Last);
// 2.判断不为null再进行引用
var ticker = exchange.GetTicker();
if(!ticker){
Log(ticker.Last);
}
// 3._C()函数重试
var ticker = _C(exchange.GetTicker);
Log(ticker.Last);
// 4. try catch容错
try{
var ticker = exchange.GetTicker();
Log(ticker.Last);
}
catch(err){
Log('ticker 获取出错');
}
Si vous voulez obtenir des informations erronées, vous pouvez utiliserGetLastError(), qui renvoie la dernière chaîne de messages d'erreur, permettant un traitement différentiel des erreurs.
FAQ
Il existe de nombreuses erreurs courantes dans les titres des forums: https://www.fmz.com/bbs-topic/1427 。 Voici un résumé de certaines erreurs courantes.
Comment mettre en place un tuteur ?
Vous trouverez plus de détails dans la section Ajouter un administrateur.
Pourrait-on trouver une stratégie de rédaction ?
Il y a des gens sur le site https://www.fmz.com/markets qui offrent des services de substitution, ou qui consultent dans des groupes, mais il faut les contacter eux-mêmes, à leurs risques et périls.
Accès à toutes les interfaces avec un délai d'attente
Il s'agit d'accéder à l'interface de l'échange en cas de temps d'arrêt occasionnel, si cela n'est pas un problème, si le message indique que le réseau n'est pas accessible, il faut utiliser un serveur à l'étranger.
Erreur dans le code de la position
L'erreur est généralement due à une erreur de programmation de la stratégie et à une tentative de liquidation de la position lorsqu'il n'y a pas de position ou si elle est insuffisante.
symbol not set
Le code ne contient pas de contrat, voir la fonction exchange.SetContractType
BITMEX 429 erreur,{"error":{"message": "Rate limit exceeded retry in 1 seconds"..."}}
L'accès à l'interface de la bourse est trop fréquent.
{"status":6004,"msg":"timestamp is out of range"}
Le temps du serveur doit être mis à jour si la barre de temps du serveur est dépassée.
GetOrder(455284455): Error: invalid order id or order cancelled.
Les commandes annulées ne sont pas conservées et ne sont pas accessibles.
GetOrders: 400: {"code":-1121,"msg":"Invalid symbol."}
Une paire d'opérations non valide, vérifiez si la configuration de la paire d'opérations est erronée.
Secret key decrypt failed
API KEY n'a pas réussi à être déchiffré. Si le mot de passe FMZ a été modifié après la configuration d'APIKEY, essayez d'ajouter une page d'échange sur FMZ et de reconfigurer l'échange APIKEY.
Signature not valid: Invalid submission time or incorrect time format [[Temps de soumission non valide ou format de temps incorrect]
Il est recommandé d'utiliser un serveur Linux ou un logiciel de synchronisation de temps d'installation sur les systèmes Windows qui présentent ce problème.
Pourquoi un agent mondial est-il installé et les administrateurs ne peuvent pas accéder à l'API de l'échange ?
Les agents mondiaux n'ont pas de ports réseau pour les agents hôtes, et il est préférable de déployer des hôtes sur des serveurs à l'étranger en raison de problèmes de latence.
Comment les stratégies peuvent-elles être conservées localement et non sur des FMZ téléchargées ?
En utilisant Python, on peut importer des fichiers locaux, les enregistrer normalement sous forme de fichiers écrits selon la stratégie de l'API de FMZ, les placer sur son propre serveur sous le chemin d'exécution et les lire directement.
#!python2.7
def run(runfile):
with open(runfile,"r") as f:
exec(f.read())
def main():
run('my.py')
Comment utiliser le testnet de l'échange ou modifier l'adresse de base de l'API
Vous pouvez utiliser exchange.SetBase () pour passer directement à l'adresse de base de l'API correspondante. Par exemple:
exchange.SetBase("https://www.okex.me")
我是看1分钟k线图操作的,所以Python死循环的sleep time 可以设置为0.1s,也就是sleep(100)吗,我看你其中写过一个sleep(10),也就是0.1s不会超过huobi HM的API限制吗?
exchange.SetDirection("closebuy"); //如果是永续合约,直接设置exchange.SetDirection("sell")
这儿我试了OKex的永续合约,如果设置成 sell,直接开空了,平不是平多
是我错了。。。
exchange.Buy(-1, 0.5),交易对是ETH_BTC,市价单代表买入0.5BTC的ETH
exchange.Buy(price, 0.5),如果是这种限价单,则代表用price的价格买入 0.5ETH
- 1







