Blockchain Quantitative Investment Series Kurs (3) Kalender Spread Arbitrage

Schriftsteller:Rubin, Erstellt: 2018-08-27 16:49:50, Aktualisiert:

Nr. 1 In dem Buch Financial Alchemy von Soros aus dem Jahr 1987 wurde ein wichtiger Vorschlag gemacht: Ich glaube, dass die Marktpreise immer falsch sind, weil sie eine voreingenommene Sicht auf die Zukunft darstellen. Die Marktwerthypothese ist nur eine theoretische Annahme. Tatsächlich sind Marktteilnehmer nicht immer rational und können zu jedem Zeitpunkt nicht alle Informationen vollständig erwerben und objektiv interpretieren. Auch wenn es sich um dieselben Informationen handelt, ist das Feedback von jedem anders.

Mit anderen Worten, der Preis selbst enthält bereits die falschen Erwartungen der Marktteilnehmer, so dass der Marktpreis im Wesentlichen immer falsch ist.

img

Nr. 2 Auf der Grundlage der vorstehenden Grundsätze wissen wir auch, dass in einem nicht effektiven Futures-Markt die Marktwirkung von Lieferverträgen in verschiedenen Perioden nicht immer synchronisiert ist und die Preisgestaltung nicht der Grund für eine vollständige Effektivität ist.

Auf der Grundlage des Preises des Liefervertrags zu verschiedenen Zeiten des gleichen Transaktionsziels ist es dann möglich, Futures-Kontrakte mit unterschiedlichen Zeiträumen gleichzeitig zu handeln und intertemporales Arbitrage durchzuführen, wenn ein großer Spread zwischen den beiden Preisen besteht. Wie Rohstoff-Futures haben auch digitale Währungen ein intertemporales Arbitrage-Kontraktportfolio, das mit ihnen verbunden ist.

Nehmen wir zum Beispiel an, dass der Spread zwischen ETC Woche und ETC Quartal für eine lange Zeit bei etwa 5 gehalten wird. Wenn der Spread 7 erreicht, erwarten wir, dass der Spread zu irgendeiner Zeit in der Zukunft auf 5 zurückkehrt. Dann können Sie die ETC Woche verkaufen und das ETC Quartal kaufen, um den Spread zu verkürzen. umgekehrt.

Nr. 3 Obwohl diese Differenz besteht, gibt es oft viele Unsicherheiten bei manueller Arbitrage aufgrund der zeitaufwändigen, schlechten Genauigkeit manueller Operationen und der preisverändernden Effekte.

Durch das quantitative Modell, um Arbitragenchancen zu erfassen und Arbitragenhandelsstrategien zu entwickeln, sowie programmatische Algorithmen, die automatisch Handelsaufträge an die Börse freigeben, um schnell und genau Chancen zu erfassen und effizient Einkommen zu erzielen, was der Reiz der quantitativen Arbitrage ist.

img

In diesem Artikel erfahren Sie, wie Sie die FMZ-Quantitative Trading-Plattform und den ETC-Futures-Kontrakt in der OkEX-Börse beim Handel mit digitalen Währungen verwenden, mit einer einfachen Arbitragestrategie, um zu zeigen, wie Sie die sofortigen Arbitrage-Möglichkeiten nutzen und jeden sichtbaren Gewinn nutzen und gleichzeitig die Risiken absichern können, denen Sie begegnen.

Nr. 4 Erstellen Sie eine digitale Währung Intertemporal Arbitrage Strategie Schwierigkeitsgrad: Durchschnittliche Strategisches Umfeld: Transaktionsziel: Ethereum classic (ETC) Spread-Daten: wöchentlich - vierteljährlich Handelszeit: 5 Minuten Positionsabgleich: 1:1 Transaktionsart: gleiche Variante zwischenzeitlich Strategie Logik: Konditionen für den Kauf von Long-Spread-Positionen: Wenn das Girokonto keine Positionen aufweist und der Spread kleiner ist als der Abwärtsverlauf des Boll-Indikators, wird eine Spread-Order platziert, d. h. wöchentlich Long-ETC-Positionen kaufen, vierteljährlich ETC-Short-Positionen verkaufen.

Konditionen für Short-Selling-Spread-Positionen: Wenn das Girokonto keine Positionen aufweist und der Spread höher ist als der Up-Rail des Boll-Indikators, wird eine Spread-Order platziert, d. h. wöchentlich kurz ETC verkauft, vierteljährlich lang ETC gekauft.

