Sumber daya yang dimuat... Pemuatan...

Pengantar ke Kode Sumber Strategi Perdagangan Pasangan Mata Uang Digital dan API Terbaru dari Platform FMZ

Penulis:FMZ~Lydia, Dibuat: 2024-07-11 14:57:15, Diperbarui: 2024-07-12 15:55:53

img

Pengantar

Artikel sebelumnya memperkenalkan prinsip dan backtesting perdagangan pasangan,https://www.fmz.com/bbs-topic/10459. Berikut adalah kode sumber praktis berdasarkan platform FMZ. Strategi sederhana dan jelas, cocok untuk pemula untuk belajar. Platform FMZ baru-baru ini telah memperbarui beberapa API untuk menjadi lebih ramah untuk strategi pasangan multi-dagang. Artikel ini akan memperkenalkan kode sumber JavaScript strategi ini secara rinci. Meskipun kode strategi hanya seratus baris, itu berisi semua aspek yang diperlukan untuk strategi yang lengkap. API tertentu dapat dilihat dalam dokumen API, yang sangat rinci. Alamat publik strategi:https://www.fmz.com/strategy/456143dapat disalin langsung.

Penggunaan Platform FMZ

Jika Anda tidak terbiasa dengan platform FMZ, saya sangat menyarankan Anda untuk membaca tutorial ini:https://www.fmz.com/bbs-topic/4145Ini memperkenalkan fungsi dasar platform secara rinci, serta bagaimana untuk menyebarkan robot dari nol.

Kerangka Strategi

Berikut adalah kerangka strategi sederhana. Fungsi utamanya adalah titik masuk. loop tak terbatas memastikan bahwa strategi dieksekusi secara terus menerus, dan waktu tidur kecil ditambahkan untuk mencegah frekuensi akses melebihi batas pertukaran.

function main(){
    while(true){
        //strategy content
        Sleep(Interval * 1000) //Sleep
    }
}

Catat Data Sejarah

Robot akan memulai kembali berulang kali karena berbagai alasan, seperti kesalahan, pembaruan parameter, pembaruan strategi, dll, dan beberapa data perlu disimpan untuk startup berikutnya. Berikut adalah demonstrasi cara menyimpan ekuitas awal untuk menghitung pengembalian. Fungsi _G() dapat menyimpan berbagai data. _G(key, value) dapat menyimpan nilai nilai dan memanggilnya dengan _G(key), di mana key adalah string.

let init_eq = 0 //defining initial equity
if(!_G('init_eq')){  //If there is no storage, _G('init_eq') returns null.
    init_eq = total_eq
    _G('init_eq', total_eq) //Since there is no storage, the initial equity is the current equity and is stored here
}else{
    init_eq = _G('init_eq') //If stored, read the value of the initial equity
}

Strategi Toleransi Kesalahan

Ketika mendapatkan data seperti posisi dan kondisi pasar melalui API, kesalahan dapat dikembalikan karena berbagai alasan. Menelpon data secara langsung akan menyebabkan strategi berhenti karena kesalahan, sehingga mekanisme toleransi kesalahan diperlukan. Fungsi _C() akan mencoba kembali secara otomatis setelah kesalahan sampai data yang benar dikembalikan. Atau periksa apakah data tersedia setelah dikembalikan.

let pos = _C(exchange.GetPosition, pair)

let ticker_A = exchange.GetTicker(pair_a)
let ticker_B = exchange.GetTicker(pair_b)
if(!ticker_A || !ticker_B){
    continue //If the data is not available, exit the loop.
}

API yang kompatibel dengan multi-mata uang

Fungsi seperti GetPosition, GetTicker, dan GetRecords dapat menambahkan parameter pasangan perdagangan untuk mendapatkan data yang sesuai, tanpa harus mengatur pasangan perdagangan yang terikat pertukaran, yang sangat memfasilitasi kompatibilitas beberapa strategi pasangan perdagangan.https://www.fmz.com/bbs-topic/10456. Tentu saja, docker terbaru diperlukan untuk mendukungnya. Jika docker Anda terlalu tua, Anda perlu meningkatkan.

