[TOC] Je vous en prie.

Instructions de base

Les débuts

Que peut faire la plateforme de trading quantique FMZ?

FMZ Quant Trading est la communauté quantitative la plus professionnelle dans le domaine du trading quantitatif. Ici, vous pouvez apprendre, écrire, partager, acheter et vendre des stratégies quantitatives; vous pouvez effectuer des backtests en ligne et utiliser des robots de simulation pour effectuer des transactions simulées; vous pouvez également exécuter, publier et regarder le trading en direct.

Série complète de tutoriels

Des tutoriels graphiques:

En cas de problème, vous pouvez poser des questions et discuter dans le forum à tout moment, ou soumettre un ticket, ou contacter un administrateur dans le groupe Telegram (TélégrammeDans l'ensemble, la réponse à cette question sera rapide.

Appui au ChatGPT pour l'aide au développement

La plateforme de négociation quantitative FMZ a adopté ChatGPT comme outil d'assistance au développement, auquel on peut accéder en cliquant sur ChatGPT dans la barre de raccourcis dans le Dashboard pour accéder à la plateforme.Page de l'outil auxiliaire de ChatGPT.

Quels langages de programmation sont disponibles pour mettre en œuvre mes stratégies?

La plateforme de négociation de FMZ Quant prend en charge l'utilisationJavaScript, TypeScript, Python, C++, Pine MylanguageetBlockly Visualizationpour écrire et concevoir des stratégies.

Il soutientTypeScriptLe langage, toujours réglé surJavaScriptla stratégie quand nous créons des stratégies, alors nous écrivons// @ts-checkau début du code de stratégie ou cliquez sur le boutonTypeScriptdans le coin supérieur droit de la zone d'édition de la stratégie pour passer àTypeScriptLa plateforme reconnaîtra le code commeTypeScriptautomatiquement et vous fournir le support approprié de compilation et de vérification de type pour:

  • Sécurité par type:TypeScriptLa fonction de vérification de type statique peut vous aider à trouver des erreurs potentielles lors de l'écriture de code et à améliorer la qualité du code.
  • Complétion automatique du code:TypeScriptLe système de type de Microsoft permet de trouver plus rapidement les attributs et les méthodes dont vous avez besoin lors de l'écriture de code, améliorant ainsi l'efficacité du développement.
  • Structure de code plus claire: avecTypeScript, vous pouvez mieux organiser et maintenir votre code, ce qui le rend facile à lire et à comprendre.
  • Des fonctionnalités puissantes de programmation orientée objet:TypeScriptfournit de puissantes fonctionnalités de programmation orientée objet, telles que des interfaces, des classes, des génériques, etc., vous aidant à écrire un code de stratégie plus robuste et réutilisable.

Vous n'avez besoin que de maîtriser un de ces langages. En plus de soutenir la façon de concevoir des stratégies en écrivant du code, vous pouvez également créer des stratégies à l'aide de modules visuels (Blockly).

BlocklyTutoriels de visualisation:

Mettez lePythoninterprète utilisé par lePythonprogramme stratégique

Des stratégies écrites enPython, lors du backtesting ou de la négociation en direct, si l'environnement du système docker a à la foisPython2etPython3installé, vous pouvez régler lePythonLa version à lancer en temps d'exécution sur la première ligne de la stratégie, telle que#!python3et#!python2Vous pouvez également spécifier un chemin absolu, comme:#!/usr/bin/python3.

Qu'est-ce que le Docker?

Docker peut être compris comme l'exécuteur de votre stratégie de trading, responsable des demandes de données complexes, de la réception de données, des liens réseau, du postback de journaux, etc. Le docker fonctionne sur votre serveur, même si le site Web de la plateforme de trading FMZ Quant a une panne de réseau, cela n'affectera pas le fonctionnement de votre docker. Le docker peut fonctionner surLe système Linux, Les fenêtres, Mac OS, Pour Android, Raspberry Pi ARM sous Linuxet autres systèmes.Page Docker, Installation et mise à jour des étapes de docker Linux. Les robots et les journaux gérés par le docker sont stockés dans le répertoire/logs/storageLe dossier est unSqlitefichier de base de données avecdb3, qui peut être édité directement par leSqlitePour un fichier avec une extensiondb3Dans la vraie base de données de bots, le nom du fichier est l'ID du bot.

Protocoles pris en charge

  • Actifs Blockchain: Plus de 50 échanges d'actifs blockchain (crypto-monnaie) traditionnels sont désormais pris en charge sur notre plateforme.
  • Accès au protocole général:Protocole général

Sécurité stratégique

Lorsque les stratégies de trading sont développées sur la plateforme de trading FMZ Quant, le contenu de la stratégie n'est visible que par les titulaires de compte FMZ.PythonLe code de stratégie est chargé dans le package, de sorte que la localisation du contenu de la stratégie puisse être réalisée.

La sécurité desPythonLe code: Parce que...Pythonest un langage open-source qui est extrêmement facile à décompiler, si la stratégie n'est pas pour un usage personnel mais pour la location, vous pouvez exécuter la stratégie sur votre propre docker déployé et la louer sous forme de sous-compte ou de gestion complète du docker si vous craignez une fuite de stratégie.

Le chiffrement dePythoncode de stratégie: Par défaut,PythonLe code de stratégie n'est pas chiffré lorsqu'il est utilisé par l'auteur et chiffré lorsqu'il est loué à d'autres. En modifiant le code suivant au début duPythonLa stratégie, vous pouvez spécifier si le code de la stratégie à chiffrer pour un usage personnel ou de location.PythonLes versions qui prennent en charge le chiffrement des codes de stratégie sont les suivantes:Python 2.7, Python 3.5etPython 3.6.

  • Les auteurs de stratégie l'exécutent eux-mêmes et cryptent le code de stratégie pour que d'autres puissent l'utiliser via un code d'enregistrement: Spécifier#!pythoncomme la version de l'interpréteur Python, puis utiliser,pour garder à l'écart; entrez la commande de chiffrementencryptSi vous ne précisez pas la version dePython, ajouter#!,encrypt directly.
 #!python,encrypt

Ou alors...

  #!encrypt
  • Il ne crypte pas les codes de stratégie lorsque les rédacteurs de stratégie courent pour leur propre usage et partagent avec d'autres par le code d'enregistrement:
  #!python, not encrypted

Ou alors...

  #!not encrypted

Utiliser le codeos.getenv('__FMZ_ENV__')pour déterminer si le code de chiffrement est valide; le retour de la chaîne"encrypt"indique qu'il a pris effet. Il est valable uniquement dans le bot réel, et le backtest ne chiffrera pas lePythonles codes stratégiques.

#!encrypt
def main():
    ret = os.getenv('__FMZ_ENV__')
    # If the print variable ret is the string "encrypt" or ret == "encrypt" is true, that means the encryption is valid. 
    Log(ret, ret == "encrypt")

La sécurité est essentielle

Les données sensibles, telles que les informations de compte et les chaînes cryptées dans les paramètres de stratégie configurés sur la plate-forme de trading FMZ Quant, sont cryptées dans le navigateur Web. Toutes les informations stockées sur la plate-forme de trading FMZ Quant sont cryptées (pas de données en texte brut), et seuls les utilisateurs peuvent déchiffrer et utiliser les informations, ce qui améliore considérablement la sécurité des données sensibles. Veuillez ne pas divulguer ou vendre les stratégies si d'autres informations sensibles sont incluses dans le code de stratégie, les paramètres et les descriptions de stratégie, etc.

  • Notre plateforme prend en charge la configuration localisée des informations sensibles, telles que les informations de compte d'échange et clé secrète Sur la page où la plateforme configure les informations d'échange, toutes les commandes de boîtes de texte cryptées avec masques prennent en charge la façon de configurer le chemin du fichier pour charger le fichier local du docker.RSA KEYméthode d'authentification de l'échange comme exemple pour expliquer en détail comment configurer les informations sensibles localement sur l'appareil où se trouve le programme docker.
  1. Créer des clés publiques et privées RSA. Par exemple, créer des clés publiques et privées au formatPKCS#8, il existe de nombreux outils de création, tels queopenssl.
  2. Créer uneRSA KEYsur l'échange, et télécharger la clé publique créée dansÉtape 1pendant la création.
  3. Enregistrer la clé privée créée dansÉtape 1dans le même répertoire du docker au formattxtfile, ou dans d'autres chemins dans le répertoire du programme docker.
  4. Lors de la configuration de l'échange sur la plateforme FMZ, remplir leRSA KEYcréé par l'échange dans la zone d'édition de la configurationAccess Key.
  5. Lors de la configuration de l'échange sur la plateforme FMZ, remplir le chemin detxtle fichier placé dans le même répertoire de niveau du docker dans leÉtape 3dans la zone d'édition de la configurationSecret Key. Par exemple, si le nom du fichier est:rsaKey.txt, et le fichier et le docker sont remplis dans le même répertoire de niveau:file:///rsaKey.txt. Si le fichier est dans le répertoire à côté du répertoire du programme dockerrsa_key, remplir:file:///rsa_key//rsaKey.txtSi vous placezrsaKey. txtDans le cas d'un fichier situé ailleurs sur votre ordinateur ou serveur, suivez ces instructions en conséquence, il convient de noter que ce fichier ne peut être placé que dans des répertoires de même niveau ou des sous-répertoires par rapport à Docker.

Cela rend plus sûr pour localiser et enregistrer la clé privée, vous pouvez vous référer àVidéo explicativepour un processus détaillé.

Système de contre-test

Qu'est-ce qu'un système de backtest, et à quoi sert-il?

Après avoir réalisé la conception d'une stratégie de trading quantitative, comment pouvez-vous connaître la situation de base de votre stratégie, telle que la logique de la stratégie et la direction des rendements de la stratégie? Bien sûr, nous ne pouvons pas utiliser de l'argent réel directement pour exécuter la stratégie sur le marché de trading réel, mais nous pouvons utiliser des données historiques pour tester votre stratégie et connaître les profits de votre stratégie dans les données historiques.

Les données du système de backtest sont-elles exactes et quelle est l'exactitude des résultats des backtest?

FMZ Quant Trading plateforme divise le système de backtest enniveau réel du marchéetniveau de simulationLe niveau réel du marché est de backtest complètement selon les données historiques complètes; tandis que le niveau de simulation backtest génèretickLes données sont basées sur les données historiques réelles, mais les données au niveau du marché réel sont plus précises et les résultats sont plus crédibles.Description du mécanisme de contre-test FMZCependant, le backtesting n'est que la performance de la stratégie selon les données historiques. Les données historiques ne peuvent pas représenter pleinement le marché futur. Le marché historique peut se répéter, ou cela peut également conduire au cygne noir. Par conséquent, les résultats du backtest doivent être traités de manière rationnelle et objective.

Questions à prendre en compte lors du backtesting de différentes stratégies de langage de programmation:

Le backtest deJavaScriptetC++Les stratégies de trading est menée dans le navigateur, et le vrai marché bot ouNous avons une application.Le marché réel de change émulé (c'est-à-dire leNous avons une application.L'échange émulé de la plateforme de trading FMZ Quant) s'exécute sans installer aucun autre logiciel, bibliothèques ou modules. Le backtest dePythonL'opération de marché réelle et le backtest dépendent tous deux de la capacité de l'utilisateur à effectuer des tests sur les marchés.PythonSi certaines bibliothèques sont nécessaires, elles doivent être installées manuellement (seules les bibliothèques communes sont prises en charge sur les serveurs publics).

Données de contre-test dans le système

Il existe deux types de backtest de la plateforme de trading FMZ Quant: le backtest au niveau de la simulation et le backtest au niveau du marché réel.tickChaque période de ligne K générera 12 points de temps de backtesting; cependant, le niveau réel du marché recueilleticksLe mécanisme de backtest de FMZ permet à la stratégie de trading de négocier plusieurs fois sur une seule ligne K, évitant la situation où le trading ne peut être exécuté qu'au prix de clôture. Il est plus précis tout en tenant compte de la vitesse de backtest. Pour des explications plus détaillées, veuillez vous référer àle lien.

Méthode de débogage de la stratégie dans le système de backtesting

Débogage des tests de stratégie JavaScript dans Chrome DevTools

Échanges pris en charge dans le système de backtesting

  • Monnaie cryptée (Cryptocurrency)

    Nom Le type Instruction
    Bitfinex objet de change au comptant le soutien de paires de négociation limitées, telles que:BTC_USD, ETH_USDetLTC_USD, etc. (notez que la devise de cotation des paires de négociation estUSDdollars américains)
    Binance objet de change au comptant le soutien de paires de négociation limitées, telles que:BTC_USDT, ETH_USDT, ETH_BTCetLTC_BTC, etc.
    - Ça va. objet de change au comptant le soutien de paires de négociation limitées, telles que:BTC_USDT, ETH_USDT, ETH_BTCetLTC_BTC, etc.
    Huobi est un joueur. objet de change au comptant le soutien de paires de négociation limitées, telles que:BTC_USDT, ETH_USDT, ETH_BTCetLTC_BTC, etc.
    Les titres à terme Objet d'échange à terme le soutien de paires de négociation limitées, telles que:BTC_USDetETH_USD, etc.; la devise de cotation des paires de négociation estUSD; après la définition du code de contrat spécifique (voir la fonctionexchange.SetContractType), le contrat est un contrat à crypto-marge; les codes de contrat pris en charge comprennent:this_week, next_week, quarteretswap
    HuobiDM Objet d'échange à terme HuobiDM est Huobi Futures (Huobi Contract), qui prend en charge des paires de négociation limitées, telles que:BTC_USDetETH_USD, etc.; la devise de cotation des paires de négociation estUSD; après la définition du code de contrat spécifique (voir la fonctionexchange.SetContractType), le contrat est un contrat à crypto-marge; les codes de contrat pris en charge comprennent:this_week, next_week, quarteretswap.
    BitMEX Objet d'échange à terme la paire de négociation estXBT_USD; après la définition du code de contrat spécifique (voir la fonctionexchange.SetContractType), le contrat est un contrat cryptographique à marge; le code du contrat pris en charge est:XBTUSD
    Les contrats à terme de Binance Objet d'échange à terme le soutien de paires de négociation limitées, telles que:BTC_USDTetETH_USDT, etc.; la devise de cotation des paires de négociation estUSD; après la définition du code de contrat spécifique (voir la fonctionexchange.SetContractType), le contrat est uneUSDT- contrat à marge; le code du contrat pris en charge estswap
    Options dérivées Objet d'échange à terme les paires de négociation sont:BTC_USDetETH_USD; après la définition du code de contrat spécifique (voir la fonctionexchange.SetContractType), le contrat est un contrat à crypto-marge; des codes spécifiques des contrats d'options doivent être définis

    Pour les objets d'échange de contrats à terme dans le système de backtest, le changement de paires de négociation n'est pas temporairement pris en charge dans les codes de stratégie.

Niveau de simulation

Le backtest de niveau de simulation est basé sur les données de ligne K sous-jacentes du système de backtest, simulant les données de tick dans le cadre des valeurs du prix le plus élevé, le prix le plus bas, le prix d'ouverture et le prix de clôture d'une barre de ligne K sous-jacente donnée selon un certain algorithme.tickles données lorsque l'interface est demandée. Pour plus de détails, veuillez vous référer à:Description du mécanisme de contre-test au niveau de simulation quantique FMZ.

Niveau du marché réel

Le backtest au niveau du marché réel est letickPour les stratégies basées sur lestickDans le cas des tests antérieurs de niveau de marché réel, les données de niveau de marché réel utilisées pour le backtest sont plus proches de la réalité.tickLes données sont des données enregistrées réelles, pas simulées. Il prend en charge les données de profondeur, la lecture des données d'enregistrement des transactions sur le marché, la profondeur personnalisée et chaque donnée de négociation individuelle. La taille maximale du backtest de données au niveau du marché réel est maximale de 50 Mo, sans limite sur la plage de temps de backtest dans la limite supérieure de l'ensemble de données. Si vous avez besoin d'agrandir la plage de temps de backtest autant que possible, vous pouvez réduire la valeur de l'équipement de réglage de profondeur d'appel et ne pas utiliser chaque donnée de négociation individuelle pour augmenter la plage de temps de backtest.GetDepth,GetTradesDans un moment de données de marché sur la chronologie, appelantGetTicker,GetTrades, GetDepthetGetRecordsNe pas pousser le temps plusieurs fois lorsque le temps se déplace sur la chronologie du backtest (ce qui ne déclenchera pas un saut vers le prochain moment des données du marché). Les appels répétés à l'une des fonctions ci-dessus pousseront le temps du backtest pour se déplacer sur la chronologie du backtest (sauter vers le prochain moment des données du marché). Lorsque le niveau réel du marché est utilisé pour le backtest, il n'est pas recommandé de choisir un moment antérieur. Il peut ne pas y avoir de données au niveau du marché réel dans la période de temps prématurée.

Le backtest au niveau du marché réel soutient actuellement:

  • Binance
  • Le montant de l'émission est calculé à partir de la valeur de l'émission.
  • HuobiDM (Huobi Futures)

Optimisation des paramètres du système de backtesting

La fonction d'optimisation des paramètres du système de backtest de la plateforme de trading FMZ Quant consiste à définir des optimisations en fonction de chaque option d'optimisation des paramètres pendant le backtest, et les options sont indiquées comme suit:

  • Valeur minimale: pour limiter la valeur de départ des paramètres.
  • Valeur maximale: pour limiter la valeur maximale des paramètres après des modifications incrémentielles.
  • Taille d'étape: la valeur de la variable incrémentielle des paramètres.

Générer des combinaisons de paramètres, et traverser toutes ces combinaisons à backtest (à savoir backtesting chaque combinaison de paramètres une fois).NuméroLe système de backtesting permet d'optimiser le type de données.

Par exemple, définissez les options d'optimisation des paramètres sur la page de backtest:

img

Le backtest du mode d'optimisation des paramètres:

img

Enregistrer les paramètres de test arrière

Dans la page d'édition de stratégie, dans la pagination de Backtest (à savoir le système de backtest), vous pouvez définir des options telles que les configurations de backtest et les paramètres de stratégie pour backtest la stratégie. Les paramètres de backtest se réfèrent à la plage de temps de backtest, la plate-forme d'échange, le point de glissement et les frais de service, etc.; tandis que les paramètres de stratégie sont utilisés pour définir des options de paramètres pour les stratégies. Lorsque les configurations de stratégie sont toutes réglées, vous pouvez backtest la stratégie en fonction des paramètres. Alors, comment sauvegarder ces paramètres configurés pour une utilisation dans la prochaine page de backtest (les options lors du rafraîchissement de la page seront réinitialisées)? Vous pouvez cliquer sur le bouton Save Settings sur la page de stratégie, et tous les paramètres de backtest (y compris les configurations de backtest et les paramètres de paramètres) seront enregistrés sous forme de code source dans la page de test

img

PrenezJavaScriptla stratégie comme exemple, et cliquez sur Save Backtest Settings to Source File:

img

Il y a de légères différences sur Save Backtest Settings to Source File entreJavaScript, Python, cppetMylanguage:

/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
'''backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Binance","currency":"BTC_USDT"}]
'''
/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

- Je ne sais pas.

(*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
*)

Source de données personnalisée

Le système utilise lesGETméthode pour demander une URL personnalisée (URL accessible au public) afin d'obtenir une source de données externe pour le backtest.

Paramètre Signification Expliquer
Le symbole Nom du symbole comme BTC_USD_OKCoin_EN
Le jour de l'Aïd Les échanges comme OKCoin_EN
Ronde Précision des prix tel que 3, le prix dans les données renvoyées doit être multiplié par 1000 et arrondi
Environs Précision de la quantité comme 2, le montant des données renvoyées doit être multiplié par 100 et arrondi
Période Période de barre (millièmes de seconde) Par exemple, 60 000 indiquant la barre demandant une minute
Profondeur Niveaux de profondeur 1-20
Commerces Si les données doivent être scindées vrai/faux
- Je ne sais pas. Heure de début Le timestamp est unix
Pour Le temps de la fin Le timestamp est unix

Note: le numéro de série

Round and V-Round are two parameters designed to avoid losing the precision of floating-point numbers during network transmission. The price data, trading volume and order amount, are all transmitted using integers.

Exemple de données cousues:

http://customserver:80/data?symbol=BTC_USD_OKCoin_EN&eid=OKCoin_EN&round=3&vround=3&period=900000&from=1564315200&to=1567267200

Le format retourné doit être l'un des deux formats suivants (qui seront automatiquement reconnus par le système):

Test de retour ordinaire au niveau des barres

{
    "schema":["time","open","high","low","close","vol"],
    "data":[[1564315200000,9531300,9531300,9497060,9497060,787],[1564316100000,9495160,9495160,9474260,9489460,338]]
}

Données de backtest au niveau du tick (y compris les informations sur la profondeur du marché, un tableau avec un format de profondeur de [prix, volume]; il peut y avoir plusieurs niveaux de profondeur; asks fait référence à l'ordre croissant des prix et bids fait référence à l'ordre inverse des prix).

{
    "schema":["time","asks", "bids","trades","close","vol"],
    "data":[[1564315200000,[[9531300,10]], [[9531300,10]],[[1564315200000,0,9531300,10]],9497060,787]]
}

Définition

Le champ Définition
Le schéma Il spécifie les attributs des colonnes dans le tableau de données, qui est sensible à la casse et est limité à time, open, high, low, close, vol, asks et bids
Données Un tableau qui stocke des données par schéma

Format des données

Le champ Définition
demandes/offres [prix, volume],...]
commerces [temps, direction, prix, volume,...]