Schließung der Long-Spread-Positionsbedingung: Wenn das Girokonto eine lange wöchentliche ETC-Position und eine kurze vierteljährliche ETC-Position hält und der Spread höher als die mittlere Schiene des Boll-Indikators ist, wird eine Close-Spread-Order platziert, d. h. wöchentlich ETC verkauft, vierteljährlich ETC gekauft.

Schließung der Bedingung für die Leerverkaufs-Spread-Position: Wenn das Girokonto eine wöchentliche Leer-ETC-Position und eine vierteljährliche Leer-ETC-Position hält und der Spread niedriger ist als die mittlere Schiene des Boll-Indikators, wird eine close-Spread-Order platziert, d. h. wöchentlich kaufen, um die Leer-ETC-Position abzudecken, vierteljährlich verkaufen.

Nr. 5 Die obige ist eine einfache Beschreibung der digitalen Währung intertemporalen Arbitrage Strategie Logik, dann, wie um Ihre eigenen Ideen in das Programm umzusetzen? Strategischer Rahmen:

img

Der strategische Rahmen kann leicht nach dem strategischen Denken und Transaktionsprozess aufgebaut werden.

  1. Vorverarbeitung vor der Transaktion.
  2. Holen und berechnen Sie Daten.
  3. Bestellen und verfolgen.

Nr. 6 Als nächstes müssen wir die notwendigen Details im Strategie-Rahmen auf der Grundlage des tatsächlichen Transaktionsprozesses und der Transaktionsdetails ausfüllen.

Erstens: Vorverarbeitung vor der Transaktion Schritt 1: In der globalen Umgebung werden die notwendigen globalen Variablen angegeben. Deklarieren eines Chartobjekts, das das Chart konfiguriert - Das ist nicht wahr. Die Funktion Chart wird aufgerufen, um das Chart zu initialisieren. Var ObjChart = Diagramm (Diagramm) Deklarieren eines leeren Arrays zur Speicherung der Verbreitungssequenz Var-Stäbe = [ ] Anzeigen einer Zeitstempelvariable, die historische Daten erfasst War oldTime = 0 Schritt 2: Konfigurieren Sie externe Parameter für die Strategie.

img

Schritt 3: Definition der Datenverarbeitung Grunddatenfunktion: Daten ()) Erstellen Sie einen Konstruktor Daten und definieren Sie seine internen Eigenschaften, einschließlich: Konto-Daten, Positionsdaten, Zeitstempel für K-Liniendaten, letzten Kauf-/Verkaufspreis eines Arbitragevertrags A/B, positiver/umgekehrter Arbitrage-Spread

img

Erhalten Sie die Positionsfunktion: mp ()) Überprüfen Sie das gesamte Array von Positionen, geben Sie den angegebenen Vertrag und die Anzahl der Positionen in der angegebenen Richtung zurück.

img

K-Linie und Indikatorfunktion: boll ()) Synthetisieren Sie eine neue K-Linienfolge basierend auf den Daten der positiven/umgekehrten Arbitrage-Spread und geben Sie die Up/Middle/Down-Rail-Daten zurück, die durch den Boll-Indikator berechnet wurden.

img

Auftragsfunktion: Handel (') Der Bestellungsvertrag wird mit dem Namen und dem Handelstyp versehen, dann wird der Auftrag zum letzten Kauf-/Verkaufspreis platziert und das Ergebnis nach der Auftragserteilung zurückgegeben.

img

Funktion Auftrag stornieren: cancelOrders ()) Erhalten Sie eine Anordnung aller ausstehenden Bestellungen und stornieren Sie sie einzeln.

img

Einheitlicher Vertrag zur Abwicklung: isEven ()) Im Falle der Single-Leg-Situation im Arbitrage-Handel wird sie direkt durch einfaches Schließen aller Positionen abgewickelt.

img

Zeichnungsdiagrammfunktion: Zeichnungsdiagramm () Aufrufen Sie die ObjChart.add ( ) -Methode, um die notwendigen Marktdaten und Indikatordaten im Diagramm zu erfassen: Aufwärts-, Mittelfeld-, Abwärts- und Positiv-/Umkehr-Arbitrage-Spread.

img

Schritt 4: In der Eingabefunktion main () wird vor der Transaktion der vorverarbeitende Code ausgeführt, der nur einmal nach dem Start des Programms ausgeführt wird, einschließlich:

Filtern Sie die nicht sehr wichtigen Informationen in der Konsole aus SetErrorFilter ()) Festlegen des zu handelnden digitalen Währungstypsexchange.IO() Entleeren Sie die gezeichneten Diagramme, bevor das Programm startet ObjChart.reset ()) Leeren Sie die Statusleiste vor Beginn des Programms aus LogProfitReset ())

