En la carga de los recursos... Cargando...

El código fuente de la estrategia de negociación de la pareja de monedas digitales y la última API de la plataforma FMZ

El autor:Las hierbas, Creado: 2024-07-10 16:36:54, Actualizado: 2024-07-12 15:53:41

img

Prólogo

En un artículo anterior, se habló sobre los principios y las pruebas de los acuerdos de pareja.https://www.fmz.com/digest-topic/10457Aquí se proporciona un código fuente práctico basado en la plataforma FMZ, la estrategia es más simple y clara, para el aprendizaje de los principiantes. La plataforma FMZ ha actualizado recientemente parte de la API para ser más amigable con la estrategia multi-transacción. Este artículo describe en detalle el código fuente JavaScript de la política.https://www.fmz.com/strategy/456143Los usuarios pueden copiarlos directamente.

Uso de la plataforma FMZ

Si no estás familiarizado con la plataforma FMZ, te recomiendo que leas este tutorial:https://www.fmz.com/bbs-topic/4145En la página web del sitio web, se explica en detalle las funciones básicas de la plataforma y cómo desplegar un robot de principio a fin.

Marco estratégico

A continuación se muestra el marco de la estrategia más simple, la función principal es la entrada. La estrategia de garantía de ciclo muerto se ejecuta continuamente, y se incluye un pequeño tiempo de descanso para evitar que la frecuencia de acceso exceda demasiado rápidamente los límites de la bolsa.

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

Registro de datos históricos

El robot se reinicia repetidamente por diversas razones, como errores, actualización de parámetros, actualización de políticas, etc., y necesita guardar algunos datos para su siguiente inicio. Aquí se demuestra cómo guardar los derechos iniciales para calcular los beneficios.

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

El error de la estrategia

Cuando se obtienen datos de posiciones, mercados, etc. a través de la API, por diversas razones, puede que se devuelvan errores. Esto significa que si se llama directamente a los datos, la política se detiene por error, lo que requiere un mecanismo de tolerancia a errores.

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 compatible con varias monedas

Funciones como GetPosition, GetTicker y GetRecords pueden agregar parámetros a una transacción para obtener los datos correspondientes sin necesidad de configurar transacciones vinculadas a exchange, lo que facilita la compatibilidad de múltiples transacciones con la política.https://www.fmz.com/digest-topic/10451Por supuesto, se requiere el servidor más reciente para soportar, si su servidor es demasiado antiguo, necesita una actualización.

Parámetros de la estrategia

  • Pair_A moneda de negociación A: el par de transacciones A que requiere el emparejamiento de la transacción, requiere que usted elija su propio par de transacciones, por lo que puede consultar la introducción y la revisión del artículo anterior.
  • Pair_B moneda de transacción B: el par de transacciones B que requiere el emparejamiento de transacciones
  • Quote moneda base: moneda de garantía de las bolsas de futuros, generalmente USDT
  • Tamaño de la rejilla Pct: no debe ser demasiado pequeño debido a las tarifas y puntos de deslizamiento.
  • Trade_Value Valor de la transacción: el valor de la transacción incrementado por cada desviación del tamaño de una red
  • Ice_Value Valor de la comisión de montaña de hielo: si el valor de la transacción es demasiado grande, se puede abrir una operación con el valor de la comisión de montaña de hielo, generalmente se puede establecer como el mismo valor de la transacción
  • Max_Value Maximum Holding: el máximo de una sola moneda para evitar el riesgo de tener demasiadas posiciones
  • Parámetros de precio medio N: Parámetros para calcular la comparación de precios medios, en unidades por hora, como 100 para 100h
  • Interval Tiempo de reposo (s): el tiempo de reposo de cada intervalo de ciclo de la estrategia

Comentario completo de la estrategia

Si aún no lo entiende, puede resolver sus dudas con la documentación de la API de FMZ, las herramientas de depuración y las herramientas de diálogo de IA que se utilizan comúnmente en el mercado.

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

Más.

SidianshuiaHola, ¿cómo se puede configurar para obtener más datos, por ejemplo, dos pares de datos?

77924998¿Hay alguna versión en Python?

Las semillas 888/upload/asset/21c799a2c667c13fcb0bd.png El contenido del archivo está disponible en inglés. Un poco de miedo.

Los inventores cuantifican - sueños pequeñosLa función GetMarkets no está soportada por el test, pero puede esperar un poco.

¿ Qué pasa?Actualizar a la última administradora