Parameter Strategi

  • Pair_A: Pasangan perdagangan A yang perlu dipasangkan untuk perdagangan. Anda perlu memilih pasangan perdagangan sendiri. Anda dapat merujuk pada pengenalan dan backtesting di artikel sebelumnya.
  • Pair_B: Pasangan perdagangan B yang perlu dipasangkan.
  • Quote: Mata uang margin dari bursa futures, biasanya dalam USDT.
  • Pct: Berapa banyak penyimpangan untuk menambahkan posisi, lihat artikel tentang prinsip-prinsip strategi untuk rincian, karena biaya penanganan dan alasan slippage, itu tidak harus ditetapkan terlalu kecil.
  • Trade_Value: Nilai perdagangan dari penjumlahan posisi untuk setiap penyimpangan dari ukuran grid.
  • Ice_Value: Jika nilai transaksi terlalu besar, Anda dapat menggunakan nilai komisi gunung es untuk membuka posisi.
  • Max_Value: Nilai maksimum dari satu mata uang, untuk menghindari risiko memegang terlalu banyak posisi.
  • N: Parameter yang digunakan untuk menghitung rasio harga rata-rata, satuannya adalah jam, misalnya, 100 mewakili rata-rata 100 jam.
  • Interval: Waktu tidur antara setiap siklus strategi.

Catatan Strategi Lengkap

Jika Anda masih tidak mengerti, Anda dapat menggunakan dokumentasi API FMZ, alat debugging, dan alat dialog AI yang umum digunakan di pasar untuk memecahkan pertanyaan Anda.

function GetPosition(pair){
    let pos = _C(exchange.GetPosition, pair)
    if(pos.length == 0){ //Returns null to indicate no position
        return {amount:0, price:0, profit:0}
    }else if(pos.length > 1){ //The strategy should be set to unidirectional position mode
        throw 'Bidirectional positions are not supported'
    }else{ //For convenience, long positions are positive and short positions are negative
        return {amount:pos[0].Type == 0 ? pos[0].Amount : -pos[0].Amount, price:pos[0].Price, profit:pos[0].Profit}
    }
}

function GetRatio(){
    let kline_A = exchange.GetRecords(Pair_A+"_"+Quote+".swap", 60*60, N) //Hourly K-line
    let kline_B = exchange.GetRecords(Pair_B+"_"+Quote+".swap", 60*60, N)
    let total = 0
    for(let i= Math.min(kline_A.length,kline_B.length)-1; i >= 0; i--){ //Calculate in reverse to avoid the K-line being too short.
        total += kline_A[i].Close / kline_B[i].Close
    }
    return total / Math.min(kline_A.length,kline_B.length)
}

function GetAccount(){
    let account = _C(exchange.GetAccount)
    let total_eq = 0
    if(exchange.GetName == 'Futures_OKCoin'){ //Since the API here is not compatible, only OKX Futures Exchange obtains the total equity currently.
        total_eq = account.Info.data[0].totalEq //The equity information of other exchanges is also included. You can look for it yourself in the exchange API documentation.
    }else{
        total_eq = account.Balance //Temporary use of available balances on other exchanges will cause errors in calculating returns, but will not affect the use of strategies.
    }
    let init_eq = 0
    if(!_G('init_eq')){
        init_eq = total_eq
        _G('init_eq', total_eq)
    }else{
        init_eq = _G('init_eq')
    }
    LogProfit(total_eq - init_eq)
    return total_eq
}