img

Nr. 7 Nach der Definition der vorstehenden Vorverarbeitung vor der Transaktion ist es notwendig, zum nächsten Schritt überzugehen, in den Abstimmungsmodus einzusteigen und die Funktion onTick () zu wiederholen. Und stellen Sie die Schlafzeit bei der Umfrage ein, weil einige der digitalen Währungsaustausch-API's eine eingebaute Zugriffsbegrenzung für eine bestimmte Zeit haben.

img

Zweitens, erhalten und berechnen Daten Schritt 1: Erhalten Sie das zugrunde liegende Datenobjekt, den Kontostand und die Boll-Indikatordaten für die Handelslogik.

img

Drittens, eine Bestellung stellen und Folgemaßnahmen ergreifen Schritt 1: Führen Sie die Kauf- und Verkaufsoperation nach der obigen Strategie-Logik durch. Zuerst prüfen Sie, ob die Preis- und Indikatorbedingungen zutreffen, dann prüfen Sie, ob die Positionsbedingungen zutreffen, und schließlich führen Sie die Trade () -Orderfunktion aus.

img

Schritt 2: Nach Auftragserteilung müssen ungewöhnliche Situationen wie ausstehende Aufträge und einzelne Verträge behandelt und Diagramme erstellt werden.

img

Nr. 8 Wir haben eine einfache digitale Währung Intertemporal Arbitrage Strategie durch mehr als 200 Zeilen erstellt.

img

Nr. 9 Der reale Markt ist nicht so einfach, aber Sie können dieses Beispiel verwenden, um mit Ihrer Fantasie zu spielen.

Was daran erinnert werden muss, ist, dass, basierend auf meiner begrenzten Erfahrung, die reine Perioden-Arbitrage-Strategie im Grunde genommen nicht in der aktuellen Situation des Marktes für digitale Währungen laufen sollte, egal ob es sich um risikofreie Dreiecks-Arbitrage oder um Marktübergreifende Arbitrage handelt.

Der Grund dafür ist, dass egal in welchem digitalen Währungsaustausch der Futures-Markt ist, die Marge nicht fiat ist. Fast alle digitalen Währungen sind seit Jahresbeginn um etwa 70% gefallen. Mit anderen Worten, die Strategie ist immer, Währung zu machen, aber der Preis der Währung sinkt.

Der Markt für digitale Währungen hat die Blockchain bereits verlassen, genau wie die Tulpen damals, kommt der Preis immer von den Erwartungen und dem Vertrauen der Menschen, und das Vertrauen kommt vom Preis...

Hier ist der vollständige Code:

// global variable
// Declare a chart object that configures the chart
var chart = {
    __isStock: true,
    tooltip: {
        xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
    },
    title: {
        text: 'Profit and loss chart(detail)'
    },
    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: 'spread'
        },
        opposite: false,
    },
    series: [{
        name: "up",
        id: "line1,up",
        data: []
    }, {
        name: "middle",
        id: "line2,middle",
        data: []
    }, {
        name: "down",
        id: "line3,down",
        data: []
    }, {
        name: "basb",
        id: "line4,basb",
        data: []
    }, {
        name: "sabb",
        id: "line5,sabb",
        data: []
    }]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Store spread sequence
var oldTime = 0; // Record historical data timestamp

// Parameter
var tradeTypeA = "this_week"; // Arbitrage contract A
var tradeTypeB = "quarter"; // Arbitrage contract B
var dataLength = 10; //Length of indicator cycle
var timeCycle = 1; // The cycle of K-line
var name = "ETC"; // Currency type
var unit = 1; // Quantity of orders

// Basic data
function Data(tradeTypeA, tradeTypeB) { // input arbitrage contract A&B
    this.accountData = _C(exchange.GetAccount); // get account data
    this.positionData = _C(exchange.GetPosition); // get position data
    var recordsData = _C(exchange.GetRecords); //get k-line data
    exchange.SetContractType(tradeTypeA); // subscribe arbitrage contract A
    var depthDataA = _C(exchange.GetDepth); // deep data of arbitrage contract A
    exchange.SetContractType(tradeTypeB); // subscribe arbitrage contract B
    var depthDataB = _C(exchange.GetDepth); // deep data of arbitrage contract B
    this.time = recordsData[recordsData.length - 1].Time; // get the latest time data
    this.askA = depthDataA.Asks[0].Price; // the latest selling price of arbitrage contract A
    this.bidA = depthDataA.Bids[0].Price; // the latest buying price of arbitrage contract A
    this.askB = depthDataB.Asks[0].Price; // the latest selling price of arbitrage contract B
    this.bidB = depthDataB.Bids[0].Price; // the latest buying price of arbitrage contract B
    // Positive arbitrage spread(the latest selling price of contract A -the latest buying price of contract B )
    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
    // Reverse arbitrage spread(the latest buying price of contract A -the latest selling price of contract B )
    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}