Fourniture de données sur le taux de financement:

Par exemple, lors du backtesting de Binance Futures, il est nécessaire d'avoir des données supplémentaires sur le taux de financement, qui doivent être fournies par une source de données personnalisée.

{
  "detail": {},
  "symbol": "futures_binance.eth_usdt.funding",
  "schema": ["time", "open", "high", "low", "close", "vol"],
  "data": [
    [1582876800000, 25289, 25289, 25289, 25289, 0],
    [1582905600000, 30522, 30522, 30522, 30522, 0],
    [1582934400000, 40998, 40998, 40998, 40998, 0],
        ...
    [1626652800000, 198, 198, 198, 198, 0],
    [1626681600000, 691, 691, 691, 691, 0],                  // The adjacent periodic interval is 8 hours
    [1626710400000, 310, 310, 310, 310, 0],                  // The funding rate of Binance updates every 8 hours, and why the data of the funding rate turns out to be 310?
    [1626739200000, 310, 310, 310, 310, 0],                  // Like the bars data, to avoid losing the precision of floating-point numbers during network transmission, the data uses integer, so the data needs to be processed according to round parameter; the data, returned to the backtest system after processing, is 310 
    [1626768000000, -41610, -41610, -41610, -41610, 0],      // The funding rate might be a negative value
    [1626796800000, -5125, -5125, -5125, -5125, 0],
        ...   
    [1627977600000, 10000, 10000, 10000, 10000, 0]
  ]
}

