Les ressources ont été chargées... Je charge...

Stratégie d'arbitrage interpériodique de la monnaie numérique basée sur la bande de Bollinger

Auteur:FMZ~Lydia, Créé: 2022-12-02 16:58:27, Mis à jour: 2023-09-20 09:33:29

img

Stratégie d'arbitrage interpériodique de la monnaie numérique basée sur la bande de Bollinger

I. Résumé

George Soros a proposé une proposition importante dans The Alchemy of Finance écrit en 1987: Je crois que les prix du marché sont toujours faux dans le sens où ils présentent une vision biaisée de l'avenir. L'hypothèse de l'efficacité du marché n'est qu'une hypothèse théorique. En fait, les participants au marché ne sont pas toujours rationnels et à chaque moment, les participants ne peuvent pas obtenir et interpréter objectivement toutes les informations. De plus, même s'il s'agit de la même information, les commentaires de chacun sont différents. C'est-à-dire que le prix lui-même contient déjà les mauvaises attentes des participants au marché, donc en substance, le prix du marché est toujours faux.

II. Principes stratégiques

Selon les principes ci-dessus, nous pouvons savoir que dans un marché à terme inefficace, la raison pour laquelle l'impact du marché sur les contrats de livraison à différentes périodes n'est pas toujours synchrone et la tarification n'est pas complètement efficace. Ensuite, en fonction du prix du contrat de livraison de l'objet de la même transaction à différentes périodes, s'il y a une grande différence de prix entre les deux prix, nous pouvons acheter et vendre des contrats à terme à différentes périodes en même temps pour l'arbitrage interpériodique. Comme les contrats à terme sur matières premières, la monnaie numérique a également un portefeuille de contrats d'arbitrage interpériodique. Par exemple, dans l'échange OKEX, il y a: ETC semaine en cours, ETC semaine prochaine, ETC trimestre. Par exemple, supposons que la différence de prix entre la semaine courante d'ETC et le trimestre d'ETC reste autour de 5 pendant longtemps. Si la différence de prix atteint 7 un jour, nous nous attendons à ce que la différence de prix revienne à 5 à l'avenir. Nous pouvons alors vendre ETC cette semaine et acheter ETC trimestre en même temps pour court-circuiter la différence de prix, et vice versa. Bien que cette différence de prix existe, il existe de nombreuses incertitudes dans l'arbitrage manuel en raison des opérations manuelles chronophages, de la mauvaise précision et de l'impact des changements de prix. Le charme de l'arbitrage quantitatif réside dans la capture des opportunités d'arbitrage grâce à des modèles quantitatifs et la formulation de stratégies de négociation d'arbitrage, ainsi que dans le placement d'ordres de négociation automatiquement sur les bourses via des algorithmes programmés, afin de capturer les opportunités rapidement et précisément et de réaliser des profits de manière efficace et

III. La logique de la stratégie

Cet article vous apprendra à utiliser la plateforme de trading FMZ Quant et le contrat à terme ETC sur l'échange OKEX pour démontrer comment saisir les opportunités d'arbitrage instantanées, saisir les bénéfices qui peuvent être vus à chaque fois et couvrir les risques pouvant être rencontrés dans le trading de devises numériques avec une stratégie d'arbitrage simple.

Créer une stratégie d'arbitrage interpériodique pour la monnaie numérique

Difficulté: normale

Environnement stratégique

  • Objet de la transaction: Ether classique (ETC)
  • Données sur les écarts: semaine courante ETC - trimestre ETC (omettre le test de cointégration)
  • Durée de la transaction: 5 minutes
  • Correspondance de position: 1:1
  • Type d'opération: période transversale du même type

