Nr. 1
In dem Buch
Mit anderen Worten, der Preis selbst enthält bereits die falschen Erwartungen der Marktteilnehmer, so dass der Marktpreis im Wesentlichen immer falsch ist.
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.
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:
Der strategische Rahmen kann leicht nach dem strategischen Denken und Transaktionsprozess aufgebaut werden.
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.
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
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.
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.
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.
Funktion Auftrag stornieren: cancelOrders ()) Erhalten Sie eine Anordnung aller ausstehenden Bestellungen und stornieren Sie sie einzeln.
Einheitlicher Vertrag zur Abwicklung: isEven ()) Im Falle der Single-Leg-Situation im Arbitrage-Handel wird sie direkt durch einfaches Schließen aller Positionen abgewickelt.
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.
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 ())
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.
Zweitens, erhalten und berechnen Daten Schritt 1: Erhalten Sie das zugrunde liegende Datenobjekt, den Kontostand und die Boll-Indikatordaten für die Handelslogik.
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.
Schritt 2: Nach Auftragserteilung müssen ungewöhnliche Situationen wie ausstehende Aufträge und einzelne Verträge behandelt und Diagramme erstellt werden.
Nr. 8 Wir haben eine einfache digitale Währung Intertemporal Arbitrage Strategie durch mehr als 200 Zeilen erstellt.
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
}
}
Die Erfinder quantifizieren - Kleine TräumeDas ist gut!