Exemple de demande de données du système de backtest:

http://customserver:80/data?symbol=futures_binance.eth_usdt.funding&eid=Futures_Binance&round=8&vround=5&depth=20&trades=1&custom=0&period=3600000&from=1360771200&to=1628006400

Exemple de source de données personnalisée:

Spécifier la source de données, URL:http://xxx.xx.x.xx:9090/dataPersonnalisez le serveur de données, écrit en golang:

package main 
import (
    "fmt"
    "net/http"
    "encoding/json"
)

func Handle (w http.ResponseWriter, r *http.Request) {
    // e.g. set on backtest DataSourse: http://xxx.xx.x.xx:9090/data
    // r.URL: /data?depth=20&detail=true&eid=Binance&from=1566820800&period=900000&round=3&symbol=BTC_USDT_Binance&to=1569686400&trades=1&vround=5
    // response
    defer func() {
        // response data
        /* e.g. data
        {
            "schema":["time","open","high","low","close","vol"],
            "data":[
                [1564315200000,9531300,9531300,9497060,9497060,787],
                [1564316100000,9495160,9495160,9474260,9489460,338]
            ]
        }
        */
        ret := map[string]interface{}{
            "schema" : []string{"time","open","high","low","close","vol"},
            "data" : []interface{}{
                []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                []int64{1564316100000,9495160,9495160,9474260,9489460,338},
            },
        }
        b, _ := json.Marshal(ret)
        w.Write(b)
    }()
}

