A quantificação do círculo de moedas é algo novo para mim - leva-me mais perto da quantificação do círculo.

Autora:Sonhos pequenos, Criado: 2021-06-04 10:08:48, Atualizado: 2023-09-21 21:01:06

img

A quantificação do círculo de moedas é uma nova forma de se aproximar da quantificação do círculo de moedas.

No artigo anterior, nós começamos a fazer uma estratégia de rede simples, e neste artigo, nós a atualizamos e expandimos para uma estratégia de rede real de várias variedades e testamos a estratégia em tempo real. O objetivo não é encontrar um "Copo Sagrado", mas sim pensar e resolver os vários problemas que surgem no design da estratégia. Este artigo explica algumas das minhas experiências no design da estratégia.

Pensamento de design baseado em necessidades estratégicas

Este artigo, como o anterior, ainda é baseado na quantificação do inventor.FMZ.COMO blogueiro também escreveu sobre o projeto.

  • Variedade E, claro, eu gostaria que a estratégia da grade fosse mais do que isso.BTC_USDTE você pode.LTC_USDT/EOS_USDT/DOGE_USDT/ETC_USDT/ETH_USDTA partir de então, a empresa começou a comercializar a sua própria variedade de raças.

    O que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é que o que eu quero dizer é o que eu quero dizer. A necessidade parece simples, mas o problema surge no momento do projeto.

    • Primeiro, a aquisição de várias variedades de mercados. Este é o primeiro problema a ser resolvido. Depois de consultar a documentação API das bolsas, descobri que as bolsas em geral oferecem interfaces de mercados agregados. OK, vamos obter os dados através da interface de mercado agregado.

    • 2, O segundo problema é o dos ativos da conta. Como é uma estratégia multifacetada, é necessário considerar a gestão de ativos individuais para cada transação. E é necessário obter todos os dados de ativos e registros de uma só vez. O que você precisa fazer é avaliar os ativos disponíveis no momento do pedido, ou você precisa obter e avaliar novamente? Ou você precisa calcular o lucro, ou você precisa registrar um dado inicial de ativos da conta, e então obter os dados atuais de ativos da conta e calcular o lucro e o prejuízo em comparação com o início? A interface de conta de ativos de uma bolsa geralmente também retorna dados de ativos de todas as moedas, que só precisamos obter uma vez e depois processar os dados.

    • 3, Design de parâmetros estratégicos. O design de parâmetros de várias variedades e o design de parâmetros de uma única variedade são muito diferentes, porque as diferentes variedades de negociação, embora tenham a mesma lógica, podem ter diferentes parâmetros de negociação. Por exemplo, a estratégia da grade pode ser fazer um par de negociações BTC_USDT com a expectativa de 0,01 BTC por transação, mas DOGE_USDT é obviamente inadequado se ainda for este parâmetro (transação de 0,01 moedas). Talvez os colegas possam pensar sobre isso e então dizer: "Eu posso definir mais vários conjuntos de parâmetros, separando os parâmetros para controlar os diferentes pares de transações a serem feitos". E se eu fizer quatro variedades, será que seria mais fácil mudar a estratégia, aumentar os parâmetros? Portanto, quando se projetam parâmetros para políticas multivariadas, deve-se levar em consideração as necessidades desses parâmetros de diferenciação. Uma solução é projetar os parâmetros como strings normais ou strings JSON. Por exemplo:

      ETHUSDT:100:0.002|LTCUSDT:20:0.1
      

      A diferença entre os dois tipos de dados é que cada uma delas é uma variedade de dados.ETHUSDT:100:0.002O Bitcoin é o principal instrumento de troca de moeda do mundo.LTCUSDT:20:0.1O LTC_USDT é o par de transações controlado.ETHUSDT:100:0.002, onde o ETHUSDT indica o par de transações que você vai fazer, 100 é o intervalo da grade, 0.002 é o número de moedas de ETH por transação da grade, e o apelido é o de dividir esses dados (claro, essas regras de parâmetros são feitas pelos designers da estratégia, e você pode criar o que quiser). Dentro dessas strings estão as informações dos parâmetros de cada variedade que você vai fazer, para que você possa paralisar essas strings na política, atribuindo especificamente as variáveis da política, para controlar a lógica de transação de cada variedade.

      function main() {
          var net = []  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据
          var params = "ETHUSDT:100:0.002|LTCUSDT:20:0.1"
          var arrPair = params.split("|")
          _.each(arrPair, function(pair) {
              var arr = pair.split(":")
              var symbol = arr[0]              // 交易对名称
              var diff = parseFloat(arr[1])    // 网格间距
              var amount = parseFloat(arr[2])  // 网格下单量
              net.push({symbol : symbol, diff : diff, amount : amount})
          })
          Log("网格参数数据:", net)
      }
      

      img

      O que você pode fazer é resolver os parâmetros e, claro, você também pode usar diretamente a string JSON, que é muito mais simples.

      function main() {        
          var params = '[{"symbol":"ETHUSDT","diff":100,"amount":0.002},{"symbol":"LTCUSDT","diff":20,"amount":0.1}]'
          var net = JSON.parse(params)  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据        
          _.each(net, function(pair) {
              Log("交易对:", pair.symbol, pair)
          })
      }
      

      img

    • 4. Data Persistência A estratégia de combate real e a estratégia de ensino também são muito diferentes. A estratégia de ensino anterior é apenas um teste inicial de estratégia, lógica, design e mais questões a serem consideradas em combate real. No momento em que o disco real é ligado, o disco real pode ser ligado e desligado. Aqui é necessário fazer a conservação permanente de dados críticos durante o funcionamento do disco para que, ao reiniciar, eles possam ser lidos e continuar a funcionar. A plataforma de negociação quantitativa do inventor_G()Funções, ou usar funções de operação de banco de dadosDBExec()O site do FMZ está disponível em: http://www.fmz.com.br

      Por exemplo, nós criamos uma função de varredura,_G()Funções para armazenar dados da grade.

      var net = null 
      function main() {  // 策略主函数
          // 首先读取储存的net
          net = _G("net")
          
          // ...
      }
      
      function onExit() {
          _G("net", net)
          Log("执行扫尾处理,保存数据", "#FF0000")
      }
      
      function onexit() {    // 平台系统定义的退出扫尾函数,在点击实盘停止时触发执行
          onExit()
      }
      
      function onerror() {   // 平台系统定义的异常退出函数,在程序发生异常时触发执行
          onExit()
      }
      
    • 5. Limitações de precisão de quantidade, preço, quantidade e quantidade mínimas.

      O sistema de retrospecção não tem restrições tão severas sobre o valor do pedido, a precisão do pedido, etc., mas em tempo real, cada bolsa pode ter padrões rigorosos para o preço do pedido, o valor do pedido, e cada par de transações não é o mesmo.

      No caso de várias variedades, a necessidade é mais complexa. Em uma política de variedades únicas, você pode criar um parâmetro para especificar informações de precisão, etc., mas quando você cria uma política de variedades, obviamente, essa informação é escrita em parâmetros que parecem muito parâmetros.

      Neste momento, é necessário consultar a documentação do API da bolsa para ver se há interfaces de transações para informações relevantes na documentação da bolsa. Se existirem, pode-se projetar na política informações como precisão de acesso automático, precisão de interface de acesso e configurar para as informações de transações que participam da negociação (simplesmente, precisão de o que o pedido de acesso automático à bolsa é solicitado e depois adaptado às variáveis relacionadas com os parâmetros da política).

    • 6. Adaptação a diferentes exchanges Por que colocar essa questão no final? Como as soluções acima mencionadas levam a este último problema, porque a nossa estratégia planeja usar interfaces de mercado agregadas, acessar a precisão de transações de exchanges e outras adaptações de dados, acessar informações de contas separadamente para processar cada transação, etc. Esses métodos variam muito de acordo com o mercado. Existem diferenças nas chamadas de interface, diferenças no mecanismo. Para o mercado de ações, as diferenças são menores se a estratégia da grade for estendida para versões de futuros. As diferenças no mecanismo de cada mercado são maiores. Uma solução é projetar um catálogo de modelos FMZ. A implementação dessas diferenças é escrita no catálogo de classes. A desvantagem disso é que é necessário escrever um catálogo de tipos de modelos, e que esse modelo é implementado de forma específica para cada troca.