// get position information
Data.prototype.mp = function (tradeType, type) {
    var positionData = this.positionData; // get position data
    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;
}

// Synthetize new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
    var self = {}; // Temporary object
    // the median of Positive arbitrage spread and reverse arbitrage spread
    self.Close = (this.basb + this.sabb) / 2;
    if (this.timeA == this.timeB) {
        self.Time = this.time;
    } // Comparing two depth data timestamps
    if (this.time - oldTime > timeCycle * 60000) {
        bars.push(self);
        oldTime = this.time;
    } // According to the specified time period, insert the spread data object in the K-line array.
    if (bars.length > num * 2) {
        bars.shift(); // Control K-line array length
    } 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], // up rail of boll indicator
        middle: boll[1][boll[1].length - 1], // middle rail of boll indicator
        down: boll[2][boll[2].length - 1] // down rail of boll indicator
    } // Return a processed boll indicator data.
}

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

// cancel order
Data.prototype.cancelOrders = function () {
    Sleep(500); // delay before canceling, because some exchanges you know...
    var orders = _C(exchange.GetOrders); // Get the array of pending orders
    if (orders.length > 0) { // if there is pending order
        for (var i = 0; i < orders.length; i++) { //check through the array of pending orders
            exchange.CancelOrder(orders[i].Id); //cancel pending orders one by one
            Sleep(500); //Delay 0.5 seconds
        }
        return false; // return false if pending orders have been cancelled
    }
    return true; //return true if there is no pending order
}

// handle holding single contract
Data.prototype.isEven = function () {
    var positionData = this.positionData; // get position data
    var type = null; // converse position direction 
    // If the length of the position array divided by some number and the remainder is 2, the result is not equal to 0 or the length of the position array is not equal to 2
    if (positionData.length % 2 != 0 || positionData.length != 2) {
        for (var i = 0; i < positionData.length; i++) { // check through the array of positions
            if (positionData[i].Type == 0) { // if it's long position
                type = 10; // Set order parameters
            } else if (positionData[i].Type == 1) { // if it's short position
                type = -10; // Set order parameters
            }
            // close all positions
            this.trade(positionData[i].ContractType, type, positionData[i].Amount);
        }
    }
}

// drawing chart
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 condition
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a base 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
    // Spread description
    // basb = (the latest selling price of contract A - the latest buying price of contract B)
    // sabb = (the latest buying price of contract A - the latest selling price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // if sabb is higher than the middle rail
        if (data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
            data.trade(tradeTypeA, "closebuy"); // close long position of contract A
        }
        if (data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
            data.trade(tradeTypeB, "closesell"); // close short position of contract B
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // if basb is lower than the middle rail
        if (data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
            data.trade(tradeTypeA, "closesell"); // close short position of contract A
        }
        if (data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
            data.trade(tradeTypeB, "closebuy"); // close long position of contract B
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
        if (data.basb < boll.down) { // if basb spread is lower than the down rail
            if (!data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
                data.trade(tradeTypeA, "buy"); // open long position of contract A
            }
            if (!data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
                data.trade(tradeTypeB, "sell"); // open short position of contract B
            }
        } else if (data.sabb > boll.up) { // if sabb spread is higher than the up rail
            if (!data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
                data.trade(tradeTypeA, "sell"); // open short position of contract A
            }
            if (!data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
                data.trade(tradeTypeB, "buy"); // open long position of contract B
            }
        }
    }
    data.cancelOrders(); // cancel orders
    data.drawingChart(boll); // drawing chart
    data.isEven(); // process holding single contract
}

//enter function
function main() {
    // filter the information that is not very important in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the cryptocurrency type to be traded
    ObjChart.reset(); //Empty the drawn charts before the program starts
    LogProfitReset(); //Empty the status bar information before the program starts
    while (true) { // Enter polling mode
        onTick(); // Execute onTick function
        Sleep(500); // sleep for o.5 seconds
    }
}


Mehr

Kleine TräumeDas ist gut!