func main () {
    fmt.Println("listen http://localhost:9090")
    http.HandleFunc("/data", Handle)
    http.ListenAndServe(":9090", nil)
}

stratégie de test,JavaScriptExemple:

/*backtest
start: 2019-07-28 00:00:00
end: 2019-07-29 00:00:00
period: 1m
platforms: [{"eid":"OKX","currency":"BTC_USDT","feeder":"http://120.24.2.20:9090/data"}]
*/

function main() {
    var ticker = exchange.GetTicker()
    var records = exchange.GetRecords()
    Log(ticker)
    Log(records)
}

Graphiques dessinés par les données personnalisées du système de backtest:

Stratégie Imprimer des informations:

Moteur de test de retour local

La plateforme de trading de FMZ Quant est open-source pour leJavaScriptLa versionPythonversion du moteur de backtest local, réglage de supportPériode sous-jacente de la ligne Kpendant le backtesting.

Les touches de raccourci de page de test arrière

  • Touche de raccourci pour basculer entre la stratégie Édition page et la page Backtesting

    Utilisez la clé.Ctrl +,pour revenir à la page Backtest et Edit Strategy.CtrlAppuie sur la touche.,.

  • Touche de raccourci pour la stratégie d'économie

    Utilisez la clé.Ctrl + spour sauver des stratégies.

  • Raccourci pour démarrer le backtest de stratégie

    Utilisez la clé.Ctrl + bpour activer Start Backtest.

