Utiliser le plug-in du terminal de trading pour faciliter le trading manuel

Auteur:La bonté, Créé: 2020-07-30 11:39:54, Mis à jour: 2023-10-25 19:56:42

img

Introduction au projet

FMZ.COM, en tant que plate-forme de trading quantitative, est principalement destinée à servir les traders programmatiques. Mais elle fournit également un terminal de trading de base. Bien que la fonction soit simple, elle peut parfois être utile. Par exemple, si l'échange est occupé et ne peut pas être exploité, mais l'API fonctionne toujours. À ce moment-là, vous pouvez retirer des ordres, passer des ordres et les afficher via le terminal. Afin d'améliorer l'expérience du terminal de trading, des plug-ins sont maintenant ajoutés. Parfois, nous avons besoin d'une petite fonction pour aider la transaction, comme les ordres en attente d'échelle, les ordres d'iceberg, la couverture en un clic, les positions de clôture en un clic et d'autres opérations. Il n'est pas nécessaire de regarder le journal d'exécution du robot. Il est un peu lourd de créer un nouveau robot. Il suffit de cliquer sur le plugin dans le terminal, Les fonctions correspondantes peuvent être réalisées immédiatement, ce qui peut grandement faciliter les transactions manuelles.

img

Principe du branchement

Il existe deux modes d'opération du plug-in, opération immédiate et opération en arrière-plan. L'exécution en arrière-plan est équivalente à la création d'un robot (charges normales). Le principe de l'opération immédiate est le même que celui de l'outil de débogage: envoyer un morceau de code au docker de la page du terminal de trading pour exécution, et prendre en charge le retour de graphiques et de tableaux (l'outil de débogage est actuellement également mis à niveau pour prendre en charge), le même ne peut être exécuté que pendant 5 minutes, sans frais, sans restrictions Langue. Les plug-ins avec un temps d'exécution court peuvent utiliser le mode d'exécution immédiate, tandis que les stratégies complexes et à long terme doivent encore exécuter des robots.

Lorsque vous écrivez une stratégie, vous devez sélectionner le type de stratégie en tant que plug-in.mainfonctionreturnde l'exécution du plug-in apparaîtra dans le terminal après l'opération est terminée, soutenant les chaînes, dessins et tables.returnle résultat de l'exécution du plug-in.

Comment utiliser

  • Ajouter une stratégie

Cherchez directement dans la zone de recherche comme indiqué sur la figure. Notez que seules les stratégies de type plugin de trading peuvent être exécutées, puis cliquez sur Ajouter. Les plugins publics se trouvent dans Strategy Square:https://www.fmz.com/square/21/1

img img

  • Exécutez le plugin

