Die Ressourcen sind geladen. Beförderung...

Die neue API der FMZ-Plattform und der Quellcode für die Kryptowährungspaarungsstrategie

Schriftsteller:Das Gras, Erstellt: 2024-07-10 16:36:54, aktualisiert: 2024-07-12 15:53:41

img

Vorwort

In einem früheren Artikel ging es um die Grundsätze und Retesting von Pairing-Transaktionen.https://www.fmz.com/digest-topic/10457Hier ist ein praktischer, einfacher und klarer Grundsatz der FMZ-Plattform, der für Anfänger geeignet ist. Die FMZ-Plattform hat kürzlich einige API-Upgrades vorgenommen, um die Strategie für mehrere Transaktionen freundlicher zu gestalten.https://www.fmz.com/strategy/456143Sie können direkt kopiert werden.

FMZ-Plattform verwendet

Wenn Sie nicht mit der FMZ-Plattform vertraut sind, empfehlen wir Ihnen dringend, dieses Tutorial zu lesen:https://www.fmz.com/bbs-topic/4145In diesem Artikel werden die grundlegenden Funktionen der Plattform und wie man einen Roboter von Anfang an einsetzt, detailliert beschrieben.

Strategischer Rahmen

Hier ist ein einfaches Strategien-Framework, dessen Hauptfunktion die Eingabe ist. Die Toten-Zyklus-Sicherheits-Strategien werden kontinuierlich ausgeführt, eine kleine Ruhezwischenzeit hinzugefügt, um zu vermeiden, dass die Zugriffsfrequenz zu schnell die Grenzen der Börse überschreitet.

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

Die historische Aufzeichnung

Der Roboter wird aus verschiedenen Gründen wiederholt neu gestartet, z. B. wenn Fehler auftreten, Parameter aktualisiert werden, Strategien aktualisiert werden usw. Es ist notwendig, einige Daten für den nächsten Start zu speichern. Hier wird gezeigt, wie man die ursprünglichen Rechte für die Berechnung der Erträge speichert.

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') //如果储存,读取初始权益的值
}

Strategische Fehler

Bei der Erfassung von Daten wie Positionen, Märkte usw. durch die API kann es aus verschiedenen Gründen zu Fehlern kommen. Dies führt dazu, dass die Daten direkt aufgerufen werden, was zu einem Fehlerstopp führt. Dies erfordert einen fehlerfreien Mechanismus.

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

Kompatible APIs für mehrere Währungen

Funktionen wie GetPosition, GetTicker, GetRecords können die Parameter eines Transaktionspaares hinzufügen, um die entsprechenden Daten zu erhalten, ohne dass ein Exchange-gebundenes Transaktionspaar eingerichtet werden muss. Dies erleichtert die Kompatibilität von mehreren Transaktionen mit den Strategien.https://www.fmz.com/digest-topic/10451Und natürlich benötigen Sie den neuesten Host, um ihn zu unterstützen, und wenn Ihr Host zu alt ist, müssen Sie ihn aktualisieren.

Strategieparameter

  • Pair_A Handelswährung A: Die Paare A, die für den Handel benötigt werden, müssen selbst ausgewählt werden. Sie können sich auf die Einführung und die Überprüfung des vorherigen Artikels beziehen.
  • Pair_B Handelskurse B: Handelspare B, die eine Pairing erfordern
  • Quote Basiswährung: Die Basiswährung der Futures-Börse, in der Regel USDT
  • Pct-Gittergröße: Wie viel Abweichung von der Aufstockung, sehen Sie den Artikel über die Strategieprinzipien Einführung, sollte nicht zu klein sein, wegen der Gebühren und Gleitpunkte
  • Trade_Value Transaktionswert: Der Transaktionswert, der für jede Abweichung von einer Gittergröße erhöht wird
  • Ice_Value Eisberg-Auftragswert: Wenn der Transaktionswert zu groß ist, kann mit dem Eisberg-Auftragswert gehandelt werden, der normalerweise so groß ist wie der Transaktionswert
  • Max_Value: Maximaler Bestand in einer Währung, um das Risiko zu vermeiden, zu viel zu halten
  • N Durchschnittspreisparameter: Parameter, die für den Vergleich von Durchschnittspreisen verwendet werden, wobei die Einheit Stunden ist, z. B. 100 für den Durchschnittswert von 100 h
  • Interval Ruhezwischenzeit ((Sekunden): Die Ruhezwischenzeit für jedes Zyklusintervall der Strategie

Komplete Strategie-Anmerkung

Wenn Sie sich noch nicht im Klaren sind, können Sie sich mit FMZs API-Dokumentation, Debugging-Tools und den häufig auf dem Markt verwendeten AI-Dialog-Tools befassen.

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
    }
}

Mehr

77924998Gibt es eine Python Version?

Weizen 888/upload/asset/21c799a2c667c13fcb0bd.png Ein bisschen schief

Die Erfinder quantifizieren - Kleine TräumeDie GetMarkets-Funktion wird derzeit nicht unterstützt.

ChaoZhangUpgrade auf den neuesten Host