Criar uma biblioteca de modelos

Com base nas análises acima, um conjunto de modelos foi projetado para reduzir a conexão entre a estratégia e os mecanismos e interfaces das bolsas.

Podemos projetar este catálogo de classes de modelos da seguinte forma (excluindo parte do código):

function createBaseEx(e, funcConfigure) {
    var self = {}
    self.e = e 
    
    self.funcConfigure = funcConfigure
    self.name = e.GetName()
    self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
    self.label = e.GetLabel()
    
    // 需要实现的接口
    self.interfaceGetTickers = null   // 创建异步获取聚合行情数据线程的函数
    self.interfaceGetAcc = null       // 创建异步获取账户数据线程的函数
    self.interfaceGetPos = null       // 获取持仓
    self.interfaceTrade = null        // 创建并发下单
    self.waitTickers = null           // 等待并发行情数据 
    self.waitAcc = null               // 等待账户并发数据
    self.waitTrade = null             // 等待下单并发数据
    self.calcAmount = null            // 根据交易对精度等数据计算下单量
    self.init = null                  // 初始化工作,获取精度等数据
    
    // 执行配置函数,给对象配置
    funcConfigure(self)

    // 检测configList约定的接口是否都实现
    _.each(configList, function(funcName) {
        if (!self[funcName]) {
            throw "接口" + funcName + "未实现"
        }
    })
    
    return self
}

