Untuk waktu yang lama, masalah keterlambatan data dari antarmuka API posisi pertukaran mata uang digital selalu mengganggu saya. Saya belum menemukan cara yang tepat untuk menangani masalah ini. Biarkan saya mereproduksi adegan masalah. Biasanya, pesanan harga pasar yang disediakan oleh pertukaran kontrak sebenarnya adalah harga lawan, jadi kadang-kadang tidak dapat diandalkan untuk menggunakan apa yang disebut
Karena masalah ini, saya telah melihat sebuah strategi terbuka penuh dengan posisi panjang gila. Untungnya, pasar melonjak pada saat itu, dan keuntungan mengambang melebihi 10BTC. Untungnya, pasar meningkat tajam. Jika turun tajam, kita dapat membayangkan hasilnya.
Solusi 1 Strategi dapat dirancang untuk menempatkan hanya satu pesanan, dan harga pesanan adalah harga lawan perdagangan saat ini ditambah harga geser besar, sehingga mengambil kedalaman tertentu dari pesanan lawan. Keuntungan dari ini adalah bahwa hanya satu pesanan akan ditempatkan, dan tidak akan dinilai berdasarkan informasi posisi. Ini dapat menghindari masalah pesanan berulang, tetapi kadang-kadang menempatkan pesanan dapat memicu mekanisme batas harga bursa ketika perubahan harga relatif besar, dan dimungkinkan untuk meningkatkan harga geser dan masih gagal melakukan kesepakatan, sehingga kehilangan kesempatan.
Solusi 2 Dengan fungsi pesanan harga pasar dari bursa, harga ditransfer ke - 1 pada FMZ sebagai pesanan harga pasar.
Solusi 3 Kami masih menggunakan logika trading sebelumnya dan menempatkan order dengan harga limit order, tetapi kami menambahkan beberapa deteksi dalam logika trading untuk mencoba memecahkan masalah yang disebabkan oleh keterlambatan data posisi. Periksa apakah order telah menghilang langsung dari daftar order yang sedang menunggu tanpa pembatalan (ada dua kemungkinan untuk menghilang dari daftar order yang sedang menunggu: 1. Pembatalan dan 2. Diisi). Jika situasi seperti itu terdeteksi, dan jumlah order yang ditempatkan lagi sama dengan pesanan terakhir, penting untuk dicatat bahwa apakah data posisi tertunda. Biarkan program memasukkan logika menunggu untuk memperoleh kembali informasi posisi, atau bahkan terus mengoptimalkan dan meningkatkan jumlah waktu menunggu untuk memicu waktu menunggu, jika melebihi jumlah waktu tertentu, itu menunjukkan bahwa keterlambatan data antarmuka posisi serius, yang menyebabkan logika trading dihentikan.
// Parameters
/*
var MinAmount = 1
var SlidePrice = 5
var Interval = 500
*/
function GetPosition(e, contractType, direction) {
e.SetContractType(contractType)
var positions = _C(e.GetPosition);
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType == contractType && positions[i].Type == direction) {
return positions[i]
}
}
return null
}
function Open(e, contractType, direction, opAmount) {
var initPosition = GetPosition(e, contractType, direction);
var isFirst = true;
var initAmount = initPosition ? initPosition.Amount : 0;
var nowPosition = initPosition;
var directBreak = false
var preNeedOpen = 0
var timeoutCount = 0
while (true) {
var ticker = _C(e.GetTicker)
var needOpen = opAmount;
if (isFirst) {
isFirst = false;
} else {
nowPosition = GetPosition(e, contractType, direction);
if (nowPosition) {
needOpen = opAmount - (nowPosition.Amount - initAmount);
}
// Check directBreak and the position remains unchanged
if (preNeedOpen == needOpen && directBreak) {
Log("Suspected position data is delayed, wait for 30 seconds", "#FF0000")
Sleep(30000)
nowPosition = GetPosition(e, contractType, direction);
if (nowPosition) {
needOpen = opAmount - (nowPosition.Amount - initAmount);
}
/*
timeoutCount++
if (timeoutCount > 10) {
Log("Suspected position is delayed for 10 consecutive times, and the order is failed!", "#FF0000")
break
}
*/
} else {
timeoutCount = 0
}
}
if (needOpen < MinAmount) {
break;
}
var amount = needOpen;
preNeedOpen = needOpen
e.SetDirection(direction == PD_LONG ? "buy" : "sell");
var orderId;
if (direction == PD_LONG) {
orderId = e.Buy(ticker.Sell + SlidePrice, amount, "open long positions", contractType, ticker);
} else {
orderId = e.Sell(ticker.Buy - SlidePrice, amount, "open short positions", contractType, ticker);
}
directBreak = false
var n = 0
while (true) {
Sleep(Interval);
var orders = _C(e.GetOrders);
if (orders.length == 0) {
if (n == 0) {
directBreak = true
}
break;
}
for (var j = 0; j < orders.length; j++) {
e.CancelOrder(orders[j].Id);
if (j < (orders.length - 1)) {
Sleep(Interval);
}
}
n++
}
}
var ret = {
price: 0,
amount: 0,
position: nowPosition
};
if (!nowPosition) {
return ret;
}
if (!initPosition) {
ret.price = nowPosition.Price;
ret.amount = nowPosition.Amount;
} else {
ret.amount = nowPosition.Amount - initPosition.Amount;
ret.price = _N(((nowPosition.Price * nowPosition.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount);
}
return ret;
}
function Cover(e, contractType, opAmount, direction) {
var initPosition = null;
var position = null;
var isFirst = true;
while (true) {
while (true) {
Sleep(Interval);
var orders = _C(e.GetOrders);
if (orders.length == 0) {
break;
}
for (var j = 0; j < orders.length; j++) {
e.CancelOrder(orders[j].Id);
if (j < (orders.length - 1)) {
Sleep(Interval);
}
}
}
position = GetPosition(e, contractType, direction)
if (!position) {
break
}
if (isFirst == true) {
initPosition = position;
opAmount = Math.min(opAmount, initPosition.Amount)
isFirst = false;
}
var amount = opAmount - (initPosition.Amount - position.Amount)
if (amount <= 0) {
break
}
var ticker = _C(exchange.GetTicker)
if (position.Type == PD_LONG) {
e.SetDirection("closebuy");
e.Sell(ticker.Buy - SlidePrice, amount, "close long positions", contractType, ticker);
} else if (position.Type == PD_SHORT) {
e.SetDirection("closesell");
e.Buy(ticker.Sell + SlidePrice, amount, "close short positions", contractType, ticker);
}
Sleep(Interval)
}
return position
}
$.OpenLong = function(e, contractType, amount) {
if (typeof(e) == "string") {
amount = contractType
contractType = e
e = exchange
}
return Open(e, contractType, PD_LONG, amount);
}
$.OpenShort = function(e, contractType, amount) {
if (typeof(e) == "string") {
amount = contractType
contractType = e
e = exchange
}
return Open(e, contractType, PD_SHORT, amount);
};
$.CoverLong = function(e, contractType, amount) {
if (typeof(e) == "string") {
amount = contractType
contractType = e
e = exchange
}
return Cover(e, contractType, amount, PD_LONG);
};
$.CoverShort = function(e, contractType, amount) {
if (typeof(e) == "string") {
amount = contractType
contractType = e
e = exchange
}
return Cover(e, contractType, amount, PD_SHORT);
};
function main() {
Log(exchange.GetPosition())
var info = $.OpenLong(exchange, "quarter", 100)
Log(info, "#FF0000")
Log(exchange.GetPosition())
info = $.CoverLong(exchange, "quarter", 30)
Log(exchange.GetPosition())
Log(info, "#FF0000")
info = $.CoverLong(exchange, "quarter", 80)
Log(exchange.GetPosition())
Log(info, "#FF0000")
}
Alamat templat:https://www.fmz.com/strategy/203258
Template interface disebut dengan cara yang sama seperti$.OpenLong
, $.CoverLong
dalam fungsi utama di atas.
Template ini adalah versi beta, dan Anda dipersilakan untuk membuat saran. Kami akan terus mengoptimalkan sehingga kita dapat menangani masalah keterlambatan data posisi.