avatar of 发明者量化-小小梦 发明者量化-小小梦
fokus pada Pesan pribadi
4
fokus pada
1271
Pengikut

Beberapa pemikiran tentang logika perdagangan berjangka mata uang digital

Dibuat di: 2020-06-01 09:52:45, diperbarui pada: 2023-10-08 19:41:25
comments   6
hits   2406

Beberapa pemikiran tentang logika perdagangan berjangka mata uang digital

Beberapa pemikiran tentang logika perdagangan berjangka mata uang digital

Skenario masalah

Selama ini, masalah keterlambatan data pada antarmuka API posisi pertukaran mata uang digital selalu mengganggu saya. Saya belum menemukan solusi yang cocok, jadi saya akan mengulangi masalah ini. Biasanya, perintah pasar yang diberikan oleh bursa kontrak sebenarnya adalah harga rekanan, sehingga terkadang penggunaan apa yang disebut “perintah pasar” ini tidak dapat diandalkan. Oleh karena itu, ketika kita menulis strategi perdagangan berjangka mata uang digital, kebanyakan dari kita menggunakan perintah batas. Setelah menempatkan setiap order, kita perlu memeriksa posisi untuk melihat apakah order telah dieksekusi dan apakah posisi terkait dipertahankan. Masalahnya terletak pada informasi posisi ini. Jika order dieksekusi, data yang dikembalikan oleh antarmuka informasi posisi bursa (yaitu, antarmuka bursa yang benar-benar diakses saat kita memanggil exchange.GetPosition) harus menyertakan informasi posisi yang baru dibuka. Namun, jika data yang dikembalikan oleh bursa adalah data lama, yaitu informasi posisi sebelum order yang baru saja ditempatkan dieksekusi, maka akan terjadi masalah. Logika perdagangan mungkin mengira bahwa order belum dieksekusi dan meneruskan order tersebut. Akan tetapi, antarmuka penempatan pesanan di bursa tidak mengalami penundaan apa pun. Sebaliknya, transaksi diselesaikan dengan sangat cepat, dan pesanan dieksekusi segera setelah ditempatkan. Ini akan mengakibatkan konsekuensi serius bahwa strategi akan berulang kali menempatkan pesanan saat operasi pembukaan dipicu.

Pengalaman nyata

Karena masalah ini, saya telah melihat strategi yang membuka posisi long penuh yang gila-gilaan. Untungnya, pasar sedang booming saat itu dan laba mengambang pernah melampaui 10BTC. Untungnya, pasar sedang booming, jika anjlok, hasilnya bisa ditebak.

Cobalah untuk menyelesaikannya

  • Solusi 1 Logika order dari strategi tersebut dapat dirancang untuk menempatkan hanya satu order, dan harga order adalah harga lawan pada saat itu ditambah slippage yang lebih besar, sehingga dapat mengambil order lawan dengan kedalaman tertentu. Keuntungan melakukan ini adalah Anda hanya menempatkan satu pesanan dan tidak didasarkan pada informasi posisi. Hal ini dapat menghindari masalah order duplikat, namun terkadang menempatkan order ketika harga berubah drastis dapat memicu mekanisme batas harga bursa, dan ada kemungkinan bahwa meskipun terjadi slippage yang besar, order tersebut tetap tidak akan dieksekusi, sehingga kehilangan kesempatan. .

  • Solusi 2 Gunakan fungsi order pasar dari bursa dan berikan -1 pada FMZ sebagai harga, yang merupakan order pasar. Saat ini, antarmuka berjangka OKEX telah ditingkatkan untuk mendukung order pasar riil.

  • Solusi 3 Kami masih menggunakan logika perdagangan sebelumnya dan menempatkan pesanan menggunakan pesanan terbatas, tetapi kami menambahkan beberapa deteksi pada logika perdagangan untuk mencoba memecahkan masalah yang disebabkan oleh keterlambatan data posisi. Periksa apakah pesanan menghilang dari daftar pesanan tertunda tanpa dibatalkan setelah menempatkan pesanan (ada dua kemungkinan hilangnya pesanan dari daftar pesanan tertunda: 1 pembatalan dan 2 pemenuhan). Jika situasi seperti itu terdeteksi dan jumlah pesanan dan Pesanan volume sama dengan terakhir kali. Pada saat ini, Anda harus memperhatikan apakah data posisi tertunda. Biarkan program memasuki logika menunggu untuk memperoleh kembali informasi posisi. Anda bahkan dapat terus mengoptimalkan dan menambah jumlahnya pemicu menunggu. Jika melebihi angka tertentu, berarti data antarmuka posisi tertunda. Masalahnya serius, jadi logika transaksi ini dihentikan.

Desain berdasarkan Skema 3

// 参数
/*
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);
            }
            // 检测directBreak 并且持仓未变的情况
            if (preNeedOpen == needOpen && directBreak) {
                Log("疑似仓位数据延迟,等待30秒", "#FF0000")
                Sleep(30000)
                nowPosition = GetPosition(e, contractType, direction);
                if (nowPosition) {
                    needOpen = opAmount - (nowPosition.Amount - initAmount);
                }
                /*
                timeoutCount++
                if (timeoutCount > 10) {
                    Log("连续10次疑似仓位延迟,下单失败!", "#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, "开多仓", contractType, ticker);
        } else {
            orderId = e.Sell(ticker.Buy - SlidePrice, amount, "开空仓", 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, "平多仓", contractType, ticker);
        } else if (position.Type == PD_SHORT) {
            e.SetDirection("closesell");
            e.Buy(ticker.Sell + SlidePrice, amount, "平空仓", 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

Cara memanggil interface template sama seperti pada fungsi main diatas$.OpenLong$.CoverLong。 Template ini adalah versi beta. Saran dan komentar akan kami terima dengan senang hati. Kami akan terus mengoptimalkannya untuk mengatasi masalah keterlambatan data posisi.