Sumber dimuat naik... memuat...

Pengenalan kepada Kod Sumber Strategi Dagangan Pasangan Mata Wang Digital dan API Terkini Platform FMZ

Penulis:FMZ~Lydia, Dicipta: 2024-07-11 14:57:15, Dikemas kini: 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 kod sumber praktikal berdasarkan platform FMZ. Strategi adalah mudah dan jelas, sesuai untuk pemula untuk belajar. Platform FMZ baru-baru ini telah menaik taraf beberapa API untuk menjadi lebih mesra dengan strategi pasangan perdagangan berbilang. Artikel ini akan memperkenalkan kod sumber JavaScript strategi ini secara terperinci. Walaupun kod strategi hanya seratus baris, ia mengandungi semua aspek yang diperlukan untuk strategi yang lengkap. API tertentu boleh dilihat dalam dokumen API, yang sangat terperinci. Alamat awam strategi:https://www.fmz.com/strategy/456143boleh disalin secara langsung.

Penggunaan Platform FMZ

Jika anda tidak biasa dengan platform FMZ, saya sangat mengesyorkan anda membaca tutorial ini:https://www.fmz.com/bbs-topic/4145Ia memperkenalkan fungsi asas platform secara terperinci, serta cara menggunakan robot dari awal.

Rangka Strategi

Berikut adalah rangka kerja strategi yang mudah. Fungsi utamanya adalah titik masuk. gelung tanpa akhir memastikan bahawa strategi dilaksanakan secara berterusan, dan masa tidur kecil ditambah untuk mengelakkan frekuensi akses melebihi had pertukaran.

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

Mencatatkan Data Sejarah

Robot akan memulakan semula berulang kali kerana pelbagai sebab, seperti kesilapan, kemas kini parameter, kemas kini strategi, dan lain-lain, dan beberapa data perlu disimpan untuk permulaan seterusnya. Berikut adalah demonstrasi bagaimana menyimpan ekuiti awal untuk mengira pulangan. Fungsi _G() boleh menyimpan pelbagai data. _G(key, nilai) boleh menyimpan nilai nilai dan memanggilnya dengan _G(key), di mana kunci adalah rentetan.

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

Apabila mendapatkan data seperti kedudukan dan keadaan pasaran melalui API, kesilapan mungkin dikembalikan kerana pelbagai sebab. Menghubungi data secara langsung akan menyebabkan strategi berhenti kerana kesilapan, jadi mekanisme toleransi kesalahan diperlukan. Fungsi _C() akan mencuba semula secara automatik selepas kesilapan sehingga data yang betul dikembalikan. Atau periksa sama ada data tersedia selepas 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 serasi dengan pelbagai mata wang

Fungsi seperti GetPosition, GetTicker, dan GetRecords boleh menambah parameter pasangan dagangan untuk mendapatkan data yang sepadan, tanpa perlu menetapkan pasangan dagangan yang terikat pertukaran, yang sangat memudahkan keserasian pelbagai strategi pasangan dagangan.https://www.fmz.com/bbs-topic/10456. Sudah tentu, docker terkini diperlukan untuk menyokongnya. Jika docker anda terlalu tua, anda perlu menaik taraf.

Parameter Strategi

  • Pair_A: Pasangan dagangan A yang perlu dipasangkan untuk dagangan. Anda perlu memilih pasangan dagangan sendiri. Anda boleh merujuk kepada pengenalan dan backtesting dalam artikel sebelumnya.
  • Pasangan_B: Pasangan perdagangan B yang perlu dipasangkan.
  • Quote: Mata wang margin bursa niaga hadapan, biasanya dalam USDT.
  • Pct: Berapa banyak penyimpangan untuk menambah kedudukan, lihat artikel mengenai prinsip-prinsip strategi untuk butiran, kerana bayaran pengendalian dan alasan slippage, ia tidak boleh ditetapkan terlalu kecil.
  • Trade_Value: Nilai dagangan untuk menambah kedudukan untuk setiap penyimpangan daripada saiz grid.
  • Ice_Value: Jika nilai urus niaga terlalu besar, anda boleh menggunakan nilai komisen aisberg untuk membuka kedudukan.
  • Max_Value: Jumlah maksimum pegangan mata wang tunggal, untuk mengelakkan risiko memegang terlalu banyak kedudukan.
  • N: Parameter yang digunakan untuk mengira nisbah harga purata, unit adalah jam, contohnya, 100 mewakili purata 100 jam.
  • Interval: Waktu tidur antara setiap kitaran strategi.

Nota Strategi Lengkap

Jika anda masih tidak faham, anda boleh menggunakan dokumentasi API FMZ, alat debugging, dan alat dialog AI yang biasa digunakan di pasaran untuk menyelesaikan soalan 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 lanjut