Description du code

Fonctions d'entrée

Nom de la fonction Définition
main() C'est une fonction d'entrée.
onexit() Il s'agit d'une fonction de nettoyage lorsque la sortie est normale, son temps d'exécution maximal est de 5 minutes, qui peut être laissé non déclaré.interromprel'erreur sera signalée.
onerror() Il s'agit d'une fonction de sortie anormale, son temps d'exécution maximal est de 5 minutes, ce qui peut être laissé non déclaré.Pythonetcppne supporte pas cette fonction.
init() c'est une fonction d'initialisation, son programme de stratégie sera appelé automatiquement quand il commence à fonctionner, ce qui peut être laissé non déclaré.
  • Définition:
    1. Le système de backtest ne prend pas en charge la fonctiononerror().
    1. Si la fonctiononerror()est déclenchée dans le bot, la fonctiononexit()ne sera pas déclenchée.

Une sortie

onexit(), le traitement des travaux de nettoyage, avec un temps d'exécution maximal de 5 minutes, qui est réalisé par l'utilisateur.

function main(){
    Log("Start running, stop after 5 seconds, and execute onexit function!")
    Sleep(1000 * 5)
}

// onexit function implementation
function onexit(){
    var beginTime = new Date().getTime()
    while(true){
        var nowTime = new Date().getTime()
        Log("The program stops counting down..The cleaning starts and has passed:", (nowTime - beginTime) / 1000, "Seconds!")
        Sleep(1000)
    }
}
import time 
def main():
    Log("Start running, stop after 5 seconds, and execute onexit function!")
    Sleep(1000 * 5)

def onexit():
    beginTime = time.time() * 1000
    while True:
        ts = time.time() * 1000
        Log("The program stops counting down..The cleaning starts and has passed:", (ts - beginTime) / 1000, "Seconds!")
        Sleep(1000)
