Projeto de Sistema de Gestão da Sincronização de Encomendas Baseado no FMZ Quant (1)

Autora:Lydia., Criado: 2022-11-07 10:20:01, Atualizado: 2023-09-15 20:45:23

img

Projeto de Sistema de Gestão da Sincronização de Encomendas Baseado no FMZ Quant (1)

Em artigos anteriores na biblioteca FMZs, projetamos vários tipos de estratégias de sincronização para ordem e posição.

Estes gerenciam contas de referência e contas sincronizadas em uma estratégia para alcançar a sincronização de ordem e posição. e hoje vamos tentar um design diferente, vamos projetar um sistema de gerenciamento de sincronização de ordem baseado na poderosa interface API estendida da FMZ Quant Trading Platform.

Ideias de Design

Primeiro, precisamos de algumas boas sugestões e necessidades. as duas estratégias anteriores de sincronização de ordem e posição acima, que têm várias deficiências óbvias, que discutiremos juntos.

    1. Os usuários de estratégias de sincronização real bot devem ter a chave de API de troca da conta de referência, e a chave de API de troca da conta de sincronização. Este problema é bom para a situação de uso em que as outras contas de câmbio seguem sua própria conta. No entanto, pode ser problemático para a situação em que a conta de referência e a conta de sincronização não são o mesmo proprietário. Às vezes, o proprietário da conta sincronizada não quer fornecer a chave API de sua própria conta de câmbio por razões de segurança, mas como sincronizar as transações de pedido sem fornecer a chave API?

    Soluções: Usando a interface API estendida do FMZ, o proprietário da conta sincronizada (seguidor de ordens) só precisa registrar uma conta na plataforma de negociação FMZ Quant, em seguida, execute uma estratégia (no sistema projetado neste artigo:Order Synchronous ServerEstratégia em Real Bot). Em seguida, basta fornecer o FMZ extensão API KEY (note que não é a API KEY da conta de troca) e a ordem de servidor síncrono real bot ID para o proprietário da conta de referência (orden líder). Quando o proprietário da conta de referência (seguidores da ordem) é um robô real (oOrder Synchronization Management System Class Library (Single Server)No sistema concebido neste artigo) envia um sinal, o bot real do proprietário da conta de sincronização irá receber o sinal de negociação e colocar a ordem subsequente automaticamente.

    1. Muitos desenvolvedores têm boas estratégias, mas não podem usar as 2 estratégias de sincronização de ordem e posição anteriores descritas acima. Porque eles precisam integrar suas próprias estratégias com essas estratégias sincronizadas, e as estratégias podem precisar ser alteradas drasticamente, o que custará muito trabalho e esforço. Há uma boa maneira de atualizar algumas de suas estratégias maduras diretamente para a função de sincronização de ordem? Soluções: Você pode projetar uma biblioteca de classes de modelo de sincronização de ordem (oOrder Synchronization Management System Class Library (Single Server)estratégia no sistema concebido neste artigo), de modo que o proprietário da conta de referência (ordem-líder) possa incorporar esta biblioteca de classes modelo em sua própria estratégia diretamente para alcançar a função de sincronização de ordem e posição.
    1. Reduzir um bot real adicional. A última deficiência é que se você usar as 2 ordens passadas, as posições estratégia de sincronização descrita acima. É necessário abrir um bot real adicional para monitorar as posições da conta de referência (conta para líderes de ordem). Soluções: Use a biblioteca de classes de modelo para incorporar funcionalidades na estratégia de conta de referência.

Então o sistema consiste em 2 partes:

  1. Biblioteca de classes do sistema de gestão de sincronização de ordens (Single Server)
  2. Sistema de gestão de sincronização de encomendas (Servidor síncrono)

Uma vez definidas as nossas necessidades, vamos começar a desenhar!

Projeto 1: Biblioteca de classes do sistema de gestão de sincronização de ordens (Single Server)

Observe que esta não é uma estratégia. É uma biblioteca de classe de modelo do FMZ. O conceito de uma biblioteca de classe de modelo pode ser pesquisado na documentação da API do FMZ e não o repetiremos novamente.

Código da biblioteca de classes modelo:

// Global variables
var keyName_label = "label"
var keyName_robotId = "robotId"
var keyName_extendAccessKey = "extendAccessKey"
var keyName_extendSecretKey = "extendSecretKey"
var fmzExtendApis = parseConfigs([config1, config2, config3, config4, config5])
var mapInitRefPosAmount = {}

