No. 1
Dalam buku
Dengan kata lain, harga itu sendiri sudah mengandung harapan yang salah dari peserta pasar, sehingga pada dasarnya harga pasar selalu salah.
No. 2 Berdasarkan prinsip-prinsip di atas, kita juga tahu bahwa di pasar berjangka yang tidak efektif, dampak pasar dari kontrak pengiriman dalam periode yang berbeda tidak selalu disinkronkan, dan penetapan harga tidak menjadi alasan untuk sepenuhnya efektif.
Kemudian, berdasarkan harga kontrak pengiriman pada waktu yang berbeda dari target transaksi yang sama, jika ada perbedaan besar antara kedua harga, dimungkinkan untuk secara bersamaan memperdagangkan kontrak berjangka dari periode yang berbeda dan melakukan arbitrase intertemporal. Seperti komoditas berjangka, mata uang digital juga memiliki portofolio kontrak arbitrase intertemporal yang terkait dengan mereka.
Sebagai contoh, misalkan spread antara minggu ETC dan kuartal ETC dipertahankan sekitar 5 untuk waktu yang lama. Jika spread mencapai 7, kita mengharapkan spread untuk kembali ke 5 di beberapa waktu di masa depan. Kemudian Anda dapat menjual minggu ETC dan membeli kuartal ETC untuk short spread. sebaliknya.
No.3 Meskipun spread ini ada, sering ada banyak ketidakpastian dalam arbitrage manual karena memakan waktu, tidak akurat dari operasi manual dan efek perubahan harga.
Melalui model kuantitatif untuk menangkap peluang arbitrage dan mengembangkan strategi perdagangan arbitrage, serta algoritma programatik secara otomatis melepaskan pesanan perdagangan ke bursa, untuk dengan cepat dan akurat menangkap peluang dan secara efisien menghasilkan pendapatan, yang merupakan pesona arbitrage kuantitatif.
Artikel ini akan mengajarkan Anda cara menggunakan platform perdagangan kuantitatif FMZ dan kontrak berjangka ETC di bursa OkEX dalam perdagangan mata uang digital, dengan strategi arbitrage sederhana untuk menunjukkan cara menangkap peluang arbitrage instan, dan merebut setiap keuntungan yang terlihat sambil sekaligus lindung nilai risiko yang mungkin terjadi.
NO.4 Membuat strategi arbitrage intertemporal mata uang digital Kesulitan: tingkat biasa Lingkungan strategis: Target transaksi: Ethereum klasik (ETC) Data spread: ETC mingguan - ETC triwulanan Periode perdagangan: 5 menit Persamaan posisi: 1:1 Jenis transaksi: varietas yang sama intertemporal Logika strategi: Kondisi posisi spread panjang: Jika akun arus tidak memiliki posisi, dan spreadnya lebih kecil dari jejak penurunan indikator boll, tempatkan spread order, yaitu: membeli ETC panjang mingguan, menjual ETC pendek triwulanan.
Kondisi posisi spread short selling: Jika akun arus tidak memiliki posisi dan spreadnya lebih tinggi dari up rail dari indikator boll, tempatkan spread order, yaitu: menjual ETC short mingguan, membeli ETC long triwulanan.
Penutupan kondisi posisi jual spread panjang: Jika akun saat ini memiliki posisi mingguan ETC panjang dan posisi ETC kuartal pendek, dan spreadnya lebih tinggi dari rel tengah indikator boll, tempatkan pesanan jual spread dekat, yaitu: menjual ETC mingguan, membeli untuk menutupi ETC kuartal.
Penutupan kondisi Posisi Spread Penjualan Singkat: Jika akun arus memegang posisi ETC mingguan pendek dan memegang posisi ETC kuartal panjang, dan spreadnya lebih rendah dari rel tengah indikator boll, tempatkan pesanan spread dekat, yaitu: beli untuk menutupi ETC mingguan, menjual ETC kuartal.
NO.5 Di atas adalah deskripsi sederhana dari logika strategi arbitrage intertemporal mata uang digital, lalu bagaimana menerapkan ide Anda sendiri dalam program? Kerangka strategi:
Kerangka kerja strategi dapat dengan mudah dibangun sesuai dengan pemikiran strategis dan proses transaksi.
NO.6 Selanjutnya, kita perlu mengisi rincian yang diperlukan dalam kerangka strategi berdasarkan proses transaksi yang sebenarnya dan rincian transaksi.
Pertama, pra-pengolahan sebelum transaksi Langkah 1: Dalam lingkungan global, deklarasikan variabel global yang diperlukan. Deklarasikan objek grafik yang mengkonfigurasi grafik Diagram Var = { } Panggilan fungsi Chart untuk menginisialisasi grafik Var ObjChart = Grafik (grafik) Mengumumkan array kosong untuk menyimpan urutan penyebaran Var bar = [ ] Mengisyaratkan variabel timestamp yang mencatat data historis Var oldTime = 0 Langkah 2: Mengkonfigurasi parameter eksternal untuk strategi.
Langkah 3: Mendefinisikan fungsi pemrosesan data Fungsi data dasar: Data ()) Buat constructor Data dan tentukan sifat internalnya, termasuk: data akun, data posisi, data K-line timestamp, harga beli/penjualan terbaru dari kontrak arbitrage A/B, spread arbitrage positif/reverse
Dapatkan fungsi posisi: mp ()) Periksa seluruh array posisi, kembalikan kontrak yang ditentukan dan jumlah posisi di arah yang ditentukan.
K line dan fungsi indikator: boll ()) Sintesis urutan K-line baru berdasarkan data spread arbitrage positif / terbalik. Dan kembali data up / middle / down rail dihitung oleh indikator bol.
Fungsi pesanan: perdagangan () Masukkan nama kontrak order dan jenis perdagangan, kemudian menempatkan order di harga beli/jual terbaru dan mengembalikan hasilnya setelah menempatkan order.
Fungsi membatalkan pesanan: cancelOrders ()) Dapatkan array semua pesanan tertunda dan membatalkan mereka satu per satu. dan jika ada pesanan tertunda, kembali palsu, dan jika tidak ada, kembali benar.
Proses memegang kontrak tunggal: isEven ()) Dalam kasus situasi single-leg dalam perdagangan arbitrage, hal ini langsung ditangani dengan hanya menutup semua posisi.
Fungsi menggambar grafik: menggambarGambar ()) Menggunakan metode ObjChart.add () untuk menarik data pasar dan data indikator yang diperlukan dalam grafik: naik, tengah, turun rel, spread arbitrage positif/balik.
Langkah 4: Dalam fungsi entri utama (), eksekusi kode pra-pemrosesan sebelum transaksi, yang hanya dijalankan sekali setelah program dimulai, termasuk:
saring informasi yang tidak terlalu penting di konsol SetErrorFilter ()) Atur jenis mata uang digital yang akan diperdagangkanexchange.IO() Kosongkan grafik yang ditarik sebelum program dimulai ObjChart.reset ()) Kosongkan informasi bilah status sebelum program memulai LogProfitReset ())
NO.7 Setelah menentukan pra-pemrosesan di atas sebelum transaksi, perlu untuk melanjutkan ke langkah berikutnya, masuk ke mode pemungutan suara, dan ulangi fungsi onTick (). Dan atur waktu tidur saat polling, karena beberapa API pertukaran mata uang digital memiliki batas akses bawaan untuk jangka waktu tertentu.
Kedua, mendapatkan dan menghitung data Langkah 1: Dapatkan objek data yang mendasari, saldo akun dan data indikator boll untuk logika perdagangan.
Ketiga, membuat pesanan dan tindak lanjut Langkah 1: Melakukan operasi pembelian dan penjualan sesuai dengan logika strategi di atas. Pertama, periksa apakah kondisi harga dan indikator benar, dan kemudian periksa apakah kondisi posisi benar, dan akhirnya pelaksanaan fungsi pesanan perdagangan ().
Langkah 2: Setelah pemesanan, perlu untuk menangani situasi yang tidak normal seperti pesanan yang menunggu dan memegang kontrak tunggal, dan membuat grafik.
No. 8 Di atas, kami telah membuat strategi arbitrage intertemporal mata uang digital sederhana melalui lebih dari 200 baris.
NO.9 Strategi ini hanya berfungsi sebagai pemicu. pasar nyata tidak begitu sederhana, tapi Anda dapat menggunakan contoh ini untuk bermain dengan imajinasi Anda.
Apa yang perlu diingat adalah bahwa, berdasarkan pengalaman terbatas saya, strategi arbitrage periode murni pada dasarnya tidak layak dijalankan dalam situasi pasar mata uang digital saat ini, apakah itu risiko bebas arbitrage segitiga atau cross-market arbitrage.
Alasan adalah bahwa tidak peduli di pasar futures pertukaran mata uang digital mana, margin tidak fiat. Hampir semua mata uang digital telah turun sekitar 70% sejak awal tahun. Dengan kata lain, strategi selalu menghasilkan mata uang, tetapi harga mata uang menurun.
Jika dilihat secara luas, pasar mata uang digital sudah meninggalkan blockchain. sama seperti bunga tulip saat itu, harga selalu berasal dari harapan dan kepercayaan orang, dan kepercayaan berasal dari harga...
Di sini untuk mendapatkan kode lengkap:
// 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
}
}
Penemu Kuantitas - Mimpi KecilBagus sekali!