Tài nguyên đang được tải lên... tải...

Các mã nguồn cho các chiến lược giao dịch cho các đồng tiền kỹ thuật số và các API mới nhất của nền tảng FMZ

Tác giả:Cỏ nhỏ, Tạo: 2024-07-10 16:36:54, Cập nhật: 2024-07-12 15:53:41

img

Lời mở đầu

Một bài viết trước đã giới thiệu về các quy tắc và kiểm tra lại của giao dịch ghép nối.https://www.fmz.com/digest-topic/10457Trong bài viết này, chúng tôi sẽ giới thiệu chi tiết về mã nguồn JavaScript của chính sách này. Chính sách chỉ có một trăm dòng, nhưng nó chứa tất cả các khía cạnh cần thiết cho chính sách hoàn chỉnh. Các API cụ thể có thể được xem trong tài liệu API, giới thiệu chi tiết hơn.https://www.fmz.com/strategy/456143Có thể sao chép trực tiếp.

Sử dụng nền tảng FMZ

Nếu bạn không quen thuộc với nền tảng FMZ, chúng tôi khuyên bạn nên xem hướng dẫn này:https://www.fmz.com/bbs-topic/4145Các bài viết trên được đăng trên trang web của chúng tôi và được đăng trên trang web của chúng tôi, trong đó có những chi tiết về các chức năng cơ bản của nền tảng và cách triển khai robot từ đầu đến cuối.

Khung chiến lược

Dưới đây là một khuôn khổ chiến lược đơn giản nhất, chức năng chính là nhập. Chiến lược bảo đảm vòng quay chết được thực hiện liên tục, bao gồm một thời gian ngủ ngắn để tránh truy cập tần suất quá nhanh vượt quá giới hạn giao dịch.

function main(){
    while(true){
        //策略内容
        Sleep(Interval * 1000) //Sleep
    }
}

Ghi lại dữ liệu lịch sử

Robot sẽ khởi động lại nhiều lần vì nhiều lý do khác nhau, chẳng hạn như lỗi, cập nhật tham số, chính sách cập nhật, v.v. và cần lưu một số dữ liệu để sử dụng vào lần khởi động tiếp theo.

let init_eq = 0 //定义初始权益
if(!_G('init_eq')){  //如果没有储存_G('init_eq')返回null
    init_eq = total_eq
    _G('init_eq', total_eq) //由于没有储存,初始权益为当前权益,并在这里储存
}else{
    init_eq = _G('init_eq') //如果储存,读取初始权益的值
}

Chiến lược sai lầm

Khi truy cập dữ liệu vị trí, thị trường, v.v. thông qua API, có thể trả lại lỗi vì nhiều lý do. Việc gọi dữ liệu trực tiếp trong đó sẽ gây ra chính sách lỗi dừng lại, điều này đòi hỏi một cơ chế chấp nhận lỗi.

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 //如果数据不可用,就跳出这次循环
}

API tương thích với nhiều loại tiền tệ

Các chức năng như GetPosition, GetTicker, GetRecords có thể thêm các tham số vào một cặp giao dịch để có được dữ liệu tương ứng mà không cần thiết lập các cặp giao dịch bị ràng buộc bởi exchange, điều này rất thuận tiện cho sự tương thích của nhiều giao dịch đối với các chính sách.https://www.fmz.com/digest-topic/10451Các nhà quản lý cần phải có trình duyệt mới nhất để hỗ trợ, nếu bạn có một trình duyệt quá cũ, bạn cần nâng cấp.