La logique de la stratégie

  • Conditions d'ouverture des positions avec une différence de prix longue: si le compte courant ne comporte aucune position et que la différence de prix est inférieure à la limite inférieure de la boll, alors la différence de prix longue. c'est-à-dire acheter des positions d'ouverture ETC pour la semaine, vendre des positions d'ouverture ETC pour le trimestre.
  • Conditions d'ouverture des positions avec une réduction de la différence de prix: s'il n'y a pas de position dans le compte courant et que la différence de prix est supérieure à la limite supérieure du boll, alors réduire la différence de prix.
  • Conditions pour la clôture des positions avec une différence de prix longue: si le compte courant détient des ordres longs d'ETC en cours dans la semaine en cours et détient des ordres courts d'ETC en cours du trimestre, et que la différence de prix est supérieure à la limite médiane de la boll, alors clôturer la différence de prix longue. c'est-à-dire vendre des positions de clôture d'ETC pour la semaine, acheter des positions de clôture d'ETC pour le trimestre.
  • Conditions de clôture des positions avec une réduction de l'écart de prix: si le compte courant détient des ordres courts d'ETC pendant la semaine en cours et des ordres longs pendant le trimestre et que l'écart de prix est inférieur à la limite du milieu de la boll, alors réduire l'écart de prix.

IV. Rédaction d'un cadre stratégique

Ce qui précède est une description logique simple de la stratégie d'arbitrage de période croisée de la monnaie numérique.

function Data() {}  // Basic data function
Data.prototype.mp = function () {}  // Position function
Data.prototype.boll = function () {}  // Indicator function
Data.prototype.trade = function () {}  // Order placement function
Data.prototype.cancelOrders = function () {}  // Order withdrawal function
Data.prototype.isEven = function () {}  // Processing single contract function
Data.prototype.drawingChart = function () {}  // Drawing function

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB);  // Create a basic data object
    var accountStocks = data.accountData.Stocks;  // Account balance
    var boll = data.boll(dataLength, timeCycle);  // Calculate the technical indicators of boll
    data.trade();  // Calculate trading conditions to place an order
    data.cancelOrders();  // Cancel orders
    data.drawingChart(boll);  // drawing
    data.isEven();  // Processing of holding individual contract
}

//Entry function
function main() {
    while (true) {  // Enter the polling mode
        onTick();  // Execute onTick function
        Sleep(500);  // Sleep for 0.5 seconds
    }
}

V. Rédaction de stratégie

Le cadre stratégique peut être facilement mis en place en fonction de l'idée stratégique et du processus de transaction. Pré-traitement avant la transaction. Obtenez et calculez les données. Faites une commande et traitez-la plus tard. Ensuite, nous devons remplir le code de détail nécessaire dans le cadre de la stratégie en fonction du processus de transaction réel et des détails de la transaction.

Pré-traitement avant la transaction Étape 1: Déclarer les variables globales nécessaires dans le champ d'application global.

//Declare a chart object for the configuration chart
var chart = { }

//Call Chart function and initialize the chart
var ObjChart = Chart ( chart )

//Declare an empty array to store price difference series
var bars = [ ]

//Declare a record history data timestamp variable
var oldTime = 0

Étape 2: configurer les paramètres externes de la stratégie.

// parameters
var tradeTypeA = "this_week"; // Arbitrage A Contract
var tradeTypeB = "quarter"; // Arbitrage B Contract
var dataLength = 10; //Indicator period length
var timeCycle = 1; // K-line period
var name = "ETC"; // Currencies
var unit = 1; // Order quantity

Étape 3: Définition de la fonction de traitement des données Fonction de base de données: Données Créez un constructeur, Data, et définissez ses propriétés internes, y compris: les données de compte, les données de position, le timestamp des données de ligne K, le prix d'achat/vente du contrat d'arbitrage A/B et la différence de prix d'arbitrage positif/négatif.