function parseConfigs(configs) {
    var arr = []
    _.each(configs, function(config) {
        if (config == "") {
            return 
        }
        var strArr = config.split(",")
        if (strArr.length != 4) {
            throw "configs error!"
        }
        var obj = {}
        obj[keyName_label] = strArr[0]
        obj[keyName_robotId] = strArr[1]
        obj[keyName_extendAccessKey] = strArr[2]
        obj[keyName_extendSecretKey] = strArr[3]
        arr.push(obj)
    })
    return arr 
}

function getPosAmount(pos, ct) {
    var longPosAmount = 0
    var shortPosAmount = 0
    _.each(pos, function(ele) {
        if (ele.ContractType == ct && ele.Type == PD_LONG) {
            longPosAmount = ele.Amount
        } else if (ele.ContractType == ct && ele.Type == PD_SHORT) {
            shortPosAmount = ele.Amount
        }
    })
    var timestamp = new Date().getTime()
    return {ts: timestamp, long: longPosAmount, short: shortPosAmount}
}

function sendCommandRobotMsg (robotId, accessKey, secretKey, msg) {
    // https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
    var url = "https://www.fmz.com/api/v1?access_key=" + accessKey + "&secret_key=" + secretKey + "&method=CommandRobot&args=[" + robotId + ',"' + msg + '"]'
    Log(url)
    var ret = HttpQuery(url)
    return ret 
}

function follow(nowPosAmount, symbol, ct, type, delta) {
    var msg = ""
    var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short
    if (delta > 0) {
        // open the position
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // send signals
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // close the position
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("no positions found")
            return 
        }
        // send signals
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
    } else {
        throw "error"
    }
    if (msg) {
        _.each(fmzExtendApis, function(extendApiConfig) {
            var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
            Log("call the CommandRobot interface, ", "label:", extendApiConfig[keyName_label], ",  msg:", msg, ",  ret:", ret)
            Sleep(1000)
        })
    }
}