void main() {
    Log("Start running, stop after 5 seconds, and execute onexit function!");
    Sleep(1000 * 5);
}

void onexit() {
    auto beginTime = Unix() * 1000;
    while(true) {
        auto ts = Unix() * 1000;
        Log("The program stops counting down..The cleaning starts and has passed:", (ts - beginTime) / 1000, "Seconds!");
        Sleep(1000);
    }
}

init (()

L'utilisateur implémente la fonction d'initialisationinit(), qui exécutera automatiquement la fonctioninit()au début de la stratégie pour compléter la tâche d'initialisation.

function main(){
    Log("The first line of the code executed in the program!", "#FF0000")
    Log("Exit!")
}

// Initialization Function
function init(){     
    Log("Initialization!")
}
def main():
    Log("The first line of the code is executed!", "#FF0000")
    Log("Exit!")

def init():
    Log("Initialization!")
void main() {
    Log("The first line of the code is executed!", "#FF0000");
    Log("Exit!");
}

void init() {
    Log("Initialization!");
}

Une erreur.

Exécution de la fonctiononerror()Cette fonction ne prend pas en charge les stratégies écrites enPythonetcpp.

function main() {
    var arr = []
    Log(arr[6].Close)
}

function onerror() {
    Log("error")
}
# not supported by python 
// not supported by C++ 

Cadre stratégique classique

Dans les stratégies écrites enJavaScript, Pythonetcpp, leSleep()Dans le bot, il est utilisé pour contrôler les intervalles de vote de stratégie, et aussi contrôler la fréquence de demande d'accès à l'interface API de l'échange.

  • Exemples de cadres de base de stratégies de crypto-monnaie:

    function onTick(){
        //Write strategy logic here, and it will be called constantly, such as printing market information
        Log(exchange.GetTicker())
    }
    
    function main(){
        while(true){
            onTick()
            //The function "Sleep" is mainly used to control the polling frequency of cryptocurrency strategies to prevent accessing the exchange API interafce too frequently 
            Sleep(60000)
        }
    }
    
    def onTick():
        Log(exchange.GetTicker())
    
    def main():
        while True:
            onTick()
            Sleep(60000)
    
    void onTick() {
        Log(exchange.GetTicker());
    }
    
    void main() {
        while(true) {
            onTick();
            Sleep(60000);
        }
    }
    

    Prenons l'exemple le plus simple, si je veux placer un ordre d'achat avec un prix de 100 et une quantité de 1 sur l'échange chaque seconde, je peux l'écrire comme ceci:

    function onTick(){
        // It is just an example; for all the assets will be used to place orders fast during backtest or in the bot, do not implement the example in the bot
        exchange. Buy(100, 1)
    }
    
    function main(){
        while(true){
            onTick()
            // The pause period can be customized in millisecond (1 second = 1000 milliseconds)
            Sleep(1000)
        }
    }
    
    def onTick():
        exchange.Buy(100, 1)
    
    def main():
        while True:
            onTick()
            Sleep(1000)
    
    void onTick() {
        exchange.Buy(100, 1);
    }
    
    void main() {
        while(true) {
            onTick();
            Sleep(1000);
        }
    }
    

Bibliothèque de modèles

Lebibliothèque de modèlesest un module de code réutilisable dans la plateforme de trading FMZ Quant, fonctionnant comme une catégorie de codes de stratégie de trading.Bibliothèque de modèles, un modèle est ajouté à la page Strategy du compte actuellement connecté à la plateforme de trading FMZ Quant. Après la création, il n'est plus possible de modifier la catégorie à une stratégie normale.

Bibliothèque de modèles JavaScript:

img

Bibliothèque de modèles Python:

img

Bibliothèque de modèles cpp:

img

  • Fonction d'exportation de la bibliothèque de modèles La fonction d'exportation est une fonction d'interface de Template library, et elle peut être appelée par la stratégie qui fait référence à Template library.

    /*
    -- This method is called directly with $.Test() after the strategy refers to the template
    -- The "main" function will not be triggered in the strategy, and it is only used as the entry point for template debugging
    */
    $.Test = function() {
        Log('Test')
    }
    
    function main() {
        $.Test()
    }
    
    def Test():
        Log("template call")
    
    # Export "Test" function; the main strategy can be called by ext.Test()
    ext.Test = Test 
    
    // The strategy refers to the template and calls this method directly with ext::Test()
    void Test() {
        Log("template call");
    }
    
  • Paramètres de la bibliothèque de modèles Template library peut également définir ses propres paramètres d'interface, qui sont utilisés sous forme de variables globales dans le code de Template library.

    Les paramètres de la bibliothèque de modèles:

    img

    Codes de bibliothèque de modèle:

    $.SetParam1 = function(p1) {
        param1 = p1
    }
    
    $.GetParam1 = function() {
        Log("param1:", param1)
        return param1
    }
    
    def SetParam1(p1):
        global param1
        param1 = p1
    
    def GetParam1():
        Log("param1:", param1)
        return param1
    
    ext.SetParam1 = SetParam1
    ext.GetParam1 = GetParam1
    
    void SetParam1(float p1) {
        param1 = p1;
    }
    
    float GetParam1() {
        Log("param1:", param1);
        return param1;
    }
    

    Consultez le code de stratégie dans leBibliothèque de modèlesl'exemple mentionné ci-dessus:

    function main () {
        Log("call $.GetParam1:", $.GetParam1())
        Log("call $.SetParam1:", "#FF0000")
        $.SetParam1(20)
        Log("call $.GetParam1:", $.GetParam1())
    }
    
    def main():
        Log("call ext.GetParam1:", ext.GetParam1())
        Log("call ext.SetParam1:", "#FF0000")
        ext.SetParam1(20)
        Log("call ext.GetParam1:", ext.GetParam1())
    
    void main() {
        Log("call ext::GetParam1:", ext::GetParam1());
        Log("call ext::SetParam1:", "#FF0000");
        ext::SetParam1(20);
        Log("call ext::GetParam1:", ext::GetParam1());
    }
    

    img

  • Citation Bibliothèque de modèles

    Après avoir vérifié la référence dans la colonne modèle de la page d'édition de la stratégie, enregistrez la stratégie.

    img

Structure intégrée

Variables globales

Échange

ExchangeL'objectif d'échange est considéré par défaut comme le premier objet d'échange ajouté dans les paramètres de stratégie.

  • Ajout d'objets d'échange dans Backtest

  • Ajout d'objets d'échange sur la page Bot

Les objets d'échange ajoutés correspondent àexchangeles objets du code:

function main() {
    Log("The name of the first exchange object added on the bot page or backtest page:", exchange.GetName(), ", Label:", exchange.GetLabel())
}
def main():
    Log("The name of the first exchange object added on the bot page or backtest page:", exchange.GetName(), ", Label:", exchange.GetLabel())
void main() {
    Log("The name of the first exchange object added on the bot page or backtest page:", exchange.GetName(), ", Label:", exchange.GetLabel());
}
Les échanges

Il peut être compris comme un tableau qui stocke tous les objets d'échange commeexchangeles objets d'échange, qui peuvent contenir plusieurs objets d'échange;exchanges[0]estexchange.

Les objets d'échange ajoutés correspondent àexchanges[0], exchanges[1], exchanges[2]...et ainsi de suite dans le code de la stratégie.

function main() {
    for(var i = 0; i < exchanges.length; i++) {
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "Label:", exchanges[i].GetLabel())
    }
}
def main():
    for i in range(len(exchanges)):
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "Label:", exchanges[i].GetLabel())
void main() {
    for(int i = 0; i < exchanges.size(); i++) {
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "Label:", exchanges[i].GetLabel());
    }
}
Statut de la commande

