avatar of 发明者量化-小小梦 发明者量化-小小梦
Suivre Messages privés
4
Suivre
1271
Abonnés

Parlons de l'expérience de développement de stratégies de trading

Créé le: 2019-08-06 17:15:13, Mis à jour le: 2023-10-20 20:06:49
comments   4
hits   3416

Parlons de l’expérience de développement de stratégies de trading

Parlons de l’expérience de développement de stratégies de trading

Le but de cet article est de partager quelques expériences et conseils en matière de développement de stratégies, qui peuvent permettre aux lecteurs d’appréhender rapidement l’expérience du développement de stratégies de trading. Lorsque l’on rencontre des problèmes similaires dans la conception d’une stratégie, des solutions raisonnables peuvent être immédiatement conçues. La plateforme de trading quantitative Inventor est utilisée comme plate-forme d’explication, de test et de pratique. Langage de programmation des politiques : JavaScript Marché commercial : marché des actifs blockchain (BTC, ETH, etc.)

  • ## Acquisition et traitement des données

Habituellement, en fonction de la logique de la stratégie, il est possible d’utiliser les différentes interfaces suivantes pour obtenir des données de marché, car la logique de trading de la stratégie est généralement pilotée par les données de marché (bien sûr, il existe certaines stratégies qui ne regardent pas le marché). , telles que les stratégies d’investissement fixe).

  • GetTicker : obtenez des informations sur les ticks en temps réel. Il est généralement utilisé pour obtenir rapidement le dernier prix actuel, le prix d’achat et le prix de vente.

  • GetDepth : obtenez des cotations sur la profondeur du carnet d’ordres. Il est généralement utilisé pour obtenir le prix de chaque niveau et la taille de la commande. Utilisé pour les stratégies de couverture, les stratégies de création de marché, etc.

  • GetTrade : obtenez les derniers enregistrements de transactions sur le marché. Il est généralement utilisé pour analyser le comportement du marché sur une courte période de temps et analyser les micro-changements du marché. Habituellement utilisé dans les stratégies à haute fréquence et les stratégies algorithmiques.

  • GetRecords : obtenez des données K-line du marché. Souvent utilisé dans les stratégies de suivi de tendance. Utilisé pour calculer les indicateurs.

  • Tolérance aux pannes

    Lors de la conception de stratégies, les novices ignorent généralement diverses situations d’erreur et croient intuitivement que les résultats de chaque lien de la stratégie sont prédéterminés. Mais en réalité, ce n’est pas le cas. Lors de la demande de données de marché pendant le fonctionnement du programme de stratégie, diverses situations inattendues seront rencontrées. Par exemple, certaines interfaces de marché renvoient des données anormales :

    var depth = exchange.GetDepth()
    
    
    // depth.Asks[0].Price < depth.Bids[0].Price      卖一价格低于了买一价格,这种情况不可能存在于盘面上,
    //                                                因为卖出的价格低于买入的价格,必定已经成交了。
    // depth.Bids[n].Amount = 0                       订单薄买入列表第n档,订单量为0
    // depth.Asks[m].Price = 0                        订单薄卖出列表第m档,订单价格为0
    

    Ou exchange.GetDepth() renvoie directement une valeur nulle.

    Il existe de nombreuses situations étranges de ce genre. Par conséquent, un traitement correspondant doit être effectué pour ces problèmes prévisibles, et ce type de solution de traitement est appelé traitement tolérant aux pannes.

    L’approche habituelle de tolérance aux pannes consiste à supprimer les données et à les récupérer à nouveau.

    Par exemple:

    function main () {
        while (true) {
            onTick()
            Sleep(500)
        }
    }
    
    
    function GetTicker () {
        while (true) {
            var ticker = exchange.GetTicker()
            if (ticker.Sell > ticker.Buy) {       // 以 检测卖一价格是不是小于买一价这个错误的容错处理为例,
                                                  // 排除这个错误,当前函数返回 ticker 。
                return ticker
            }
            Sleep(500)
        }
    }
    
    
    function onTick () {
        var ticker = GetTicker()                  // 确保获取到的 ticker 不会存在 卖一价格小于买一价格这种数据错误的情况。
        // ...  具体的策略逻辑
    }
    

    D’autres processus tolérants aux pannes prévisibles peuvent être traités de manière similaire. Le principe de conception est que des données incorrectes ne doivent jamais être utilisées pour piloter la logique stratégique.

  • Utilisation des données K-line

    Acquisition de données K-line, appel :

    var r = exchange.GetRecords()
    

    Les données de la ligne K obtenues sont un tableau, tel que celui-ci :

    [
        {"Time":1562068800000,"Open":10000.7,"High":10208.9,"Low":9942.4,"Close":10058.8,"Volume":6281.887000000001},
        {"Time":1562072400000,"Open":10058.6,"High":10154.4,"Low":9914.5,"Close":9990.7,"Volume":4322.099},
        ...
        {"Time":1562079600000,"Open":10535.1,"High":10654.6,"Low":10383.6,"Close":10630.7,"Volume":5163.484000000004}
    ]
    

    Vous pouvez voir que chaque accolade{}Il comprend l’heure, le prix d’ouverture (open), le prix le plus élevé (high), le prix le plus bas (low), le prix de clôture (close) et le volume des transactions (volume). C’est un chandelier. Généralement, les données de la ligne K sont utilisées pour calculer des indicateurs, tels que la moyenne mobile MA, le MACD, etc. Saisissez les données de la ligne K comme paramètres (données sur les matières premières), puis définissez les paramètres de l’indicateur et calculez la fonction des données de l’indicateur, que nous appelons la fonction de l’indicateur. Il existe de nombreuses fonctions d’indicateur sur la plateforme de trading quantitatif Inventor.

    Par exemple, lorsque nous calculons l’indicateur de moyenne mobile, en fonction des différentes périodes des données K-line que nous transmettons, nous calculons la moyenne mobile de la période correspondante. Par exemple, si les données K-line quotidiennes sont transmises (une barre K-line représente un jour), l’indicateur calculé est la moyenne mobile quotidienne. De même, si les données K-line transmises à la fonction d’indicateur de moyenne mobile sont une période d’une heure, alors l’indicateur calculé est la moyenne mobile sur une heure.

    En général, lorsque nous calculons des indicateurs, nous oublions souvent un problème. Si je veux calculer l’indicateur de moyenne mobile sur 5 jours, nous préparons d’abord les données quotidiennes de la ligne K :

    var r = exchange.GetRecords(PERIOD_D1)  // 给GetRecords 函数传入参数 PERIOD_D1就是指定获取日K线,
                                            // 具体函数使用可以参看:https://www.fmz.com/api#GetRecords
    

    Avec les données quotidiennes de la ligne K, nous pouvons calculer l’indicateur de moyenne mobile. Si nous voulons calculer la moyenne mobile sur 5 jours, nous devons définir le paramètre d’indicateur de la fonction d’indicateur sur 5.

    var ma = TA.MA(r, 5)        // TA.MA() 就是指标函数,用来计算均线指标,第一个参数设置刚才获取的日K线数据r,
                                // 第二个参数设置5,计算出来的就是5日均线,其它指标函数同理。
    

    Nous avons négligé un problème potentiel. Que se passe-t-il si le nombre de barres K-line dans les données K-line du jour r est inférieur à 5 ? Pouvons-nous calculer un indicateur de moyenne mobile sur 5 jours valide ? La réponse est définitivement non. Parce que l’indicateur de moyenne mobile sert à trouver la moyenne des prix de clôture d’un certain nombre de barres K-line.

    Parlons de l’expérience de développement de stratégies de trading

    Par conséquent, avant d’utiliser les données K-line et les fonctions indicatrices pour calculer les données indicatrices, il est nécessaire de déterminer si le nombre de colonnes K-line dans les données K-line répond aux conditions de calcul de l’indicateur (paramètres de l’indicateur).

    Par conséquent, avant de calculer la moyenne mobile sur 5 jours, il est nécessaire de faire un jugement. Le code complet est le suivant :

    function CalcMA () {
        var r = _C(exchange.GetRecords, PERIOD_D1)     // _C() 是容错函数,目的就是避免 r 为 null , 具体可以查询文档:https://www.fmz.com/api#_C
        if (r.length > 5) {
            return TA.MA(r, 5)                         // 用均线指标函数 TA.MA 计算出均线数据,做为函数返回值,返回。
        }
    
    
        return false 
    }
    
    
    function main () {
        var ma = CalcMA()
        Log(ma)
    }
    

    Parlons de l’expérience de développement de stratégies de trading

    Les backtests montrent : [null,null,null,null,4228.7,4402.9400000000005, … ]

    On peut voir que les quatre premiers des indicateurs de moyenne mobile sur 5 jours calculés sont nuls, car le nombre de colonnes K-line est inférieur à 5 et la moyenne ne peut pas être calculée. À partir du 5ème chandelier, cela peut être calculé.

  • Conseils pour juger les mises à jour de la ligne K

    Lorsque nous écrivons certaines stratégies, il existe souvent un scénario dans lequel nous devons traiter certaines opérations ou imprimer certains journaux lorsque chaque cycle de ligne K est terminé. Comment pouvons-nous obtenir cette fonctionnalité ? Pour les débutants qui n’ont aucune expérience en programmation, il se peut qu’ils ne sachent pas quel mécanisme utiliser pour gérer ce problème. Nous vous donnerons ici directement quelques conseils.

    Nous pouvons juger qu’un cycle de colonne K-line est terminé en commençant par l’attribut time dans les données K-line. Chaque fois que nous obtenons des données K-line, nous évaluons l’attribut Time dans les données de la dernière colonne K-line de ces données K-line. Si cette valeur d’attribut a changé. Si elle a changé, cela signifie qu’une nouvelle colonne K-line a été générée (prouvant que le cycle de colonne K-line précédent de la colonne K-line nouvellement générée a (est terminé). Si elle n’a pas changé, cela signifie qu’il n’y a pas de Un nouveau chandelier est généré (le dernier cycle de chandelier actuel n’est pas encore terminé).

    Nous avons donc besoin d’une variable pour enregistrer l’heure de la dernière colonne de chandelier des données du chandelier.

    var r = exchange.GetRecords()
    var lastTime = r[r.length - 1].Time       // lastTime 用来记录最后一根K线柱的时间。
    

    Dans les applications pratiques, la structure est généralement la suivante :

    function main () {
        var lastTime = 0
        while (true) {
            var r = _C(exchange.GetRecords)
            if (r[r.length - 1].Time != lastTime) {
                Log("新K线柱产生")
                lastTime = r[r.length - 1].Time      // 一定要更新 lastTime ,这个至关重要。
    
    
                // ... 其它处理逻辑
                // ...
            }
    
    
            Sleep(500)
        }
    }
    

    Parlons de l’expérience de développement de stratégies de trading

    On peut voir que dans le backtest, la période K-line est définie sur jour (la fonction exchange.GetRecords est appelée sans spécifier de paramètres, et la période K-line définie selon le backtest est le paramètre par défaut). Chaque fois qu’un nouveau La colonne K-line apparaît, elle est imprimée Un journal.

  • Calculs numériques

    • ### Calculer le temps nécessaire pour accéder à l’interface d’échange

    Si vous souhaitez afficher ou contrôler le temps nécessaire à une stratégie pour accéder à l’interface de l’échange, vous pouvez utiliser le code suivant :

    function main () {
        while (true) {
            var beginTime = new Date().getTime()
            var ticker = exchange.GetTicker()
            var endTime = new Date().getTime()
    
    
            LogStatus(_D(), "GetTicker() 函数耗时:", endTime - beginTime, "毫秒")
            Sleep(1000)
        } 
    }
    

    En termes simples, l’horodatage enregistré après l’appel de la fonction GetTicker est soustrait de l’horodatage avant l’appel pour calculer le nombre de millisecondes qui se sont écoulées, c’est-à-dire le temps nécessaire à la fonction GetTicker pour s’exécuter et renvoyer le résultat.

    • ### Utilisez Math.min / Math.max pour définir les limites supérieures et inférieures des valeurs

    Si vous souhaitez une limite supérieure numérique, vous utilisez généralement Math.min pour limiter

    Par exemple, lors du placement d’un ordre de vente, le montant de l’ordre ne doit pas être supérieur au nombre de pièces sur le compte. Car si celui-ci est supérieur au nombre de pièces disponibles sur le compte, une erreur sera signalée lors de la passation d’une commande.

    Habituellement contrôlé comme ceci : Par exemple, vous prévoyez de passer un ordre de vente pour 0,2 pièce.

    var planAmount = 0.2
    var account = _C(exchange.GetAccount)
    var amount = Math.min(account.Stocks, planAmount)
    

    Cela garantit que le montant, le montant de la commande à passer, ne dépasse pas le nombre de pièces disponibles sur le compte.

    De même, Math.max est utilisé pour garantir une limite inférieure pour une valeur. À quel type de scénarios cela s’applique-t-il généralement ? En règle générale, les bourses imposent une limite de quantité minimale de commande pour certaines paires de trading. Si la quantité commandée est inférieure à cette quantité minimale de commande, la commande sera rejetée. De cette façon, la commande échouera. Supposons que la quantité minimale de commande pour BTC soit généralement de 0,01. Parfois, la stratégie de trading peut calculer que la quantité de commande est inférieure à 0,01, nous pouvons donc utiliser Math.max pour garantir la quantité minimale de commande.

    • ### Contrôle précis de la quantité et du prix des commandes

    Peut être utilisé_Fonction N() ou fonction SetPrecision pour contrôler la précision.

    La fonction SetPrecision() ne doit être définie qu’une seule fois et le système tronquera automatiquement les décimales en excès dans les valeurs de quantité et de prix de la commande.

    _La fonction N() permet de tronquer une valeur à un certain nombre de décimales (contrôle de précision)

    Par exemple:

    var pi = _N(3.141592653, 2)
    Log(pi)
    

    La valeur de pi est tronquée à 2 décimales, soit : 3,14

    Consultez la documentation de l’API pour plus de détails.

  • Quelques paramètres logiques

    • ### Timing : effectuer certaines opérations à une certaine période de temps

    Vous pouvez utiliser ce mécanisme pour utiliser la méthode de détection d’horodatage afin de déterminer l’horodatage actuel moins l’horodatage de la dernière fois où la tâche planifiée a été terminée et calculer le temps écoulé en temps réel. Lorsque le temps écoulé dépasse une certaine durée définie Après cela , la nouvelle opération est exécutée.

    Par exemple, il est utilisé dans les stratégies d’investissement fixe.

    var lastActTime = 0
    var waitTime = 1000 * 60 * 60 * 12   // 一天的毫秒数
    function main () {
        while (true) {
            var nowTime = new Date().getTime()
            if (nowTime - lastActTime > waitTime) {
                Log("执行定投")
                // ... 具体的定投操作,买入操作。
    
    
                lastActTime = nowTime
            }
    
    
            Sleep(500)
        }
    }
    

    Ceci est un exemple simple.

    • ### Concevoir des mécanismes de récupération automatique pour les stratégies

    En utilisant la fonction quantifiée _G() de l’inventeur et la fonction de sauvegarde de sortie, il est très pratique de concevoir une stratégie pour quitter et sauvegarder la progression, et redémarrer pour restaurer automatiquement l’état.

    var hold = {
        price : 0, 
        amount : 0,
    }
    
    
    function main () {
        if (_G("hold")) {
            var ret = _G("hold")
            hold.price = ret.price
            hold.amount = ret.amount
            Log("恢复 hold:", hold)
        }
    
    
        var count = 1
        while (true) {
            // ... 策略逻辑
            // ... 策略运行中,可能开仓,交易,把开仓的持仓价格赋值给 hold.price ,开仓的数量赋值给 hold.amount,用以记录持仓信息。
    
    
            hold.price = count++     // 模拟一些数值
            hold.amount = count/10   // 模拟一些数值
    
    
            Sleep(500)
        }
    }
    
    
    function onexit () {    // 点击机器人上的停止按钮,会触发执行这个函数,执行完毕机器人停止。
        _G("hold", hold)
        Log("保存 hold:", JSON.stringify(hold))
    }
    

    Parlons de l’expérience de développement de stratégies de trading

    On peut voir qu’à chaque arrêt du robot, les données de l’objet hold sont enregistrées. A chaque redémarrage, les données sont lues et la valeur hold est restaurée à l’état de l’arrêt précédent. Bien entendu, ce qui précède est un exemple simple. S’il est utilisé dans une stratégie réelle, il doit être conçu en fonction des données clés qui doivent être restaurées dans la stratégie (généralement les informations de compte, les positions, les valeurs de profit, les directions de trading, etc.) .). Bien entendu, vous pouvez également définir certaines conditions pour déterminer si vous souhaitez restaurer.

Voici quelques conseils pour développer des stratégies. J’espère qu’ils seront utiles aux débutants et aux développeurs de stratégies ! Le moyen le plus rapide de s’améliorer est de pratiquer ! Je vous souhaite à tous de continuer à faire des bénéfices.