function main(){
    var precision = exchange.GetMarkets() //Get the precision here
    var last_get_ratio_time = Date.now()
    var ratio = GetRatio()
    var total_eq = GetAccount()
    while(true){
        let start_loop_time = Date.now()
        if(Date.now() - last_get_ratio_time > 10*60*1000){ //Update the average price and account information every 10 minutes
            ratio = GetRatio()
            total_eq = GetAccount()
            last_get_ratio_time = Date.now()
        }
        let pair_a = Pair_A+"_"+Quote+".swap" //The trading pair is set as BTC_USDT.swap
        let pair_b = Pair_B+"_"+Quote+".swap"
        let CtVal_a = "CtVal" in precision[pair_a] ? precision[pair_a].CtVal : 1 //Some exchanges use sheets to represent quantity, such as one sheet represents 0.01 coin, so you need to convert.
        let CtVal_b = "CtVal" in precision[pair_b] ? precision[pair_b].CtVal : 1 //No need to include this field
        let position_A = GetPosition(pair_a)
        let position_B = GetPosition(pair_b)
        let ticker_A = exchange.GetTicker(pair_a)
        let ticker_B = exchange.GetTicker(pair_b)
        if(!ticker_A || !ticker_B){ //If the returned data is abnormal, jump out of this loop
            continue
        }
        let diff = (ticker_A.Last / ticker_B.Last - ratio) / ratio //Calculate the ratio of deviation
        let aim_value = - Trade_Value * diff / Pct //Target holding position
        let id_A = null
        let id_B = null
        //The following is the specific logic of opening a position
        if( -aim_value + position_A.amount*CtVal_a*ticker_A.Last > Trade_Value && position_A.amount*CtVal_a*ticker_A.Last > -Max_Value){
            id_A = exchange.CreateOrder(pair_a, "sell", ticker_A.Buy, _N(Ice_Value / (ticker_A.Buy * CtVal_a), precision[pair_a].AmountPrecision))
        }
        if( -aim_value - position_B.amount*CtVal_b*ticker_B.Last > Trade_Value && position_B.amount*CtVal_b*ticker_B.Last < Max_Value){
            id_B = exchange.CreateOrder(pair_b, "buy", ticker_B.Sell, _N(Ice_Value / (ticker_B.Sell * CtVal_b), precision[pair_b].AmountPrecision))
        }
        if( aim_value - position_A.amount*CtVal_a*ticker_A.Last > Trade_Value && position_A.amount*CtVal_a*ticker_A.Last < Max_Value){
            id_A = exchange.CreateOrder(pair_a, "buy", ticker_A.Sell, _N(Ice_Value / (ticker_A.Sell * CtVal_a), precision[pair_a].AmountPrecision))
        }
        if( aim_value + position_B.amount*CtVal_b*ticker_B.Last > Trade_Value &&  position_B.amount*CtVal_b*ticker_B.Last > -Max_Value){
            id_B = exchange.CreateOrder(pair_b, "sell", ticker_B.Buy, _N(Ice_Value / (ticker_B.Buy * CtVal_b), precision[pair_b].AmountPrecision))
        }
        if(id_A){
            exchange.CancelOrder(id_A) //Cancel directly here
        }
        if(id_B){
            exchange.CancelOrder(id_B)
        }
        let table = {
            type: "table",
            title: "trading Information",
            cols: ["initial equity", "current equity", Pair_A+"position", Pair_B+"position", Pair_A+"holding price", Pair_B+"holding price", Pair_A+"profits", Pair_B+"profits", Pair_A+"price", Pair_B+"price", "current price comparison", "average price comparison", "deviation from average price", "loop delay"],
            rows: [[_N(_G('init_eq'),2), _N(total_eq,2), _N(position_A.amount*CtVal_a*ticker_A.Last, 1), _N(position_B.amount*CtVal_b*ticker_B.Last,1),
                _N(position_A.price, precision[pair_a].PircePrecision), _N(position_B.price, precision[pair_b].PircePrecision),
                _N(position_A.profit, 1), _N(position_B.profit, 1), ticker_A.Last, ticker_B.Last,
                _N(ticker_A.Last / ticker_B.Last,6), _N(ratio, 6), _N(diff, 4), (Date.now() - start_loop_time)+"ms"
            ]]
        }
        LogStatus("`" + JSON.stringify(table) + "`") //This function will display a table containing the above information on the robot page.
        Sleep(Interval * 1000) //Sleep time in ms
    }
}

Lebih banyak