$.PosMonitor = function(exIndex, symbol, ct) {    
    var ts = new Date().getTime()
    var ex = exchanges[exIndex]
    // judge the type of ex
    var exName = ex.GetName()
    var isFutures = exName.includes("Futures_")
    var exType = isFutures ? "futures" : "spot"
    if (!isFutures) {
        throw "only future-following is supported"
    }

    if (exType == "futures") {
        // caching symbol ct
        var buffSymbol = ex.GetCurrency()
        var buffCt = ex.GetContractType()

        // switch to the corresponding contract pair, contract code
        ex.SetCurrency(symbol)
        if (!ex.SetContractType(ct)) {
            throw "SetContractType failed"
        }

        // monitor positions
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // no initialization data, initialize it
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

        // monitor
        var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
        // calculate the position changes
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

        // detect changes
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // Perform long positions
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform long position-following, changes in volume:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // Perform short positions
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform short position-following, changes in volume:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // Update after performing the order-following operation
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

        // restore symbol ct
        ex.SetCurrency(buffSymbol)
        ex.SetContractType(buffCt)
    } else if (exType == "spot") {
        // Spots
    }
}

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "synchronization of data", 
        "cols" : [], 
        "rows" : []
    }
    // construct the table headers
    tbl.cols.push("monitor the account: refPos-exIndex-symbol-contractType")
    tbl.cols.push(`monitor the position: {"timestamp":xxx,"long positions":xxx,"short positions":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // Write data in
    _.each(mapInitRefPosAmount, function(initRefPosAmount, key) {
        var arr = [key, JSON.stringify(initRefPosAmount)]
        _.each(fmzExtendApis, function(extendApiData) {
            arr.push(extendApiData[keyName_robotId])
        })
        tbl.rows.push(arr)
    })

    return tbl
}

// Example of the strategy call that references the template class library
function main() {
    // Clear all logs
    LogReset(1)

    // Switch to OKEX demo to test
    exchanges[0].IO("simulate", true)

    // Set the contract
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // Timed trading interval
    var tradeInterval = 1000 * 60 * 3        // Trade for every three minutes to observe the order-following signals
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Simulated trading triggers for testing
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Interface functions that use templates
        $.PosMonitor(0, "ETH_USDT", "swap")    // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy  
        var tbl = $.getTbl()
        
        // Display status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

O projeto é muito simples, a biblioteca de classes tem 2 funções funcionais.Order Synchronization Management System Class Library (Single Server)Então a estratégia pode usar as seguintes funções.

  • $. Monitor de posição. O objetivo desta função é monitorar as alterações de posição dos objetos de troca na estratégia e, em seguida, enviar sinais de negociação para o mercado real de bots definidos nos parâmetros do modelo: Biblioteca de classes do Sistema de Gestão de Sincronização de Encomendas (Sistema Único de Servidores).

  • $. GetTbl. Volte para os dados de sincronização monitorizados.

Exemplo de utilização:mainfunção do modelo de biblioteca de classes do sistema de gestão de sincronização de ordens (servidor único):

// Example of the strategy call that references the template class library
function main() {
    // Clear all logs
    LogReset(1)

    // Switch to OKEX demo to test
    exchanges[0].IO("simulate", true)

    // Set the contract
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // Timed trading interval
    var tradeInterval = 1000 * 60 * 3        // Trade for every three minutes to observe the order-following signals
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Simulated trading triggers for testing
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Interface functions by using templates
        $.PosMonitor(0, "ETH_USDT", "swap")    // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy  
        var tbl = $.getTbl()
        
        // Display status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Uma biblioteca de classe de modelo também pode criar um bot real de estratégia por si só, que geralmente é usado para testar a biblioteca de classe de modelo, como o teste do modelo.mainfunção num modelo é amainA função de uma das suas estratégias.

O código de teste é escrito usando a demonstração do OKEX para testar, você precisa configurar a chave de API de demonstração do OKEX no FMZ como uma conta de referência (ordem líder), e ela começa a mudar para demonstração na função principal. Em seguida, defina o par de negociação para ETH_USDT e defina o contrato para swap. Em seguida, ele entra em um loop enquanto. No loop, uma ordem é colocada a cada 3 minutos para simular o gatilho de transações de estratégia.$.PosMonitor(0, "ETH_USDT", "swap")é chamado no loop enquanto, o primeiro parâmetro desta função é passado para 0, o que significa monitorar thes troca objecto trocas[0], monitorar ETH_USDT par de negociação, contrato de swap.$.getTbl()para obter informações do gráfico, usandoLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")para fazer com que os dados do gráfico sejam exibidos na barra de estado.

Então podemos ver que podemos fazer a estratégia ter a capacidade de monitorar as posições de uma certa espécie, e as mudanças de posição para enviar mensagens usando$.PosMonitor(0, "ETH_USDT", "swap")Em uma estratégia que faça referência ao modelo.

Antes do teste, explicaremos o projeto dos parâmetros de estratégia doOrder Synchronization Management System Class Library (Single Server)- Não. Nós acabamos de falar sobre como usar a função de interface de um modelo para atualizar uma estratégia para ter uma função de liderança de ordem. A questão de quem enviar é configurada pelos parâmetros doOrder Synchronization Management System Class Library (Single Server).

img

Podemos ver que há 5 parâmetros, suportando até 5 pushes (pode ser estendido por si mesmo se ele precisa aumentar), os parâmetros padrão são strings vazios, ou seja, não processados.

  • etiqueta Um rótulo para uma conta de sincronização, é usado para definir um rótulo para uma conta com um nome que pode ser definido à vontade.

  • robotId Identificação do robô, a identificação doOrder Synchronous ServerUm bot real criado pelo proprietário da conta sincronizada.

  • accessKey (chave de acesso) Acesso API estendidoChave da FMZ

  • chave secreta Segredo da API estendidaChiave da FMZ

Código temporário do Sistema de Gestão de Sincronização de Encomendas (Servidor Sincrônico):

function main() {
    LogReset(1)
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            // cmd: ETH_USDT,swap,buy,1
            Log("cmd: ", cmd)
        }
        Sleep(1000)
    }
}

img

Podemos ver que o bot real do proprietário da conta sincronizada recebeu a mensagem:ETH_USDT,swap,buy,1- Não. Em seguida, ele nos permitirá fazer o nosso próprio automático ordem-seguindo na próxima etapa com base nos pares tradiing, códigos de contrato, direções de comércio, e quantidade na informação.

Até à data, oOrder Synchronization Management System (Synchronous Server)É o código temporário, continuaremos a explorar o seu desenho na próxima edição.


Relacionados

Mais.