Các tham số chiến lược

  • Pair_A giao dịch đồng tiền A: cần phải ghép cặp giao dịch A, cần tự chọn cặp giao dịch, có thể tham khảo bài viết trước đây về giới thiệu và đánh giá lại.
  • Pair_B giao dịch tiền tệ B: cặp giao dịch B cần giao dịch
  • Quote Tiền cơ sở: Tiền bảo lãnh của sàn giao dịch tương lai, thường là USDT
  • Kích thước lưới Pct: Phân biệt số lượng đặt cược, xem bài viết về các nguyên tắc chiến lược cụ thể, do phí thủ tục và điểm trượt nên không quá nhỏ
  • Trade_Value Giá trị giao dịch: giá trị giao dịch tăng lên mỗi lần sai kích thước lưới
  • Ice_Value Giá trị ủy thác núi băng: Nếu giá trị giao dịch quá lớn, bạn có thể mở giao dịch bằng giá trị ủy thác núi băng, thường được đặt bằng giá trị giao dịch
  • Max_Value Maximum Holding: Mức nắm giữ lớn nhất của một đồng tiền, tránh rủi ro nắm giữ quá nhiều
  • N tham số giá trung bình: tham số được sử dụng để tính tỷ lệ giá trung bình, đơn vị là giờ, chẳng hạn như 100 đại diện cho giá trung bình của 100h
  • Interval thời gian ngủ (s): thời gian ngủ trong mỗi khoảng thời gian chu kỳ của chiến lược

Thông tin chính sách đầy đủ

Nếu bạn chưa hiểu, bạn có thể giải quyết câu hỏi bằng tài liệu API của FMZ, công cụ điều chỉnh và các công cụ đối thoại AI phổ biến trên thị trường.

function GetPosition(pair){
    let pos = _C(exchange.GetPosition, pair)
    if(pos.length == 0){ //返回为空代表没有持仓
        return {amount:0, price:0, profit:0}
    }else if(pos.length > 1){ //策略要设置为单向持仓模式
        throw '不支持双向持仓'
    }else{ //为了方便,多仓持仓量为正,空仓持仓量为负
        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) //小时K线
    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--){ //反过来计算,避免K线长度不够
        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'){ //由于这里的API并不兼容,目前仅OKX期货交易所获取到总权益
        total_eq = account.Info.data[0].totalEq //其他交易所的宗权益Info中也包含,可以自己对着交易所API文档找找
    }else{
        total_eq = account.Balance //其它交易所暂时使用可用余额,会造成计算收益错误,但不影响策略使用
    }
    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() //这里获取精度
    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){ //每10分钟更新下均价和账户信息
            ratio = GetRatio()
            total_eq = GetAccount()
            last_get_ratio_time = Date.now()
        }
        let pair_a = Pair_A+"_"+Quote+".swap" //交易对的设置形如BTC_USDT.swap
        let pair_b = Pair_B+"_"+Quote+".swap"
        let CtVal_a = "CtVal" in precision[pair_a] ? precision[pair_a].CtVal : 1 //有的交易所用张来代表数量,如一张代表0.01个币,因此需要换算下
        let CtVal_b = "CtVal" in precision[pair_b] ? precision[pair_b].CtVal : 1 //不含这个字段的不用张
        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){ //如果返回数据异常,跳出这次循环
            continue
        }
        let diff = (ticker_A.Last / ticker_B.Last - ratio) / ratio //计算偏离的比例
        let aim_value = - Trade_Value * diff / Pct //目标持有的仓位
        let id_A = null
        let id_B = null
        //以下是具体的开仓逻辑
        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) //这里直接撤销
        }
        if(id_B){
            exchange.CancelOrder(id_B)
        }
        let table = {
            type: "table",
            title: "交易信息",
            cols: ["初始权益", "当前权益", Pair_A+"仓位", Pair_B+"仓位", Pair_A+"持仓价", Pair_B+"持仓价", Pair_A+"收益", Pair_B+"收益", Pair_A+"价格", Pair_B+"价格", "当前比价", "平均比价", "偏离均价", "循环延时"],
            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) + "`") //这个函数会在机器人页面显示包含以上信息的表格
        Sleep(Interval * 1000) //休眠时间为ms
    }
}

Thêm nữa

gia súcXin chào, hãy kiểm tra lại exchange.GetMarkets))) chỉ có thể nhận được dữ liệu của một cặp giao dịch, làm thế nào để thiết lập có thể nhận được nhiều hơn, ví dụ như hai cặp giao dịch.

77924998Có phiên bản Python không?

Hạt đậu 888/upload/asset/21c799a2c667c13fcb0bd.png Mái có hơi lùn

Những nhà phát minh định lượng - những giấc mơ nhỏQuá trình kiểm tra lại hiện chưa hỗ trợ chức năng GetMarkets, bạn có thể chờ một chút.

ChaoZhangTăng cấp lên nhà quản trị mới nhất