L'attributStatusdans leOrder structure.

Nom constant Définition Valeur
Résultats de l'enquête non terminé 0
- Je ne sais pas. terminé 1
L'ordre est annulé. annulé 2
L'ordre est inconnu. État inconnu (autres États) 3

L'ordre est inconnu.le statut peut appelerexchange.GetRawJSON()pour obtenir les informations d'état de la commande originale, consulter le fichier d'échange et afficher la description spécifique. Les noms des constantes du formulaire peuvent être utilisés directement dans le code de stratégie pour comparer avec l'attributStatusdans leOrderL'impression de ces noms constants montrera le nombre de fois où les variables sont égales.les noms constantset leur correspondantles valeurs, et d'autres noms constants ci-dessous fonctionnent de la même manière, il n'y aura donc pas de descriptions plus détaillées à leur sujet.

Type de transaction d'ordre

L'attributTypedans leOrder structure.

Nom constant Définition Valeur
Nom de l'entreprise Commande 0
Nom de l'entreprise Commande de vente 1
Type de position

L'attributTypedans lePosition structure.

Nom constant Définition Définition Applicable Valeur
Résultats de l'analyse Position à long terme Utilisation des contrats à terme sur crypto-monnaieexchange.SetDirection("closebuy")pour définir la direction de la position de clôture et fermer ce type de positions Futures sur crypto-monnaie 0
PD_SHORT Position à court terme Utilisation des contrats à terme sur crypto-monnaieexchange.SetDirection("closesell")pour définir la direction de la position de clôture et fermer ce type de positions Futures sur crypto-monnaie 1
Résultats de l'évaluation de l'activité

L'attributOffsetdans leOrder structure.

Nom constant Définition Valeur
Le code de commande est le même. Les ordres de position ouverts 0
REMARQUE de l'opérateur Ordre de clôture 1
Paramètres de stratégie

Dans les codes de stratégie de négociation, les paramètres de stratégie définis sur l'interface de stratégie sont reflétés sous forme de variables globales.JavaScriptL'interface de stratégie permet d'accéder directement aux valeurs de paramètres définies ou modifiées.Pythonstratégies, le mot cléglobalIl est nécessaire de modifier les variables globales de la stratégie.

Type de paramètre:

img

Variable Définition Les commentaires Le type Valeur par défaut Définition
Numéro Type numérique Les commentaires Numéro (nombre) 1 C++ stratégie est un type de virgule flottante
Chaîne une chaîne Les commentaires Chaîne (chaîne) Bonjour FMZ La valeur par défaut n'a pas besoin d'être citée. L'entrée est traitée comme une chaîne
Boîte à outils ComboBox Les commentaires ComboBox (sélectionné) 1|2|3 La variable combox elle-même est une valeur numérique, qui représente l'index de la colonne sélectionnée par la commande Combobox.
Bool Options de vérification Les commentaires Boolean (vrai/faux) vrai Si elle est vérifiée, la variable bool est vraie; si elle n'est pas vérifiée, la variable bool est fausse
SecretString est une chaîne Chaîne chiffrée Les commentaires Chaîne chiffrée (chaîne) Mot de passe Avec la même utilisation qu'une chaîne, la chaîne cryptée sera envoyée par cryptage et ne sera pas transmise en texte brut
  • Les paramètres d'interface sont définis dans la section paramètres de stratégie située en dessous de la section de modification de code de la page de modification de stratégie.
  • Les paramètres d'interface existent comme variables globales dans le code de stratégie, c'est-à-dire que les paramètres d'interface peuvent être modifiés dans le code.
  • Les noms des variables des paramètres d'interface dans le code de stratégie (voir le formulaire ci-dessus):number, string, combox, bool, secretString.
  • Option de description: les noms des paramètres d'interface de l'interface de stratégie.
  • Option de remarque: la description détaillée des paramètres d'interface; la description s'affiche lorsque la souris est posée sur les paramètres d'interface.
  • Option de type: le type des paramètres d'interface.
  • Option de valeur par défaut: les valeurs par défaut des paramètres d'interface.