// Basic data
function Data(tradeTypeA, tradeTypeB) { // Pass in arbitrage A contract and arbitrage B contract
    this.accountData = _C(exchange.GetAccount); // Get account information
    this.positionData = _C(exchange.GetPosition); // Get position information
    var recordsData = _C(exchange.GetRecords); // Get K-line data
    exchange.SetContractType(tradeTypeA); // Subscription arbitrage A contract
    var depthDataA = _C(exchange.GetDepth); // Depth data of arbitrage A contract
    exchange.SetContractType(tradeTypeB); // Subscription arbitrage B contract
    var depthDataB = _C(exchange.GetDepth); // Depth data of arbitrage B contract
    this.time = recordsData[recordsData.length - 1].Time; // Time of obtaining the latest data
    this.askA = depthDataA.Asks[0].Price; // Sell one price of Arbitrage A contract
    this.bidA = depthDataA.Bids[0].Price; // Buy one price of Arbitrage A contract
    this.askB = depthDataB.Asks[0].Price; // Sell one price of Arbitrage B contract
    this.bidB = depthDataB.Bids[0].Price; // Buy one price of Arbitrage B contract
    // Positive arbitrage price differences (Sell one price of contract A - Buy one price of contract B)
    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
    // Negative arbitrage price differences (Buy one price of contract A - Sell one price of contract B)
    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}

Obtenez la fonction de position: mp ()) Traversez l'ensemble du tableau de position et retournez la quantité de position du contrat et de la direction spécifiés.

// Get positions
Data.prototype.mp = function (tradeType, type) {
    var positionData = this.positionData; // Get position information
    for (var i = 0; i < positionData.length; i++) {
        if (positionData[i].ContractType == tradeType) {
            if (positionData[i].Type == type) {
                if (positionData[i].Amount > 0) {
                    return positionData[i].Amount;
                }
            }
        }
    }
    return false;
}

Ligne K et fonction d'indicateur: boll ((() Une nouvelle séquence de lignes K est synthétisée selon les données d'arbitrage positif/différence de prix d'arbitrage négatif. Les données de piste supérieure, piste moyenne et piste inférieure calculées par l'indicateur de boll sont renvoyées.

// Synthesis of new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
    var self = {}; // Temporary objects
    // Median value of positive arbitrage price difference and negative arbitrage price difference
    self.Close = (this.basb + this.sabb) / 2;
    if (this.timeA == this.timeB) {
        self.Time = this.time;
    } // Compare two depth data timestamps
    if (this.time - oldTime > timeCycle * 60000) {
        bars.push(self);
        oldTime = this.time;
    } // Pass in the price difference data object into the K-line array according to the specified time period
    if (bars.length > num * 2) {
        bars.shift(); // Control the length of the K-line array
    } else {
        return;
    }
    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the talib library
    return {
        up: boll[0][boll[0].length - 1], // boll indicator upper track
        middle: boll[1][boll[1].length - 1], // boll indicator middle track
        down: boll[2][boll[2].length - 1] // boll indicator down track
    } // Return a processed boll indicator data
}

Fonction de commande: commerce Passer dans le nom de contrat de l'ordre et le type de l'ordre, puis placer l'ordre avec contrepartie, et retourner le résultat après avoir placé l'ordre.

// place the order
Data.prototype.trade = function (tradeType, type) {
    exchange.SetContractType(tradeType); // Resubscribe to a contract before placing an order
    var askPrice, bidPrice;
    if (tradeType == tradeTypeA) { // If the order is placed in contract A
        askPrice = this.askA; // set askPrice
        bidPrice = this.bidA; // set bidPrice
    } else if (tradeType == tradeTypeB) { // If the order is placed in contract B
        askPrice = this.askB; // set askPrice
        bidPrice = this.bidB; // set bidPrice
    }
    switch (type) { // Match order placement mode
        case "buy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        case "sell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closebuy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closesell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        default:
            return false;
    }
}

Annuler les commandes Fonction: annuler les commandes Obtenez un tableau de toutes les commandes en suspens et annulez-les une par une. En outre, false est retourné s'il y a une commande non remplie, et true est retourné s'il n'y a pas de commande non remplie.

