Je suis désolé. Ce tutoriel contient des connaissances de base sur l'écriture de stratégies, y compris l'introduction de l'API, la revue, les graphiques, etc. Après avoir appris ce tutoriel de base, les utilisateurs seront en mesure d'utiliser l'API de base avec compétence pour écrire des stratégies de disque dur stables.Introduction à la plateforme de quantification des inventeurs FMZ 。
Il y a aussi une version plus ancienne:Inventor quantification (FMZ.COM) Stratégie écrite en utilisant entièrement le manuel 2.0 (tutoriel)Ce tutoriel répertorie de nombreux index de messages et vous est recommandé de les parcourir.
La transaction programmatique consiste à connecter un programme à l'échange par l'intermédiaire d'une API pour effectuer automatiquement des achats, des ventes ou d'autres fonctions conformément à l'intention de la conception.
Actuellement, les échanges de crypto-monnaie ont principalement deux protocoles d'interface: REST et Websocket. Le protocole REST est utilisé pour chaque prise de données, une seule fois est nécessaire.
{"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 permet de voir les dernières tendances de la transaction avec la paire BTC_USDT, qui changent à chaque mise à jour.market=
Ensuite, il y a des paramètres spécifiques pour les transactions, qui peuvent être modifiés pour obtenir des données pour d'autres transactions. Pour les interfaces publiques, comme les marchés, toutes les personnes peuvent y accéder et ne nécessitent donc pas d'authentification, tandis que certaines interfaces, comme les commandes ci-dessous et les comptes d'accès, nécessitent une authentification de l'utilisateur, ce qui nécessite une signature à l'aide de l'API-KEY.
La plateforme de trading quantitative FMZ est enveloppée dans l'interface REST des différentes plateformes, utilisant des appels et des formats de données unifiés, ce qui rend l'écriture des stratégies plus simple et plus universelle.
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 suivants auront une introduction spéciale. Comme Js est relativement simple et n'a pas de problèmes de compatibilité, il est recommandé pour les débutants.
Comme il existe différentes versions de Python, il est possible de spécifier au début du programme, comme#!Python2
,#!Python3
Les codes Python et Javascript présentant les mêmes fonctionnalités sont présentés ci-dessous, avec seulement des différences de syntaxe, de sorte que la documentation de l'API ne donne que des exemples de Javascript, ce tutoriel prend également en compte les cas particuliers de Python.
#python代码
def main():
while True:
Log(exchange.GetAccount().Balance)
Sleep(2000)
#相应的Js代码
function main(){
while(true){
Log(exchange.GetAccount().Balance)
Sleep(2000)
}
}
La plateforme de débogage FMZ fournit des outils de débogage pour les interfaces d'API.https://www.fmz.com/m/debugLes outils de débogage ne prennent en charge que JavaScript et ne peuvent être exécutés que pendant un certain temps. Les interfaces d'échange peuvent être déblayées sans créer de disque virtuel. Les données de retour sont renvoyées en tant que résultat et le code du outil de débogage n'est pas sauvegardé.
Comme les programmes de stratégie, les programmes normaux sont exécutés dans l'ordre de leur code. La particularité est qu'il doit y avoir une fonction principale. Comme les stratégies doivent fonctionner en continu, elles nécessitent généralement un cycle plus un temps de repos. Comme toutes les API de transaction ont une fréquence d'accès limitée, le temps de repos doit être ajusté en conséquence.
Les autres fonctions qui jouent un rôle particulier sont les suivantes:
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//在这里写策略逻辑,将会每6s调用一次
}
function main(){
while(true){
onTick()
Sleep(6000)
}
}
Dans l'exemple précédent, si une erreur d'accès au réseau peut entraîner l'arrêt direct de la politique, si vous voulez une politique similaire à une reprise automatique qui ne s'arrête pas, vous pouvez utiliser la politique de disque réel try catch pour permettre le cycle d'erreur du maître (revoir ne pas utiliser try). Bien sûr, il est recommandé de ne procéder qu'à condition que la politique soit stable, sinon il ne rendra pas tous les erreurs et il sera difficile de trier le problème de la politique.
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//在这里写策略逻辑,将会每6s调用一次
}
function main(){
try{
while(true){
onTick()
Sleep(6000)
}
}catch(err){
Log(err)
}
}
Lors de l'appel d'une API liée à n'importe quelle bourse, il est nécessaire d'indiquer clairement l'échange et la paire de transactions.exchange
On peut représenter cet objet commeexchange.GetTicker()
Ce que vous obtiendrez sera le ticker de marché de cette bourse-paire de transactions.
La plateforme FMZ prend en charge l'ajout simultané de plusieurs paires d'échanges, par exemple BTC et ETH, qui peuvent être exploités simultanément sur le même compte d'échange, ou BTC et ETH d'un autre échange.exchanges
L'arithmétique représente l'ordre d'ajout de la disquette créée.exchanges[0]
、exchanges[1]
... et ainsi de suite.BTC_USDT
Le premier est la monnaie de transaction BTC, l'autre est la monnaie de tarification USDT.
Évidemment, si nous traitons beaucoup de paires de transactions, cela peut être un problème, mais il est possible d'utiliser SetCurrency pour échanger des paires de transactions telles queexchange.SetCurrency("BTC_USDT")
À ce moment,exchange
La paire de transactions liée devientBTC_USDT
Les modifications de la paire de transactions seront toujours en vigueur jusqu'à la prochaine fois qu'elles seront appelées.Notez que la dernière version de la mise à jour des paires de transactions est prise en charge.Dans le même temps, il est important de se rappeler qu'il y a une grande différence entre les deux.
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)
}
}
Comme nous l'avons mentionné précédemment, les interfaces de marché sont généralement des interfaces ouvertes et accessibles à tous. Les interfaces de marché courantes sont: obtenir des tickers de marché, obtenir de la profondeur, obtenir des enregistrements de ligne K, obtenir des transactions.
Les interfaces sont généralementInfo
champs, qui représentent les chaînes de données originales retournées par l'échange, peuvent être utilisés pour compléter des informations supplémentaires qui doivent être analysées avant, JavaScript utiliséJSON.parse()
Python utilise une bibliothèque json.Time
Les champs indiquent la durée de la requête, qui peut être utilisée pour déterminer le délai.
Il est possible que l'accès à l'API sur disque physique échoue et revienne.null
Python est de retour.None
Il est important de tolérer les erreurs, car cela peut entraîner des erreurs et des arrêts du disque dur.
L'interface la plus couramment utilisée est probablement celle qui permet d'obtenir des informations sur le marché actuel, comme le prix de la dernière transaction, le prix d'achat et de vente, le volume de transactions récemment effectuées.{"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)
}
Obtenir des informations de profondeur sur les enchères. Bien que GetTicker contient un achat et une vente, si vous souhaitez consulter des enchères plus profondes, vous pouvez généralement utiliser cette interface pour trouver les 200 enchères les plus basses. Vous pouvez utiliser cette interface pour calculer le prix d'impact.
{
"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
}
L'exemple suivant est un exemple d'achat à distance:
function main() {
var depth = exchange.GetDepth()
Log('买一价个: ', depth.Bids[0].Price, '卖一价格: ', depth.Asks[0].Price)
}
L'accès à la ligne K, l'une des interfaces les plus couramment utilisées, permet de renvoyer à la fois des informations de prix sur une plus longue période, calculant la base de divers indicateurs. La période de la ligne K indique la période par défaut qui sera utilisée lorsque le disque réel sera ajouté si elle n'est pas spécifiée. La longueur de la ligne K ne peut pas être spécifiée, elle augmente continuellement avec le temps, jusqu'à 2000 bits, environ 200 bits sont appelés pour la première fois (différents échanges renvoient différemment); la dernière ligne K est la dernière ligne K, donc les données changent constamment au fur et à mesure, la première ligne K étant la plus ancienne.
exchange.SetMaxBarLen(Len)
Il est possible de définir le nombre de lignes K à obtenir pour la première fois (quelques échanges sont pris en charge) et de définir le nombre maximal de lignes K.Par exemple:exchange.SetMaxBarLen(500)
GetRecords peut spécifier les périodes suivantes: 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)
Les dernières mises à niveau de l'administrateur permettent de supporter des cycles personnalisés, le nombre de secondes de cycle transmis directement comme paramètre, la personnalisation au niveau des minutes est synthétisée en fonction de la ligne K de 1 minute et la ligne K de moins de 1 minute est synthétisée via GetTrades (), les futures sur les produits sont synthétisées en fonction de ticks.Attention, vous pouvez rencontrer des choses similaires dans les tutoriels.PERIOD_M1
Ces variables sont généralement écrites en majuscules, elles sont les variables globales par défaut de FMZ, et les personnes intéressées peuvent enregistrer leurs propres valeurs spécifiques et les utiliser directement.
Exemple de retour de donné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},
......
]
L'exemple de la ligne K:
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
}
L'accès à des données de transaction sur une certaine période de temps (et non à ses propres données de transaction) n'est pas pris en charge par certaines plateformes.
Ces interfaces ne sont pas directement accessibles car elles sont liées à des comptes et nécessitent une signature API-KEY.
Obtenir des informations sur les comptes. Une des interfaces les plus couramment utilisées nécessite un appel avant de passer une commande pour éviter un solde insuffisant. Retourne des résultats tels que:{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}
Les stocks sont le solde disponible de la monnaie de négociation de la paire, les frozen stocks sont le solde de la monnaie de négociation de la paire, les frozen stocks sont le solde de la monnaie de négociation de la paire, les frozen stocks sont le solde de la monnaie de négociation de la paire.BTC_USDT
Le terme "stock" désigne le BTC, le terme "balance" désigne le USDT.
Notez que les résultats retournés sont les résultats de la paire de transactions spécifiée, les informations sur les autres devises du compte de transaction sont dans le champ Info, et il n'est pas nécessaire d'appeler plusieurs paires de transactions.
Un tableau qui imprime constamment les transactions en cours par rapport à la valeur totale:
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
}
}
Vous pouvez téléphoner à l'adresse suivante:exchange.Buy(Price, Amount)
Ou alorsexchange.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 virtuel, pas obligatoire.null
Le site Web de l'équipe est disponible en anglais et en espagnol.
Si vous voulez payer à un prix de marché, le prix est -1, l'argent est la valeur de la commande, par exemple:exchange.Buy(-1, 0.5)
La transaction est bonne.ETH_BTC
Le prix de vente de l'ETH est de 0,5 BTC. Certains échanges ne supportent pas les prix du marché, ni la réévaluation des futures.
Les exigences de précision de tous les prix et quantités des transactions partielles sont disponibles_N()
Les fonctions de précision pour contrôler. Pour les contrats à terme, Buy et Sell ont une autre signification, qui sera présentée séparément.
Un exemple d'achat à un prix correspondant:
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')
}
Les paramètres de l'ordre de vente sont les mêmes que ceux de l'ordre de vente.exchange.Sell(-1, 0.2)
Il s'agit d'une vente de 0,2 ETH au prix du marché.
Obtenir des informations sur les commandes en fonction de l'identifiant de la commande.exchange.GetOrder(OrderId)
L'ID de l'ordre est l'id de la commande et est renvoyé au moment de la commande.Attention au type de commandeType
Les champs et l'état de la commandeStatus
Les valeurs réelles sont des chiffres qui représentent des significations différentes, mais elles sont préjudiciables à la mémoire. FMZ utilise des constantes globales pour représenter ces valeurs, telles que celles des commandes en suspens.Status
C'est une valeur égale à 0.ORDER_STATE_PENDING
Vous pouvez consulter toutes ces constantes globales dans la documentation.Les résultats sont les suivants:
{
"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 certain nombre de devises:
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)
}
}
}
}
Obtenez une liste des transactions en cours pour toutes les commandes en suspens. Si aucune commande n'est en suspens, retournez l'arbre vide.
Exemples d'annulations de transactions 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)
}
}
Les commandes sont annulées en fonction de l'id de la commande.exchange.CancelOrder(OrderId)
L'ordre est annulé après une transaction complète.
Les opérations futures de crypto-monnaie sont différentes des opérations à vue. Les fonctions de négociation à vue ci-dessus s'appliquent également aux futures, les transactions à vue unique ont des fonctions spécifiques. Avant de procéder à la négociation programmées de futures de crypto-monnaie, il est nécessaire de se familiariser avec les opérations manuelles sur le site Web et de comprendre les concepts de base tels que les positions ouvertes, les positions de mise à jour, les positions complètes, les positions par lots, les leviers, les pertes et pertes de mise à jour, les gains et pertes flottants, les garanties et les formules de calcul correspondantes.
Les contrats à terme et les contrats à terme sont similaires, la différence est qu'il n'y a pas de concept de plusieurs espaces en même temps.
Si l'échange prend en charge simultanément les futures sur place, comme les futures OKEX et Huobi, il est nécessaire de choisir séparément dans l'interface de l'échange de choisir la fenêtre OKEX et d'ajouter la fenêtre Huobi, qui sont considérées comme des échanges différents des futures sur place dans FMZ.
La première étape consiste à définir le contrat à négocier, par exemple le contrat OKEX, et à choisir une paire de transactions en BTC lors de la création d'un tableau réel ou d'un résumé.invalid contract type
。Contrairement aux contrats sur place, les contrats à terme sont souvent négociés avec des devises telles que le BTC comme garantie, les paires de transactions en ajoutant le BTC représentent généralement une paire de transactions BTC_USD garantie par le BTC, si un futur en USDT existe, il est nécessaire de créer une paire de transactions en ajoutant le BTC_USDT.Une fois la paire de transactions définie, il est également nécessaire de définir le type de contrat spécifique, tel que le contrat permanent, la semaine en cours, la semaine suivante, etc. Une fois le contrat configuré, des opérations d'acquisition, d'achat et de vente peuvent être effectuées.
Les contrats existants sur Bitcoin, OKEX, HuobiDM et USDT doivent être distingués lors de l'ajout de contrats de configuration en direct. Les configurations spécifiques sont les suivantes:
//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官网。
Obtenir une liste d'informations sur les stocks actuels, les contrats à terme OKEX (OKCOIN) peuvent être passés dans un paramètre spécifiant le type de contrat à obtenir. Si aucun stock n'est disponible, la liste est vide.[]
Les informations de détention sont renvoyées comme suit, beaucoup d'informations spécifiques, qui doivent être combinées avec une analyse spécifique des transactions.
Types de données | Nom de la variable | Expliquer |
---|---|---|
objet | Les informations | La structure originale de l'échange est retournée |
Numéro | Niveau de marge | La taille du levier, OKCoin est de 10 ou 20, le mode de l'ensemble du portefeuille OK retourne à 10 fixe car l'API native ne le supporte pas |
Numéro | Montant | Le volume d'inventaire, OKCoin indique le nombre de parts de contrat ((nombre entier et supérieur à 1) |
Numéro | Nombre congelé | Le volume de congélation |
Numéro | Le prix | Le prix moyen des actions |
Numéro | Marge | Le gel des garanties |
Numéro | Résultats | Commodity futures: détention de dépôts et pertes, crypto-monnaie: ((unité de monnaie numérique: BTC/LTC, unité de dépôt traditionnelle: RMB, note: OKCoin désigne le dépôt de dépôts et de pertes dans le cas d'un dépôt complet, et non le dépôt et la perte de dépôt) |
const | Le type | PD_LONG pour les positions multiples (en CTP avec closebuy_today), PD_SHORT pour les positions vides (en CTP avec closeesell_today), PD_LONG_YD pour les positions multiples d'hier (en CTP avec closebuy), PD_SHORT_YD pour les positions vides d'hier (en CTP avec closeesell) |
une chaîne | Type de contrat | Commodity Futures est le code du contrat, Stocks est le code de l'échange d'actions _ Stocks Code est le code de l'échange d'actions, type de transmission du paramètre spécifique 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)
}
}
Pour cela, vous devez d'abord configurer la taille du levier et la façon de l'appeler:exchange.SetMarginLevel(10)
Le taux d'effet de levier est de 10 fois plus élevé que le taux d'effet de levier de l'autre bourse.Attention, le levier doit être placé sur l'échange et doit correspondre au code de l'échange, sinon il y a des erreurs.Vous pouvez également le désactiver en utilisant le levier par défaut.
Ensuite, définissez l'orientation de la transaction et le mode d'appel:exchange.SetDirection(Direction)
, correspondant à la mise en place d'un placement, ** Contrairement aux contrats à terme, si le contrat permanent ne contient pas le concept de multi-espace simultanément, c'est-à-dire ne permet pas de détenir un seul poste, faire plus de temps d'ouverture sera automatiquement placé plusieurs positions, tout ne nécessite que de mettre en placebuy
etsell
Oui. Si le stockage bidirectionnel est pris en charge, vous devez configurerclosebuy
,closebuy
◦** Les relations spécifiques:
Opération | Paramètres de la Direction | Fonction de sous-rubrique |
---|---|---|
Le plus grand | Je suis en train de changer de direction | Je suis en train d' acheter. |
Plateau à plusieurs étages | Je suis en train de changer de direction. | Je suis en train d' échanger. |
Le dépôt vide | Je suis en train de changer de direction | Je suis en train d' échanger. |
Un dépôt vide | Je suis en train d'écrire une lettre. | Je suis en train d' acheter. |
Enfin, le code de l'opération spécifique est le code de l'opération de mise en place, dont le volume varie d'un échange à l'autre, par exemple, les futures huobi sont par numéro de feuille, une feuille de 100 $.
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 concret de stratégie de mise à niveau complète
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)
}
}
}
}
Il est nécessaire de passer à un compte de levier dans le code, le reste est le même que pour les transactions en direct.
Utilisationexchange.IO("trade_margin") Vous passez au mode de compte de couverture, vous passez une commande et vous accédez à l'interface d'effet de levier de l'échange. Utilisationexchange.IO("trade_normal") pour revenir au mode de compte ordinaire.
Les échanges pris en charge:
Il y a une grande différence entre les futures sur produits et les futures sur devises numériques. Tout d'abord, les futures sur produits sont de courte durée et les devises numériques sont échangées 24 heures sur 24; le protocole des futures sur produits n'est pas non plus l'API REST couramment utilisée; les futures sur produits sont limitées en fréquence et en nombre de souscriptions, les devises numériques sont très larges, etc. Ainsi, les futures sur produits ont de nombreux domaines qui nécessitent une attention particulière et il est recommandé d'avoir une riche expérience d'exploitation manuelle.https://www.fmz.com/bbs-topic/325Le blogueur a écrit:https://www.fmz.com/bbs-topic/371
Les contrats à terme sur produits et services ont été réglementés en juin 2019, les contrats à terme personnalisés pour les utilisateurs individuels ont besoin d'un code d'autorisation (le modèle d'information spécifique requis peut être envoyé dans le groupe WeChat ou le groupe QQ), ce qui prend généralement 4 à 5 jours, les étapes sont plus compliquées.https://www.fmz.com/bbs-topic/3860; Si votre courtier n'est plus sur la liste, vous pouvez simplement faire votre propre demande ou ouvrir votre compte auprès d'un courtier pris en charge, ce qui prend généralement 2 jours. ; FMZ a des relations de partenariat avec certains fournisseurs, tels que la société de courtage grand public, qui a acheté la version institutionnelle de la plate-forme FMZ, qui est disponible pour les utilisateurs, qui deviennent automatiquement VIP, et les frais de traitement sont minimes.https://www.fmz.com/bbs-topic/506 。
Grâce aux avantages de l'architecture de la plateforme FMZ, les utilisateurs peuvent également ajouter plusieurs comptes de futures et réaliser des fonctionnalités impossibles à réaliser par d'autres logiciels de négociation programmés pour les futures de produits, comme la synthèse de ticks haute fréquence.https://www.fmz.com/bbs-topic/1184
Tout d'abord, comme il ne s'agit pas d'une transaction 24h/24 et que des opérations de débarquement sont nécessaires, il est nécessaire de déterminer l'état du lien avant de procéder à la transaction.exchange.IO("status")
Pourtrue
Une connexion à l'échange est indiquée. Si la connexion n'a pas été réussie, l'API est appelée et le bouton de connexion n'est pas indiqué._C(exchange.SetContractType,"MA888")
Il est possible que le pays soit en proie à une crise sanitaire.
Les codes d'acquisition et de négociation des produits à terme sont les mêmes que pour les produits à terme sur crypto-monnaie.
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 une bibliothèque de négociation de produits à terme (voir ci-dessous), où le code est très simple et ne nécessite pas de détails fastidieux.https://www.fmz.com/strategy/57029
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)
}
});
}
Les futures sur produits utilisent le protocole CTP, où tous les marchés et les transactions d'ordres ne sont notifiés que lorsqu'il y a un changement, tandis que les demandes d'ordres, de comptes et de détentions sont des demandes actives.GetTicker
、GetDepth
、GetRecords
Les données sont mises en cache pour être mises à jour, les données sont toujours en attente de données, donc la stratégie peut être utilisée sans sommeil. Lorsqu'il y a un changement de marché, les tickers, profondeurs et enregistrements sont tous mis à jour, à ce moment-là, l'interface souhaitée est immédiatement renvoyée, l'état de l'interface appelée est mis en attente de mise à jour, la prochaine fois que l'interface est appelée, elle attend de nouvelles données.
Si vous souhaitez accéder aux données à chaque fois que vous les obtenez, même les anciennes données, vous pouvez passer à un mode de mise à jour instantanée des marchés.exchange.IO("mode", 0)
À ce stade, les stratégies ne peuvent pas être écrites en tant qu'événement, il est nécessaire d'ajouter un événement Sleep pour éviter un cycle mort rapide. Certaines stratégies à faible fréquence peuvent utiliser ce modèle, la conception de la stratégie est simple.exchange.IO("mode", 1)
Il est possible d'annuler le mode de cache par défaut.
Lors de l'opération d'un seul contrat, il est possible d'utiliser le mode par défaut. Mais s'il s'agit de plusieurs contrats, il est possible qu'un contrat n'ait pas de mise à jour de marché, ce qui entraîne un blocage de l'interface d'accès au marché et que d'autres contrats n'aient pas de mises à jour de marché. Pour résoudre ce problème, vous pouvez utiliser le mode de mise à jour immédiate, mais pas la stratégie de haute fréquence.exchange.IO("wait")
; si plusieurs objets d'échange sont ajoutés, ce qui est rare dans les futures sur produits, il peut être utiliséexchange.IO("wait_any")
L'index retourné indique l'indice de l'échange retourné.
Les ticks ont été modifiés:{Event:"tick", Index:交易所索引(按实盘上交易所添加顺序), Nano:事件纳秒级时间, Symbol:合约名称}
Les commandes sont envoyées:{Event:"order", Index:交易所索引, Nano:事件纳秒级时间, Order:订单信息(与GetOrder获取一致)}
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)
}
}
}
Il convient également de noter la différence entre les futures de produits et les échanges de devises numériques. Par exemple, GetDepth n'a en réalité qu'un seul fichier de profondeur (les frais de profondeur de 5 fichiers sont coûteux), GetTrades n'a pas non plus accès à l'historique des transactions (tous sont simulés en fonction de la variation des stocks, sans enregistrement de transactions réels). Les futures de produits ont une limite de chute et de baisse, le prix d'une vente en profondeur est le prix de la chute, le volume des commandes est 0, le prix d'un achat est le prix de la chute, le volume des commandes est 0 ; il y a également une fréquence d'interface de recherche de produits à terme, une limitation stricte des comptes, des commandes et des positions, généralement une fois 2 s.
exchange.IO("instruments"): renvoie la liste de tous les contrats de l'échange sous forme de dictionnaire {nom du contrat: détails}, ne prenant en charge que le disque réel.exchange.IO("products"): renvoie la liste de tous les produits de l'échange au format dictionnaire {nom du produit: détails} et ne prend en charge que les disques physiques.exchange.IO("subscribed"): renvoie les contrats déjà souscrits au marché, au même format, ne supportant que le disque réel.
Les futures traditionnelles de CTPContractType
Il s'agit de l'identifiant du contrat, en minuscules et en grosses lettres.exchange.SetContractType("au1506")
Les détails du contrat sont retournés après la mise en place du contrat, tels que le nombre d'achats au moins une fois, les frais d'entretien, les délais de livraison, etc. Lorsque vous souscrivez à plusieurs contrats, seule la première fois est une demande de souscription réelle, puis il suffit de changer de transaction au niveau du code, sans perdre de temps. Le contrat principal est le code 888 comme MA888, le contrat d'indice continu comme 000 comme MA000, 888 et 000 ne prennent en charge que le retrait des transactions de contrats virtuels, le disque réel ne prend en charge que l'obtention de transactions.Mais le langage mac peut manipuler des contrats principaux, les programmes changent automatiquement de position, c'est-à-dire éliminent les positions non principaux et ouvrent de nouvelles positions sur les positions principaux.
La connexion n'a pas été réussie et le contrat n'a pas pu être configuré, mais il est également retourné immédiatement, vous pouvez donc réessayer avec _C, sachant que la connexion CTP est terminée. Une fois la connexion réussie, la réinstallation du contrat n'est pas longue et n'entraîne pas d'accès réel au réseau.
SetDirection
La direction peut êtrebuy, closebuy, sell, closesell
Quatre paramètres, plus de produits à termeclosebuy_today
avecclosesell_today
Il y a des gens qui pensent que c'est une bonne chose.closebuy/closesell
Pour les contrats à terme, seules les variétés de la période précédente peuvent affecter les frais de traitement, il est donc nécessaire de privilégier les contrats à terme. Pour les contrats à terme traditionnels CTP, le deuxième paramètre peut être défini par 1 ou 2 ou 3, respectivement.Les opérations spécifiques telles que la vente, l'acquisition de positions, l'obtention d'ordres, le retrait, l'acquisition d'un compte sont les mêmes que pour les transactions à terme de devises numériques, voir le chapitre précédent.
Opération | Paramètres de la Direction | Fonction de sous-rubrique |
---|---|---|
Le plus grand | Je suis en train de changer de direction | Je suis en train d' acheter. |
Plateau à plusieurs étages | Je suis en train de changer de direction. | Je suis en train d' échanger. |
Le dépôt vide | Je suis en train de changer de direction | Je suis en train d' échanger. |
Un dépôt vide | Je suis en train d'écrire une lettre. | Je suis en train d' acheter. |
L'exemple ci-dessous est une fonction de mise en place spécifique, notez que l'exemple est trop simple, mais considérez une série de questions telles que la question de savoir si vous êtes à l'heure de la transaction, comment réessayer une transaction non complète, quelle est la quantité maximale de commande, si la fréquence est trop élevée, en particulier si le prix fluctue ou s'écoule.Il est recommandé d'utiliser une bibliothèque de classes bien emballée sur la plate-forme.https://www.fmz.com/strategy/12961Dans le chapitre de la bibliothèque, il y a des informations spécifiques, et 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 (en supportant le disque réel, le retouchage n'est pas pris en charge) qui sont spécifiés par le biais d'une barre postérieure, ajoutée après la barre postérieure, par exemple
exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")
Les conséquences spécifiques sont:
Par défaut, le commodity futures trader utilise l'interface CTP, qui peut être remplacée par l'interface Easy Transaction s'il en a besoin. Par FMZ, l'emballage et le mode d'appel sont les mêmes. La différence est que les comptes, les commandes et les détentions sont tous des modes de livraison, de sorte que le dépositaire maintient ces données localement et les renvoie immédiatement lorsqu'il appelle l'interface correspondante, sans réellement envoyer de demande.
Les types d'ordres personnalisés sont les suivants:
Dans l'interface du disque dur, un journal Log, suivi d'une chaîne avec le caractère @, le message entre dans la file d'attente de push et est directement poussé après avoir été lié à WeChat ou Telegram.Log('推送到微信@')
La couleur des journaux peut également être personnaliséeLog('这是一个红色字体的日志 #ff0000')
。#ff0000
Indicateur 16 pour les couleurs RGB
Tous les fichiers journaux se trouvent dans la base de données sqlit sur le disque virtuel du répertoire où se trouve l'hôte et peuvent être téléchargés et ouverts avec le logiciel de base de données, ou peuvent être utilisés pour copier des sauvegardes et des restaurations (le nom de la base de données est le même que l'id du disque virtuel).
Les gains sont enregistrés et tracés sur l'interface du disque dur, qui peut être conservé après le redémarrage du disque dur.LogProfit(1000)
Attention!LogProfit
Le paramètre de la valeur de l'opération n'est pas nécessairement un gain, il peut être n'importe quel nombre qui doit être rempli lui-même.
L'état de disque réel, car les journaux de log sont sauvegardés en premier et sont constamment mis à jour, peut être utilisé si vous avez besoin d'un message qui n'est pas sauvegardé.LogStatus
Les fonctions.LogStatus
Les paramètres sont des chaînes et peuvent également être utilisés pour représenter des informations de table.
Un exemple de table montrant la position de l'état du disque réel:
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'); // 上下排列显示多个表
Les paramètres sont des millisecondes, commeSleep(1000)
Une seconde de repos. En raison de la restriction de fréquence d'accès de toutes les transactions, une stratégie générale consiste à inclure une période de repos dans le cycle mort.
Une fois le disque dur redémarré, le programme redémarre._G
Il s'agit d'un logiciel très pratique qui permet de stocker du contenu sérialisé en JSON._G
La fonction est écrite comme suit:onexit()
Les utilisateurs peuvent choisir d'utiliser des outils de sauvegarde qui permettent de sauvegarder automatiquement les informations nécessaires à chaque interruption de la politique.
Si vous souhaitez stocker plus de données de formatage, la fonction _G n'est pas très pratique et vous pouvez écrire directement dans la base de données avec 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')
}
}
Lors de la commande, souvent pour contrôler la précision du prix et de la quantité, FMZ a intégré la fonction_N pour déterminer le nombre de décimales stockées, telles que:_N(4.253,2)
Le résultat est de 4,25.
L'API d'appel de l'échange est que _C est une fonction qui réessaye automatiquement chaque fois que l'accès est effectué._C(exchange.GetTicker)
Par défaut, l'intervalle de répétition est de 3 secondes. Vous pouvez appeler la fonction _CDelay pour contrôler l'intervalle de répétition, par exemple _CDelay ((1000), pour changer l'intervalle de répétition de la fonction _C à 1 seconde.GetTicker()
,exchange.GetDepth
,GetTrade
,GetRecords
,GetAccount
,GetOrders
, GetOrder
Les erreurs sont tolérées par _C, ce qui empêche les erreurs d'accès d'entraîner une interruption du programme.
CancelOrder
La fonction _C n'est pas utilisée, car il y a plusieurs raisons pour lesquelles une annulation peut échouer. Si une liste a déjà été traitée, une autre annulation renvoie un échec, ce qui entraîne une répétition constante de la fonction _C.
La fonction _C peut également transmettre des paramètres et est également utilisée pour des fonctions personnalisées.
function main(){
var ticker = _C(exchange.GetTicker)
var depth = _C(exchange.GetDepth)
var records = _C(exchange.GetRecords, PERIOD_D1) //传入参数
}
Appelez directement_D()
Retourne une chaîne de temps en cours, comme:2019-08-15 03:46:14
│ Si le test est appelé en retour, le temps de test est renvoyé│ On peut utiliser la fonction_D pour déterminer le temps, comme:_D().slice(11) > '09:00:00':
_D(timestamp,fmt)
, qui convertit le chronomètre ms en une chaîne de temps, comme_D(1565855310002)
Le paramètre fmt est le format de temps, par défaut.yyyy-MM-dd hh:mm:ss
Pour certaines fonctions d'indicateurs couramment utilisées, comme les indicateurs couramment utilisés tels que MA\MACD\KDJ\BOLL, la plate-forme FMZ est directement intégrée, et les indicateurs spécifiques pris en charge 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 indicateur.null
Si la longueur de la ligne K de l'entrée est de 100 et que le cycle de calcul de la MA est de 10, les 9 premières valeurs sont nulles et les suivantes sont normalement calculées.
JavaScript prend également en charge talib complet, comme une bibliothèque tierce prise en charge, appelée par exempletalib.CCI(records)
Pour référence:http://ta-lib.org/function.htmlPour Python, il est possible d'installer la bibliothèque talib par vous-même, mais il est impossible d'utiliser simplement pip pour l'installation, car il faut compiler.
Les fonctions indicateurs peuvent être transmises à 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)
}
}
Voici quelques-unes des fonctions JavaScript les plus couramment utilisées sur les ordinateurs.
Date.now()
Retourner à l'heure actuelleparseFloat()
On peut transformer une chaîne en chiffres, commeparseFloat("123.21")
parseInt()
Convertissez les chaînes en entiersnum.toString()
Convertir les chiffres en chaînes et les numéros en variables numériquesJSON.parse()
Pour formater une chaîne json, par exempleJSON.parse(exchange.GetRawJSON())
Math.max()
,Math.abs()
Il y a aussi des opérations mathématiques couramment utilisées, comme:https://www.w3school.com.cn/jsref/jsref_obj_math.aspIl y a beaucoup de choses à considérer pour écrire une fonctionnalité de stratégie en direct, comme une fonction simple comme acheter 5 pièces, nous devons prendre en compte: le solde actuel est-il suffisant? quel est le prix de la commande? quelle est la précision? n'a pas besoin de fractionner les commandes pour éviter d'avoir un impact sur le marché? comment traiter les commandes non terminées? etc.
Les bibliothèques JavaScript de crypto-monnaie et de produits à terme sont intégrées par défaut et ne doivent pas être copiées. D'autres bibliothèques de modèles peuvent être trouvées sur Strategy Squarehttps://www.fmz.com/square/20/1❏ Copiez et enregistrez les bibliothèques de modèles et choisissez les bibliothèques à utiliser lorsque vous créez votre propre politique.
Les fonctions de modèle JavaScript sont utilisées pour$
Nous avons commencé avec Python.ext
Je suis en train d'écrire.
Le code source est:https://www.fmz.com/strategy/10989, est intégré et n'a pas besoin d'être copié. Les implémentations de fonctions spécifiques peuvent être directement référencées au code source.
Pour accéder aux comptes:
$.GetAccount(e)
Log($.GetAccount()); // 获取账户信息, 带容错功能
Log($.GetAcccount(exchanges[1]));
Le retrait est le suivant:
$.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 du croisement:
$.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的是数组, 则直接进行比较
Le code de dépôt est le code de dépôt de la devise de la devise.
$.withdraw(exchange, "btc", "0x.........", 1.0, 0.0001, "***")
La bibliothèque de négociation des contrats à terme sur les produits est stable et recommandée.https://www.fmz.com/strategy/12961Il n'est pas nécessaire de le copier.
Bibliothèque du CTA
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
}
});
}
Exemples d'appels de bibliothèques
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)
}
}
Comme les fonctions de diagramme d'origine sont plus complexes, nous allons vous présenter dans le tutoriel suivant, il est recommandé aux débutants d'utiliser directement la bibliothèque de diagrammes d'images, des diagrammes de lignes d'images très simples, des diagrammes de lignes de lignes K, etc. FMZ a une bibliothèque de classes simple intégrée, qui peut être vue sur la page d'édition des stratégies, si elle n'est pas intégrée, elle doit être copiée et enregistrée par l'utilisateur pour sélectionner les références dans la politique.
L'adresse de copie de la bibliothèque de graphiques de Javascript est:https://www.fmz.com/strategy/27293L'adresse de copie de la bibliothèque de lignes d'impression Python:https://www.fmz.com/strategy/39066
Des exemples concrets:
function main() {
while (true) {
var ticker = exchange.GetTicker()
if (ticker) {
$.PlotLine('Last', ticker.Last) //可以同时画两条线,Last是这条线的名字
$.PlotLine('Buy', ticker.Buy)
}
Sleep(6000)
}
}
En dessous de l'éditeur de stratégie, il y a un paramètre de stratégie, qui correspond à une variable globale de la politique, accessible à n'importe quel endroit du code. Les paramètres de stratégie peuvent être modifiés dans l'interface du disque dur et prendre effet lors d'un redémarrage. Il est donc possible de définir certaines variables comme paramètres et de modifier les paramètres sans modifier la politique.
Le type de chaîne et le type de chiffre sont faciles à comprendre et sont les types les plus couramment utilisés. Le tableau de bord affiche des tableaux de bord optionnels dans l'interface des paramètres, par exemple, vous pouvez définir la valeur du paramètre SYMBOL du tableau de bord àBTC|USDT|ETH
Si vous sélectionnez USDT dans le menu déroulant de la page des paramètres, la valeur de SYMBOL dans la stratégie est l'index 1 de USDT.
Il y a beaucoup de paramètres à régler.https://www.fmz.com/bbs-topic/1306
Une fois la quantification d'une stratégie terminée, vous pouvez tester votre stratégie à l'aide des données historiques pour voir comment votre stratégie gagne dans les données historiques. Bien sûr, les résultats des retweets sont uniquement à titre indicatif. La plate-forme de quantification FMZ prend en charge les retweets de devises en espèces, futures, BitMEX futures, futures, dont les devises numériques prennent en charge principalement les variétés dominantes. Les références JavaScript sont effectuées dans le navigateur, les références Python doivent être effectuées sur un hôte, qui peut être utilisé par la plate-forme pour fournir un hôte public.
Le mécanisme de retouche onbar est basé sur la ligne K, c'est-à-dire que chaque ligne K génère un point de temps de retouche à partir duquel l'on peut obtenir des informations sur les prix élevés et bas de la ligne K actuelle, le volume des transactions, etc. et avant ce point.
le gaoencheerapes
La scienceJ'ai écrit une simple déclaration de sortie Log et j'ai suivi l'opération à la fin de la phrase. La première étape consiste à utiliser un ordinateur portable comme serveur et à exécuter le programme administrateur. La deuxième étape consiste à écrire un simple logiciel de test.py pour l'exportation des informations de Log (la fonction d'interface API de FMZ); La troisième étape, comme à la fin du texte, est d'écrire un runfile et d'appeler test.py via run.py.
- Je vous en prie.J'ai acheté un cours de quantification du cloud sur NetEase, mais je n'ai pas trouvé où aller maintenant.
MonurajakBeaucoup
MonurajakJe vous en prie.
Je ne sais pas.Apprendre
- Je ne sais pas.Il y a une petite erreur d'orthographe, GetAccount obtient le compte.
Je vous en prie, capitaine.getorder outtime: le temps d'expiration de l'ordre, l'échange d'Okex, comment faire?
Les 12 tours de l'OumuamuaLe taux d'actifs garantis n'est-il pas disponible et sera imposé à 0% au niveau des taux d'actifs garantis?
Le projet de loiJ'utilise un diagramme de k minutes, donc le temps de sommeil du cycle mort de Python peut être réglé à 0,1 s, c'est-à-dire à 100 s. J'ai vu que vous y avez écrit un sommeil de 10 s, c'est-à-dire que 0,1 s ne dépasse pas la limite de l'API de huobi HM.
Le bâtiment de l'EstExchange.SetDirection (("closebuy"); // Si c'est un contrat à durée indéterminée, installez directement exchange.SetDirection (("sell") J'ai essayé le contrat permanent OKex ici, et si vous le mettez sur sell, il est immédiatement vide, pas très bon marché.
Le bâtiment de l'EstExchange.SetDirection (("closebuy"); // Si c'est un contrat à durée indéterminée, installez directement exchange.SetDirection (("sell") J'ai essayé le contrat permanent OKex ici, et si vous le mettez sur sell, il est immédiatement vide, pas très bon marché.
Le bâtiment de l'EstIl y a deux fautes d'orthographe dans le code de GetOrders. Une fonction est écrite comme une fonction, l'autre comme une condition de la boucle for.
Le bâtiment de l'EstC'est moi qui ai fait une erreur. exchange.Buy ((-1, 0.5), la paire de transactions est ETH_BTC, le prix de vente représente l'achat d'ETH de 0.5BTC exchange.Buy ((price, 0.5), si c'est une liste de prix limitée, représente l'achat de 0.5ETH au prix de ce prix.
Le bâtiment de l'Estexchange.Buy ((-1, 0.5), la paire de transactions est ETH_BTC, ce qui représente l'achat d'ETH de 0.5BTC au prix du marché C'est le prix du marché pour acheter 0.5 ETH de lithium.
- Je vous en prie.Merci beaucoup.
Le foinIl est disponible en ligne depuis le début de l'année.
Le foinNous avons ajouté WeChat à la page d'accueil pour vous intégrer.
- Je ne sais pas.J'ai des problèmes à vous demander si vous avez un groupe de discussion officiel?
Le foinModifié
Le foinEncore une fois
Le foinVous pouvez utiliser GetRawJSON ou voir les informations dans les champs d'info.
Le bâtiment de l'EstC'est bien, c'est bien, et il y a aussi la réponse de l'administrateur.
Le foinOh, c'est corrigé, merci de souligner l'erreur.
Le foinCertains contrats perpétuels permettent de détenir des titres bidirectionnels et nécessitent une mise à niveau.