Réglage de la dépendance par paramètre: Un paramètre peut être défini pour permettre à un autre paramètre d'être affiché et caché en fonction de la sélection du paramètre.numberA, qui est un type numérique.numberAêtre affiché ou caché en fonction du paramètreisShowA(type booléen) est vrai ou faux.numberAsur les paramètres d'interface tels que:numberA@isShowA.

img

De cette façon, si le paramètreisShowAn'est pas vérifié, le paramètrenumberAPour ce qui est des paramètres du type de commande ComboBox, la partie dépendante des paramètres consiste à juger si la valeur du paramètre est égale àvaleur de l'indiceDe la même façon, prendre paramètreisShowALorsque vous définissez les variables dans les paramètres, écrivez:numberA@combox==2Le paramètrenumberAaffichera ou cachera, selon que le paramètrecomboxsera vérifiée comme étant la troisième option (où l'indice 0 correspond à la première option, l'indice 1 correspond à la deuxième option et l'indice 2 correspond à la troisième option).

Paramètres d'interface de stratégie, commandes interactives et fonction de regroupement de paramètres sur Template: Il suffit d'ajouter(?First group)au début de la description du paramètre qui démarre le regroupement, comme indiqué sur la figure suivante:

img

Lorsque vous utilisez la stratégie, les paramètres sont affichés en groupes:

img

Enregistrer la valeur par défaut du paramètre: Les paramètres de stratégie sont montrés sur la figure.Save settingsle bouton après modification des paramètres de stratégie.

img

img

Vous pouvez enregistrer les paramètres de stratégie sous forme de code:

/*backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",2],["string","Hello FMZ.COM"],["combox",2],["bool",false],["numberA@isShowA",666],["isShowA",true]]
*/
'''backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",2],["string","Hello FMZ.COM"],["combox",2],["bool",false],["numberA@isShowA",666],["isShowA",true]]
'''
/*backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",2],["string","Hello FMZ.COM"],["combox",2],["bool",false],["numberA@isShowA",666],["isShowA",true]]
*/

Structure des données

Certaines fonctions seront accompagnées de l'originalJSONLes données demandées pendant l'appel.JSONles données sont stockées dans l'attributInfoPuisque le backtest n'est pas pour accéder à une interface de plateforme, les données renvoyées pendant le backtest n'ont pas d'attributInfo. Voici une description des principaux attributs de chaque structure de données.

Le commerce

Obtenir tout l'historique des transactions (pas lui-même), renvoyé par la fonctionexchange.GetTrades().

{
    Id      : 9585306,          // Trading record ID; if the exchange interface does not provide order ID, use the timestamp to fill in 
    Time    : 1567736576000,    // Time (Unix timestamp milliseconds)
    Price   : 1000,             // Price
    Amount  : 1,                // Volume
    Type    : 0                 // Order Type; refer to the order type in the constants; 0 is ORDER_TYPE_BUY, meaning the value of ORDER_TYPE_BUY is 0
}
Les tiques

Les cotations de marché sont renvoyées par la fonctionexchange.GetTicker().

{
    Info    : {...},             // After requesting the platform interface, this attribute is not available in the raw data that the exchange interface responds to, during the backtest
    High    : 1000,              // Highest price; if the platform interface does not provide the 24-hour highest price, use sell price 1 to fill in 
    Low     : 500,               // Lowest price; if the platform interface does not provide the 24-hour lowest price, use buy price 1 to fill in 
    Sell    : 900,               // Sell price 1
    Buy     : 899,               // Buy price 1 
    Last    : 900,               // Last executed price
    Volume  : 10000000,          // Recent trading volume; in principle, the unit of spot trading volume is base currency, and the unit of futures trading volume is contract quantity. If the platform interface does not provide this kind of data, use the existing data of the platform interface to fill in; for instance, it might be a trading volume in the unit of quote currency  
    Time    : 1567736576000      // Millisecond-level timestamp
}
Enregistrement

La normeOHLCCette fonction est utilisée pour tracer des lignes K et pour le calcul et l'analyse des indicateurs de processus.exchange.GetRecords()renvoie le tableau de structure.Recordla structure représente une barre de ligne k, à savoir une ligne kBARLeTimedans leRecordest l'heure de début de la période en barres de la ligne K.

{
    Time    : 1567736576000,     // A timestamp, accurate to millisecond, in the same format as the result obtained by Javascript's newDate().GetTime()
    Open    : 1000,              // Open price
    High    : 1500,              // Highest price
    Low     : 900,               // Lowest price
    Close   : 1200,              // Close price 
    Volume  : 1000000            // Trading volume; in principle, the unit of spot trading volume is base currency, and the unit of futures trading volume is contract quantity. If the platform interface does not provide this kind of data, use the existing data of the platform interface to fill in; for instance, it might be a trading volume in the unit of quote currency
}
Les ordres

La structure d'ordre peut être renvoyée par des fonctions, y comprisexchange.GetOrder()etexchange.GetOrders(). La fonctionexchange.GetOrders()renvoie le tableau ou un tableau vide de la structure (s'il n'y a pascommande inachevée en cours, retourner[], à savoir un tableau vide).

{
    Info        : {...},         // After requesting the platform interface, this attribute is not available in the raw data that the exchange interface responds to, during the backtest
    Id          : 123456,        // Unique ide