O recurso está a ser carregado... Carregamento...

O código fonte da estratégia de negociação de pacotes de moedas digitais e a mais recente API da plataforma FMZ

Autora:Ervas daninhas, Criado: 2024-07-10 16:36:54, Atualizado: 2024-07-12 15:53:41

img

Prefácio

O artigo anterior descreveu os princípios e a retrospectiva dos acordos de parceria.https://www.fmz.com/digest-topic/10457O código-fonte prático baseado na plataforma FMZ é apresentado aqui. A estratégia é mais simples e clara e apropriada para aprendizagem de iniciantes. A plataforma FMZ recentemente atualizou parte da API para ser mais amigável para multi-transações. Este artigo descreve em detalhes o código-fonte JavaScript da política.https://www.fmz.com/strategy/456143O site também oferece uma série de vídeos sobre o assunto.

Utilização da plataforma FMZ

Se você não está familiarizado com a plataforma FMZ, recomendo que você leia este tutorial:https://www.fmz.com/bbs-topic/4145A plataforma é uma ferramenta para criar um robô, que pode ser usado para criar uma plataforma de negócios, e também para criar um robô.

Estrutura estratégica

Abaixo está um quadro de estratégias mais simples, cuja função principal é a entrada. A estratégia de garantia do ciclo morto é executada continuamente, incluindo um pequeno período de sono para evitar que a frequência de acesso ultrapasse os limites da troca.

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

Registro de dados históricos

O robô reinicia-se repetidamente por várias razões, como erros, atualização de parâmetros, política de atualização, etc., e precisa salvar alguns dados para serem usados na próxima inicialização. Aqui é demonstrado como salvar o direito inicial para calcular o rendimento.

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

A estratégia não é boa

Quando se obtém dados de posições, mercados, etc. através de uma API, por várias razões, pode retornar como um erro. Isso causa uma interrupção da política de erro quando os dados são chamados diretamente, o que requer um mecanismo tolerante a erros.

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 compatível com várias moedas

Funções como GetPosition, GetTicker, GetRecords podem ser adicionadas aos parâmetros de um par de transações para obter os dados correspondentes, sem a necessidade de configurar um par de transações vinculado ao exchange, o que facilita a compatibilidade de várias estratégias de transações.https://www.fmz.com/digest-topic/10451É claro que você precisa de um servidor mais recente para suportá-lo, mas se o seu servidor é muito antigo, você precisa atualizar.

Parâmetros de estratégia

  • Pair_A moeda de negociação A: para o par de transações A, é necessário escolher seu próprio par de transações.
  • Pair_B moeda de negociação B: o par de transações B que precisa de uma paragem de transações
  • Quote Moeda de base: moeda de garantia de uma bolsa de futuros, geralmente USDT
  • Tamanho da grade Pct: desviação de quanto o ganho, veja o artigo sobre o princípio da estratégia, não deve ser muito pequeno por causa de taxas de manutenção e pontos de deslizamento
  • Trade_Value Valor do negócio: valor do negócio aumentado a cada desvio de tamanho da grade
  • Valor Ice_Value Valor do iceberg: se o valor do negócio for muito grande, pode ser aberto com o valor do iceberg, geralmente definido como igual ao valor do negócio
  • Max_Value Maximum Holding: o maior posicionamento de uma única moeda, evitando o risco de ter muito
  • N Parâmetros de preço médio: Parâmetros usados para calcular a comparação de preços médios, unitados em horas, como 100 representa o valor médio de 100h
  • Interval Tempo de repouso (s): tempo de repouso de cada intervalo de ciclo da estratégia

Comentários completos sobre estratégias

Se você ainda não entendeu, você pode resolver suas dúvidas com a documentação da API do FMZ, ferramentas de depuração e ferramentas de diálogo de IA comuns no 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
    }
}

Mais.

77924998Há uma versão em Python?

Feijão 888/upload/asset/21c799a2c667c13fcb0bd.png Um pouco de barulho

Inventor quantificado - sonho pequenoO retest ainda não suporta a função GetMarkets, pode esperar um pouco para suportá-la.

ChaoZhangAtualizar para o último administrador