Beberapa Pikiran tentang Logika Perdagangan Berjangka Mata Uang Digital

Penulis:Lydia, Dibuat: 2022-11-30 17:12:20, Diperbarui: 2023-09-11 19:59:55

img

Beberapa Pikiran tentang Logika Perdagangan Berjangka Mata Uang Digital

Skenario masalah

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 order harga pasar. Namun, ketika kita menulis strategi perdagangan berjangka mata uang digital, kita menggunakan pesanan batas paling banyak. Setelah setiap pesanan ditempatkan, kita perlu memeriksa posisi untuk melihat apakah pesanan ditutup dan posisi yang sesuai dipegang. Masalahnya terletak pada posisi informasi ini. Jika pesanan ditutup, data yang dikembalikan oleh antarmuka informasi posisi pertukaran (yaitu antarmuka yang sebenarnya diakses oleh lapisan bawah ketika kita mengisi pertukaran. Dapatkan antarmuka posisi yang sangat serius) harus mencakup informasi posisi baru. Namun, jika posisi lama selesai, pertukaran akan kembali ke tempat yang tepat.

Pengalaman praktis

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

  • 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.

Desain berdasarkan Solusi 3

// 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, $.CoverLongdalam 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.


Berkaitan

Lebih banyak