// Cancel order
Data.prototype.cancelOrders = function () {
    Sleep(500); // Delay before cancellation, because some exchanges, you know what I mean
    var orders = _C(exchange.GetOrders); // Get an array of unfilled orders
    if (orders.length > 0) { // If there are unfilled orders
        for (var i = 0; i < orders.length; i++) { //Iterate through the array of unfilled orders
            exchange.CancelOrder(orders[i].Id); //Cancel unfilled orders one by one
            Sleep(500); //Delay 0.5 seconds
        }
        return false; // Return false if an unfilled order is cancelled
    }
    return true; // Return true if there are no unfilled orders
}

Gérer la tenue d'un seul contrat: isEven ((() Dans le cas d'une seule étape dans la transaction d'arbitrage, nous allons simplement fermer toutes les positions.

// Handle holding a single contract
Data.prototype.isEven = function () {
    var positionData = this.positionData; // Get position information
    var type = null; // Switch position direction
    // If the remaining 2 of the position array length is not equal to 0 or the position array length is not equal to 2
    if (positionData.length % 2 != 0 || positionData.length != 2) {
        for (var i = 0; i < positionData.length; i++) { // Iterate through the position array
            if (positionData[i].Type == 0) { // If it is a long order
                type = 10; // Set order parameters
            } else if (positionData[i].Type == 1) { // If it is a short order
                type = -10; // Set order parameters
            }
            // Close all positions
            this.trade(positionData[i].ContractType, type, positionData[i].Amount);
        }
    }
}

Fonction de dessin: dessin Appeler la méthode ObjChart Add (), dessiner les données de marché et les données d'indicateur nécessaires dans le graphique: piste supérieure, piste moyenne, piste inférieure, différence de prix d'arbitrage positif/négatif.

// Drawing
Data.prototype.drawingChart = function (boll) {
    var nowTime = new Date().getTime();
    ObjChart.add([0, [nowTime, boll.up]]);
    ObjChart.add([1, [nowTime, boll.middle]]);
    ObjChart.add([2, [nowTime, boll.down]]);
    ObjChart.add([3, [nowTime, this.basb]]);
    ObjChart.add([4, [nowTime, this.sabb]]);
    ObjChart.update(chart);
}

Étape 4: Dans la fonction d'entrée main ((), exécutez le code de pré-traitement de pré-transaction, qui ne s'exécutera qu'une seule fois après le démarrage du programme, y compris:

  • SetErrorFilter (()) pour filtrer les informations non importantes dans la console
  • exchange.IO ( https://www.squadhelp.com/name/exchange.io?lp=d) ()) pour définir la monnaie numérique à échanger
  • ObjChart reset ( ) pour effacer le graphique précédent dessiné avant le démarrage du programme
  • LogProfitReset (()) pour effacer les informations de la barre d'état avant de démarrer le programme
//entry function
function main() {
    // Filter the unimportant information in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the digital currency to be traded
    ObjChart.reset(); // Clear the previous chart drawn before starting the program
    LogProfitReset(); // Clear the status bar information before starting the program
}

Après la définition du pré-traitement de la transaction ci-dessus, l'étape suivante consiste à entrer dans le mode de sondage et à exécuter la fonction onTick (()) à plusieurs reprises.

//entry function
function main() {
    // Filter the unimportant information in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the digital currency to be traded
    ObjChart.reset(); //Clear the previous chart drawn before starting the program
    LogProfitReset(); //Clear the status bar information before starting the program
    while (true) { // Enter the polling mode
        onTick(); // Execute onTick function
        Sleep(500); // Sleep for 0.5 seconds
    }
}

Obtenir et calculer les données Étape 1: Obtenir les données d'objet de base, le solde du compte et les données de l'indicateur de boll à utiliser dans la logique de négociation.

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
}