Cliquez sur la stratégie pour entrer dans l'interface de réglage des paramètres. S'il n'y a pas de paramètres, il s'exécutera directement. Le docker, la paire de négociation et la période de ligne K sélectionnés par le terminal de négociation sont les paramètres correspondants par défaut. Cliquez sur la stratégie d'exécution pour commencer l'exécution et sélectionnez le mode Execute Now (vous pouvez vous souvenir du mode d'opération par défaut). Le plugin n'affichera pas le journal.

img

  • Arrêtez le plugin

Cliquez sur la position de l'icône pour arrêter le plug-in. Puisque tous les plug-ins sont exécutés dans un processus d'outil de débogage, tous les plug-ins seront arrêtés.

img

Exemples d'utilisation des plug-ins

Les plug-ins peuvent exécuter du code pendant une période de temps et effectuer certaines opérations simples. Dans de nombreux cas, les opérations manuelles nécessitant des opérations répétées peuvent être implémentées avec des plug-ins pour faciliter les transactions.

Assistance à la négociation manuelle de couverture intertemporelle des contrats à terme

Le trading de hedge intertemporel est une stratégie très courante. Parce que la fréquence n'est pas très élevée, beaucoup de gens l'opéreront manuellement. Il est nécessaire de faire un contrat long et un contrat court, il est donc préférable d'analyser la tendance de propagation. L'utilisation de plug-ins dans le terminal de trading vous permettra d'économiser de l'énergie.

La première introduction consiste à dessiner le plug-in de la différence de prix entre les périodes:

var chart = { 
   __isStock: true,    
   title : { text : 'Spread analysis chart'},                     
   xAxis: { type: 'datetime'},                 
   yAxis : {                                        
       title: {text: 'Spread'},                   
       opposite: false,                             
   },
   series : [                    
       {name : "diff", data : []}, 

   ]
}
function main() {
   exchange.SetContractType('quarter')
   var recordsA = exchange.GetRecords(PERIOD_M5) //Cycle can be customized
   exchange.SetContractType('this_week')
   var recordsB = exchange.GetRecords(PERIOD_M5)
   
   for(var i=0;i<Math.min(recordsA.length,recordsB.length);i++){
       var diff = recordsA[recordsA.length-Math.min(recordsA.length,recordsB.length)+i].Close - recordsB[recordsB.length-Math.min(recordsA.length,recordsB.length)+i].Close
       chart.series[0].data.push([recordsA[recordsA.length-Math.min(recordsA.length,recordsB.length)+i].Time, diff])
   }
   return chart
}

Cliquez une fois, la récente différence de prix entre les périodes est claire en un coup d'œil, l'adresse de copie du code source du plugin:https://www.fmz.com/strategy/187755

img

Avec l'analyse des spreads, on constate que le spread converge. C'est l'occasion de raccourcir le contrat trimestriel et d'aller long pour la semaine en cours. C'est l'occasion d'utiliser le plug-in de couverture en un clic, un clic vous aidera automatiquement à raccourcir le trimestriel et le long hebdomadaire, ce qui est plus rapide que l'opération manuelle. Le principe de mise en œuvre de la stratégie est d'ouvrir le même nombre de positions avec un prix glissant. Vous pouvez courir plusieurs fois de plus pour atteindre lentement votre position souhaitée afin d'éviter d'avoir un impact sur le marché. Vous pouvez modifier les paramètres par défaut pour passer des commandes plus rapidement. Adresse de copie de la stratégie:https://www.fmz.com/strategy/191348

function main(){
    exchange.SetContractType(Reverse ? Contract_B : Contract_A)
    var ticker_A = exchange.GetTicker()
    if(!ticker_A){return 'Unable to get quotes'}
    exchange.SetDirection('buy')
    var id_A = exchange.Buy(ticker_A.Sell+Slip, Amount)
    exchange.SetContractType(Reverse ? Contract_B : Contract_A)
    var ticker_B = exchange.GetTicker()
    if(!ticker_B){return 'Unable to get quotes'}
    exchange.SetDirection('sell')
    var id_B = exchange.Sell(ticker_B.Buy-Slip, Amount)
    if(id_A){
        exchange.SetContractType(Reverse ? Contract_B : Contract_A)
        exchange.CancelOrder(id_A)
    }
    if(id_B){
        exchange.SetContractType(Reverse ? Contract_B : Contract_A)
        exchange.CancelOrder(id_B)
    }
    return 'Position: ' + JSON.stringify(exchange.GetPosition())
}

En attendant que la différence de prix converge et que vous ayez besoin de fermer la position, vous pouvez exécuter le plugin de fermeture en un clic pour fermer la position le plus rapidement possible.

function main(){
    while(ture){
        var pos = exchange.GetPosition()
        var ticker = exchange.GetTicekr()
        if(!ticker){return 'Unable to get ticker'}
        if(!pos || pos.length == 0 ){return 'No holding position'}
        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)
            }
        }
    }
}

Plug-in pour faciliter le trading au comptant

Le plus courant est la commission de l'iceberg, qui divise les gros ordres en petits ordres. Bien qu'il puisse être exécuté comme un robot, un plug-in de 5 minutes est en fait suffisant. Il existe deux types d'ordres d'iceberg, l'un est de prendre des ordres et l'autre est en attente d'ordres. S'il y a un frais préférentiel, vous pouvez choisir les ordres en attente, ce qui signifie que le temps d'exécution est plus long.

Le code suivant est le code source du plug-in commandé par iceberg:https://www.fmz.com/strategy/191771À vendre:https://www.fmz.com/strategy/191772

function main(){
    var initAccount = _C(exchange.GetAccount)
    while(true){
        var account = _C(exchange.GetAccount)
        var dealAmount = account.Stocks - initAccount.Stocks
        var ticker = _C(exchange.GetTicker)
        if(BUYAMOUNT - dealAmount >= BUYSIZE){
            var id = exchange.Buy(ticker.Sell, BUYSIZE)
            Sleep(INTERVAL*1000)
            if(id){
                exchange.CancelOrder(id) // May cause error log when the order is completed, which is all right.
            }else{
                throw 'buy error'
            }
        }else{
            account = _C(exchange.GetAccount)
            var avgCost = (initAccount.Balance - account.Balance)/(account.Stocks - initAccount.Stocks)
            return 'Iceberg order to buy is done, avg cost is '+avgCost
        }
        
    }
}

Il s'agit également d'une façon de lentement expédier des produits pour occuper acheter 1 ou vendre 1 couche de prix tout le temps, et l'impact sur le marché est relativement faible.

À acheter:https://www.fmz.com/strategy/191582

À vendre:https://www.fmz.com/strategy/191730