$.createBaseEx = createBaseEx
$.getConfigureFunc = function(exName) {
    dicRegister = {
        "Futures_OKCoin" : funcConfigure_Futures_OKCoin,    // OK期货的实现
        "Huobi" : funcConfigure_Huobi,
        "Futures_Binance" : funcConfigure_Futures_Binance,
        "Binance" : funcConfigure_Binance,
        "WexApp" : funcConfigure_WexApp,                    // wexApp的实现
    }
    return dicRegister
}

Em um modelo, pode-se escrever para um mercado específico, por exemplo, usando o WexApp, um disco analógico do FMZ:

function funcConfigure_WexApp(self) {
    var formatSymbol = function(originalSymbol) {
        // BTC_USDT
        var arr = originalSymbol.split("_")
        var baseCurrency = arr[0]
        var quoteCurrency = arr[1]
        return [originalSymbol, baseCurrency, quoteCurrency]
    }

    self.interfaceGetTickers = function interfaceGetTickers() {
        self.routineGetTicker = HttpQuery_Go("https://api.wex.app/api/v1/public/tickers")
    }

    self.waitTickers = function waitTickers() {
        var ret = []
        var arr = JSON.parse(self.routineGetTicker.wait()).data
        _.each(arr, function(ele) {
            ret.push({
                bid1: parseFloat(ele.buy), 
                bid1Vol: parseFloat(-1),
                ask1: parseFloat(ele.sell), 
                ask1Vol: parseFloat(-1),
                symbol: formatSymbol(ele.market)[0],
                type: "Spot", 
                originalSymbol: ele.market
            })
        })
        return ret 
    }

    self.interfaceGetAcc = function interfaceGetAcc(symbol, updateTS) {
        if (self.updateAccsTS != updateTS) {
            self.routineGetAcc = self.e.Go("GetAccount")
        }
    }

    self.waitAcc = function waitAcc(symbol, updateTS) {
        var arr = formatSymbol(symbol)
        var ret = null 
        if (self.updateAccsTS != updateTS) {
            ret = self.routineGetAcc.wait().Info
            self.bufferGetAccRet = ret 
        } else {
            ret = self.bufferGetAccRet
        }
        if (!ret) {
            return null 
        }        
        var acc = {symbol: symbol, Stocks: 0, FrozenStocks: 0, Balance: 0, FrozenBalance: 0, originalInfo: ret}
        _.each(ret.exchange, function(ele) {
            if (ele.currency == arr[1]) {
                // baseCurrency
                acc.Stocks = parseFloat(ele.free)
                acc.FrozenStocks = parseFloat(ele.frozen)
            } else if (ele.currency == arr[2]) {
                // quoteCurrency
                acc.Balance = parseFloat(ele.free)
                acc.FrozenBalance = parseFloat(ele.frozen)
            }
        })
        return acc
    }

    self.interfaceGetPos = function interfaceGetPos(symbol, price, initSpAcc, nowSpAcc) {
        var symbolInfo = self.getSymbolInfo(symbol)
        var sumInitStocks = initSpAcc.Stocks + initSpAcc.FrozenStocks
        var sumNowStocks = nowSpAcc.Stocks + nowSpAcc.FrozenStocks
        var diffStocks = _N(sumNowStocks - sumInitStocks, symbolInfo.amountPrecision)
        if (Math.abs(diffStocks) < symbolInfo.min / price) {
            return []
        }
        return [{symbol: symbol, amount: diffStocks, price: null, originalInfo: {}}]
    }

    self.interfaceTrade = function interfaceTrade(symbol, type, price, amount) {
        var tradeType = ""
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeType = "bid"
        } else {
            tradeType = "ask"
        }
        var params = {
            "market": symbol,
            "side": tradeType,
            "amount": String(amount),
            "price" : String(-1),
            "type" : "market"
        }
        self.routineTrade = self.e.Go("IO", "api", "POST", "/api/v1/private/order", self.encodeParams(params))
    }

    self.waitTrade = function waitTrade() {
        return self.routineTrade.wait()
    }

    self.calcAmount = function calcAmount(symbol, type, price, amount) {
        // 获取交易对信息
        var symbolInfo = self.getSymbolInfo(symbol)
        if (!symbol) {
            throw symbol + ",交易对信息查询不到"
        }
        var tradeAmount = null 
        var equalAmount = null  // 记录币数
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeAmount = _N(amount * price, parseFloat(symbolInfo.pricePrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min)
                return false 
            }
            equalAmount = tradeAmount / price
        } else {
            tradeAmount = _N(amount, parseFloat(symbolInfo.amountPrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min / price) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min / price)
                return false 
            }
            equalAmount = tradeAmount
        }
        return [tradeAmount, equalAmount]
    }

    self.init = function init() {   // 自动处理精度等条件的函数
        var ret = JSON.parse(HttpQuery("https://api.wex.app/api/v1/public/markets"))
        _.each(ret.data, function(symbolInfo) {
            self.symbolsInfo.push({
                symbol: symbolInfo.pair,
                amountPrecision: parseFloat(symbolInfo.basePrecision),
                pricePrecision: parseFloat(symbolInfo.quotePrecision),
                multiplier: 1,
                min: parseFloat(symbolInfo.minQty),
                originalInfo: symbolInfo
            })
        })        
    }
}