Faites une commande et suivez-la. Étape 1: Exécuter l'opération d'achat et de vente selon la logique stratégique ci-dessus. Tout d'abord, juger si les conditions de prix et d'indicateur sont valables, puis juger si les conditions de position sont valables, et enfin exécuter la fonction d'ordre trade ()

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
    // Explanation of the price difference
    // basb = (Sell one price of contract A - Buy one price of contract B)
    // sabb = (Buy one price of contract A - Sell one price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // If sabb is higher than the middle track
        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
            data.trade(tradeTypeA, "closebuy"); // Contract A closes long position
        }
        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
            data.trade(tradeTypeB, "closesell"); // Contract B closes short position
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // If basb is lower than the middle track
        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
            data.trade(tradeTypeA, "closesell"); // Contract A closes short position
        }
        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
            data.trade(tradeTypeB, "closebuy"); // Contract B closes long position
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
        if (data.basb < boll.down) { // If basb price difference is lower than the down track
            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
                data.trade(tradeTypeA, "buy"); // Contract A opens long position
            }
            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
                data.trade(tradeTypeB, "sell"); // Contract B opens short position
            }
        } else if (data.sabb > boll.up) { // If sabb price difference is higher than the upper track
            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
                data.trade(tradeTypeA, "sell"); // Contract A opens short position
            }
            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
                data.trade(tradeTypeB, "buy"); // Contract B opens long position
            }
        }
    }
}

Étape 2: Après la passation de l'ordre, il est nécessaire de traiter les situations anormales telles que l'ordre non réglé et la tenue d'un contrat unique.

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
    // Explanation of the price difference
    //basb = (Sell one price of contract A - Buy one price of contract B)
    // sabb = (Buy one price of contract A - Sell one price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // If sabb is higher than the middle track
        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
            data.trade(tradeTypeA, "closebuy"); // Contract A closes long position
        }
        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
            data.trade(tradeTypeB, "closesell"); // Contract B closes short position
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // If basb is lower than the middle track
        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
            data.trade(tradeTypeA, "closesell"); // Contract A closes short position
        }
        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
            data.trade(tradeTypeB, "closebuy"); // Contract B closes long position
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
        if (data.basb < boll.down) { // If basb price difference is lower than the down track
            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
                data.trade(tradeTypeA, "buy"); // Contract A opens long position
            }
            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
                data.trade(tradeTypeB, "sell"); // Contract B opens short position
            }
        } else if (data.sabb > boll.up) { // If sabb price difference is higher than the upper track
            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
                data.trade(tradeTypeA, "sell"); // Contract A opens short position
            }
            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
                data.trade(tradeTypeB, "buy"); // Contract B opens long position
            }
        }
    }
    data.cancelOrders(); // cancel orders
    data.drawingChart(boll); // drawing
    data.isEven(); // Handle holding individual contracts
}

VI. Stratégie complète

Comme ci-dessus, nous avons créé une stratégie d'arbitrage simple de la monnaie numérique à travers plus de 200 lignes de code.