function GetPrecision(){
    var precision = {price:0, amount:0}
    var depth = exchange.GetDepth()
    for(var i=0;i<exchange.GetDepth().Asks.length;i++){
        var amountPrecision = exchange.GetDepth().Asks[i].Amount.toString().indexOf('.') > -1 ? exchange.GetDepth().Asks[i].Amount.toString().split('.')[1].length : 0
        precision.amount = Math.max(precision.amount,amountPrecision)
        var pricePrecision = exchange.GetDepth().Asks[i].Price.toString().indexOf('.') > -1 ? exchange.GetDepth().Asks[i].Price.toString().split('.')[1].length : 0
        precision.price = Math.max(precision.price,pricePrecision)
    }
    return precision
}

function main(){
    var initAccount = exchange.GetAccount()
    if(!initAccount){return 'Unable to get account information'}
    var precision = GetPrecision()
    var buyPrice = 0
    var lastId = 0
    var done = false
    while(true){
        var account = _C(exchange.GetAccount)
        var dealAmount = account.Stocks - initAccount.Stocks
        var ticker = _C(exchange.GetTicker)
        if(BuyAmount - dealAmount > 1/Math.pow(10,precision.amount) && ticker.Buy > buyPrice){
            if(lastId){exchange.CancelOrder(lastId)}
            var id = exchange.Buy(ticker.Buy, _N(BuyAmount - dealAmount,precision.amount))
            if(id){
                lastId = id
            }else{
                done = true
            }
        }
        if(BuyAmount - dealAmount <= 1/Math.pow(10,precision.amount)){done = true}
        if(done){
            var avgCost = (initAccount.Balance - account.Balance)/dealAmount
            return 'order is done, avg cost is ' + avgCost  // including fee cost
        }
        Sleep(Intervel*1000)
    }
}

Parfois, afin de vendre un meilleur prix d'expédition ou d'attendre une commande en attente, plusieurs commandes peuvent être passées à un certain intervalle.https://www.fmz.com/strategy/190017

function main() {
    var ticker = exchange.GetTicker()
    if(!ticker){
        return  'Unable to get price'
    }
    for(var i=0;i<N;i++){
        if(Type == 0){
            if(exchange.GetName().startsWith('Futures')){
                exchange.SetDirection('buy')
            }
            exchange.Buy(Start_Price-i*Spread,Amount+i*Amount_Step)
        }else if(Type == 1){
            if(exchange.GetName().startsWith('Futures')){
                exchange.SetDirection('sell')
            }
            exchange.Sell(Start_Price+i*Spread,Amount+i*Amount_Step)
        }else if(Type == 2){
            exchange.SetDirection('closesell')
            exchange.Buy(Start_Price-i*Spread,Amount+i*Amount_Step)
        }
        else if(Type == 3){
            exchange.SetDirection('closebuy')
            exchange.Sell(Start_Price+i*Spread,Amount+i*Amount_Step)
        }
        Sleep(500)
    }
    return 'order complete'
}

Plug-in pour faciliter le commerce à terme de matières premières

Les logiciels de trading de contrats à terme couramment utilisés ont souvent de nombreuses fonctions avancées d'ordre en attente, telles que les ordres d'arrêt-perte en attente, les ordres de condition en attente, etc., qui peuvent facilement être écrits sous forme de plug-ins. Voici un plugin pour fermer un ordre en attente immédiatement après la négociation de l'ordre en attente.https://www.fmz.com/strategy/187736

var buy = false
var trade_amount = 0
function main(){
    while(true){
        if(exchange.IO("status")){
            exchange.SetContractType(Contract)
            if(!buy){
                buy = true
                if(Direction == 0){
                    exchange.SetDirection('buy')
                    exchange.Buy(Open_Price, Amount)
                }else{
                    exchange.SetDirection('sell')
                    exchange.Sell(Open_Price, Amount)
                }
            }
            var pos = exchange.GetPosition()
            if(pos && pos.length > 0){
                for(var i=0;i<pos.length;i++){
                    if(pos[i].ContractType == Contract && pos[i].Type == Direction && pos[i].Amount-pos[i].FrozenAmount>0){
                        var cover_amount = math.min(Amount-trade_amount, pos[i].Amount-pos[i].FrozenAmount)
                        if(cover_amount >= 1){
                            trade_amount += cover_amount
                            if(Direction == 0){
                                exchange.SetDirection('closebuy_today')
                                exchange.Sell(Close_Price, cover_amount)
                            }else{
                                exchange.SetDirection('closesell_today')
                                exchange.Buy(Close_Price, cover_amount)
                            }
                        }
                    }
                }
            }
        } else {
            LogStatus(_D(), "CTP is not connected!")
            Sleep(10000)
        }
        if(trade_amount >= Amount){
            Log('mission completed')
            return
        }
        Sleep(1000)
    }
}

Pour résumer

Après avoir lu tant de petites fonctions, vous devriez également avoir vos propres idées.


Relationnée

Plus de