A estratégia é simples: use este modelo:

function main() {
    var fuExName = exchange.GetName()
    var fuConfigureFunc = $.getConfigureFunc()[fuExName]
    var ex = $.createBaseEx(exchange, fuConfigureFunc)

    var arrTestSymbol = ["LTC_USDT", "ETH_USDT", "EOS_USDT"]
    var ts = new Date().getTime()
    
    // 测试获取行情
    ex.goGetTickers()
    var tickers = ex.getTickers()
    Log("tickers:", tickers)
    
    // 测试获取账户信息
    ex.goGetAcc(symbol, ts)
    
    _.each(arrTestSymbol, function(symbol) {        
        _.each(tickers, function(ticker) {
            if (symbol == ticker.originalSymbol) {
                // 打印行情数据
                Log(symbol, ticker)
            }
        })

        // 打印资产数据
        var acc = ex.getAcc(symbol, ts)
        Log("acc:", acc.symbol, acc)
    })
}

Estratégia real

A estratégia de criação baseada no modelo acima é muito simples, com cerca de 300 linhas, para realizar uma estratégia de grelha multi-variedade de moeda digital.

img

img

Perda de dinheiroT_TO código-fonte está temporariamente bloqueado.

O site WexApp é uma plataforma de conteúdo virtual que permite que usuários possam acessar o site através de um e-mail, enviando alguns códigos de registro, para que os interessados possam usar o aplicativo:

购买地址: https://www.fmz.com/m/s/284507
注册码: 
adc7a2e0a2cfde542e3ace405d216731
f5db29d05f57266165ce92dc18fd0a30
1735dca92794943ddaf277828ee04c27
0281ea107935015491cda2b372a0997d
1d0d8ef1ea0ea1415eeee40404ed09cc

A maior vantagem de uma rede de compras é que você pode dormir! A estabilidade também se acumula, não se moveu desde 27 de maio e a rede de futuros não se atreve a tentar por enquanto.


Relacionados

Mais.

Quantificação da microbiologiaGraças ao edifício, quantidade de luzes acesas na rua.

Nove sóisO Presidente da Câmara!

Biologia da órbitaObrigado.

Sonhos pequenosObrigado pelo apoio!

Sonhos pequenosObrigado pelo apoio!