// Global variable
// Declare a chart object for the configuration chart
var chart = {
    __isStock: true,
    tooltip: {
        xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
    },
    title: {
        text: 'transaction profit and loss curve (detailed)'
    },
    rangeSelector: {
        buttons: [{
            type: 'hour',
            count: 1,
            text: '1h'
        }, {
            type: 'hour',
            count: 2,
            text: '3h'
        }, {
            type: 'hour',
            count: 8,
            text: '8h'
        }, {
            type: 'all',
            text: 'All'
        }],
        selected: 0,
        inputEnabled: false
    },
    xAxis: {
        type: 'datetime'
    },
    yAxis: {
        title: {
            text: 'price difference'
        },
        opposite: false,
    },
    series: [{
        name: "upper track",
        id: "line1,up",
        data: []
    }, {
        name: "middle track",
        id: "line2,middle",
        data: []
    }, {
        name: "down track",
        id: "line3,down",
        data: []
    }, {
        name: "basb",
        id: "line4,basb",
        data: []
    }, {
        name: "sabb",
        id: "line5,sabb",
        data: []
    }]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Storage price difference series
var oldTime = 0; // Record historical data timestamp

// parameters
var tradeTypeA = "this_week"; // Arbitrage A contract
var tradeTypeB = "quarter"; // Arbitrage B contract
var dataLength = 10; //Indicator period length
var timeCycle = 1; // K-line period
var name = "ETC"; // Currencies
var unit = 1; // Order quantity

// basic data
function Data(tradeTypeA, tradeTypeB) { // Pass in arbitrage A contract and arbitrage B contract
    this.accountData = _C(exchange.GetAccount); // Get account information
    this.positionData = _C(exchange.GetPosition); // Get position information
    var recordsData = _C(exchange.GetRecords); //Get K-line data
    exchange.SetContractType(tradeTypeA); // Subscribe to arbitrage A contract
    var depthDataA = _C(exchange.GetDepth); // Arbitrage A contract depth data
    exchange.SetContractType(tradeTypeB); // Subscribe to arbitrage B contract
    var depthDataB = _C(exchange.GetDepth); // Arbitrage B contract depth data
    this.time = recordsData[recordsData.length - 1].Time; // Time to get the latest data
    this.askA = depthDataA.Asks[0].Price; // Sell one price of arbitrage A contract
    this.bidA = depthDataA.Bids[0].Price; // Buy one price of arbitrage A contract
    this.askB = depthDataB.Asks[0].Price; // Sell one price of arbitrage B contract
    this.bidB = depthDataB.Bids[0].Price; // Buy one price of arbitrage B contract
    // Positive arbitrage price difference (Sell one price of contract A - Buy one price of contract B)
    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
    // Negative arbitrage price difference (Buy one price of contract A - Sell one price of contract B)
    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}

// Get position
Data.prototype.mp = function (tradeType, type) {
    var positionData = this.positionData; // Get position information
    for (var i = 0; i < positionData.length; i++) {
        if (positionData[i].ContractType == tradeType) {
            if (positionData[i].Type == type) {
                if (positionData[i].Amount > 0) {
                    return positionData[i].Amount;
                }
            }
        }
    }
    return false;
}

// Synthesis of new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
    var self = {}; // Temporary objects
    // Median value of between positive arbitrage price difference and negative arbitrage price difference
    self.Close = (this.basb + this.sabb) / 2;
    if (this.timeA == this.timeB) {
        self.Time = this.time;
    } // Compare two depth data timestamps
    if (this.time - oldTime > timeCycle * 60000) {
        bars.push(self);
        oldTime = this.time;
    } // Pass in the price difference data object into the K-line array according to the specified time period
    if (bars.length > num * 2) {
        bars.shift(); // Control the length of the K-line array
    } else {
        return;
    }
    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the talib library
    return {
        up: boll[0][boll[0].length - 1], // boll indicator upper track
        middle: boll[1][boll[1].length - 1], // boll indicator middle track
        down: boll[2][boll[2].length - 1] // boll indicator down track
    } // Return a processed boll indicator data
}

// Place an order
Data.prototype.trade = function (tradeType, type) {
    exchange.SetContractType(tradeType); // Resubscribe to a contract before placing an order
    var askPrice, bidPrice;
    if (tradeType == tradeTypeA) { // If the order is placed in contract A
        askPrice = this.askA; // Set askPrice
        bidPrice = this.bidA; // Set bidPrice
    } else if (tradeType == tradeTypeB) { // If the order is placed in contract B
        askPrice = this.askB; // Set askPrice
        bidPrice = this.bidB; // Set bidPrice
    }
    switch (type) { // Match order placement mode
        case "buy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        case "sell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closebuy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closesell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        default:
            return false;
    }
}

// Cancel orders
Data.prototype.cancelOrders = function () {
    Sleep(500); // Delay before cancellation, because some exchanges, you know what I mean
    var orders = _C(exchange.GetOrders); //Get an array of unfilled orders
    if (orders.length > 0) { // If there are unfilled orders
        for (var i = 0; i < orders.length; i++) { //Iterate through the array of unfilled orders
            exchange.CancelOrder(orders[i].Id); //Cancel unfilled orders one by one
            Sleep(500); //Sleep for 0.5 seconds
        }
        return false; // Return false if an unfilled order is cancelled
    }
    return true; //Return true if there are no unfilled orders
}

// Handle holding individual contracts
Data.prototype.isEven = function () {
    var positionData = this.positionData; // Get position information
    var type = null; // Switch position direction
    // If the remaining 2 of the position array length is not equal to 0 or the position array length is not equal to 2
    if (positionData.length % 2 != 0 || positionData.length != 2) {
        for (var i = 0; i < positionData.length; i++) { // Iterate through the position array
            if (positionData[i].Type == 0) { // If it is a long order
                type = 10; // Set order parameters
            } else if (positionData[i].Type == 1) { // If it is a short order
                type = -10; // Set order parameters
            }
            // Close all positions
            this.trade(positionData[i].ContractType, type, positionData[i].Amount);
        }
    }
}

// Drawing
Data.prototype.drawingChart = function (boll) {
    var nowTime = new Date().getTime();
    ObjChart.add([0, [nowTime, boll.up]]);
    ObjChart.add([1, [nowTime, boll.middle]]);
    ObjChart.add([2, [nowTime, boll.down]]);
    ObjChart.add([3, [nowTime, this.basb]]);
    ObjChart.add([4, [nowTime, this.sabb]]);
    ObjChart.update(chart);
}

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
    // Explanation of price difference
    // basb = (Sell one price of contract A - Buy one price of contract B)
    // sabb = (Buy one price of contract A - Sell one price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // If sabb is higher than the middle track
        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
            data.trade(tradeTypeA, "closebuy"); // Contract A closes long position
        }
        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
            data.trade(tradeTypeB, "closesell"); // Contract B closes short position
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // If basb is lower than the middle track
        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
            data.trade(tradeTypeA, "closesell"); // Contract A closes short position
        }
        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
            data.trade(tradeTypeB, "closebuy"); // Contract B closes long position
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is a balance in the account
        if (data.basb < boll.down) { // If basb price difference is lower than the down track
            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
                data.trade(tradeTypeA, "buy"); // Contract A opens long position
            }
            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
                data.trade(tradeTypeB, "sell"); // Contract B opens short position
            }
        } else if (data.sabb > boll.up) { // If sabb price difference is higher than the upper track
            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
                data.trade(tradeTypeA, "sell"); // Contract A opens short position
            }
            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
                data.trade(tradeTypeB, "buy"); // Contract B opens long position
            }
        }
    }
    data.cancelOrders(); // Cancel orders
    data.drawingChart(boll); // Drawing
    data.isEven(); // Handle holding individual contracts
}

//Entry function
function main() {
    // Filter unimportant information in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the digital currency to be traded
    ObjChart.reset(); //Clear the previous chart drawn before starting the program
    LogProfitReset(); //Clear the status bar information before starting the program
    while (true) { // Enter polling mode
        onTick(); // Execute the onTick function
        Sleep(500); // Sleep for 0.5 seconds
    }
}

Adresse stratégique:https://www.fmz.com/strategy/104964

VII. Résumé

La stratégie de cet article n'est qu'un exemple. Le vrai bot n'est pas simple, mais vous pouvez suivre l'exemple et utiliser votre propre imagination. Il convient de rappeler que, selon mon expérience limitée, sur le marché actuel de la monnaie numérique, presque toutes les stratégies d'arbitrage à terme ne valent pas la peine d'être exécutées, qu'il s'agisse d'arbitrage triangulaire sans risque ou d'arbitrage cross-marché. La raison en est que peu importe le marché des contrats à terme de change de monnaie numérique, sa marge n'est pas une monnaie légale. À l'heure actuelle, presque toutes les monnaies numériques ont chuté d'environ 70% depuis le début de l'année. C'est-à-dire que la stratégie est toujours de gagner des devises, mais le prix de la monnaie diminue. Dans l'ensemble, le marché de la monnaie numérique semble s'être détaché de la blockchain. Comme les tulipes à l'époque, le prix provient toujours des attentes et de la confiance des gens, et la confiance vient du prix...


Relationnée

Plus de