La transacción de cuantificación del círculo de monedas es algo nuevo para mí - que te acerca a la cuantificación del círculo de monedas.

El autor:Un sueño pequeño., Creado: 2021-06-04 10:08:48, Actualizado: 2023-09-21 21:01:06

img

El círculo de monedas cuantificados transacciones de la nueva apariencia que te lleva cerca de la moneda cuantificados.

En el artículo anterior, hicimos juntos una estrategia de red simple, y en este artículo la hemos mejorado y ampliado, ampliando la estrategia a una estrategia de red real de múltiples variedades y poniéndola a prueba en la vida real. El objetivo no es encontrar un "Copo Santo", sino pensar y resolver los problemas de la estrategia de diseño desde el diseño estratégico. Este artículo explica algunas de las experiencias que tuve al diseñar la estrategia, el contenido es un poco complejo y requiere una cierta base para escribir programas.

Pensamiento de diseño basado en necesidades estratégicas

Este artículo, al igual que el anterior, sigue basado en la cuantificación de los inventores.FMZ.COMEn la página web de la organización, se puede leer:

  • Variedad Y lo que quiero decir con esto es que esta estrategia de red no solo haceBTC_USDTY también lo haremos.LTC_USDT/EOS_USDT/DOGE_USDT/ETC_USDT/ETH_USDTPor otra parte, los pares de transacciones en efectivo y las variedades que quieren correr también hacen transacciones en la red.

    ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ La demanda suena simple, el problema surge cuando se diseña.

    • 1, Primero, la adquisición de mercados de varias variedades. Este es el primer problema a resolver. Después de revisar la documentación de la API de los intercambios, descubrí que los intercambios generales ofrecen interfaces de mercados agregados. Está bien, entonces obtenga los datos con una interfaz de mercado agregada.

    • 2, el segundo problema es el de los activos de la cuenta. Debido a que se trata de una estrategia de gran variedad, se debe considerar la gestión de cada transacción por separado de los activos. Y se debe obtener datos y registros de todos los activos a la vez. ¿Por qué obtener datos de activos de la cuenta? ¿Porque necesitas evaluar los activos disponibles al momento de hacer el pedido, o quieres obtenerlos y evaluarlos? ¿También necesitas calcular el beneficio, o tienes que registrar un dato de activos de la cuenta inicial, y luego obtener el dato de activos de la cuenta actual y calcular los beneficios y pérdidas en comparación con la comparación inicial? Afortunadamente, la interfaz de la cuenta de activos de los intercambios también suele devolver datos de activos de todas las monedas, que solo necesitamos obtener una vez y luego procesar los datos.

    • 3, Diseño de parámetros estratégicos. El diseño de parámetros de varias variedades y el diseño de parámetros de una sola variedad son muy diferentes, ya que aunque la lógica de negociación de varias variedades es la misma, es posible que los parámetros de negociación sean diferentes. Por ejemplo, la estrategia de la red, puede hacer que la pareja de operaciones BTC_USDT quiera 0.01 BTC por cada operación, pero si hace DOGE_USDT, si este parámetro (transacción de 0.01 monedas) es obviamente inapropiado, por supuesto, también se puede procesar por la cantidad de USDT. Tal vez otros estudiantes piensen en este tema y luego digan: ¿Puedo establecer más grupos de parámetros para controlar separadamente los parámetros de los diferentes pares de transacciones que debo hacer? ¿Seguiría siendo imposible tener la flexibilidad de satisfacer las necesidades, de establecer varios parámetros? ¿Con tres parámetros, y si voy a hacer cuatro variedades? Por lo tanto, cuando se diseñan los parámetros de la política de múltiples variedades, se debe tener en cuenta plenamente la necesidad de este parámetro de diferenciación. Una solución es diseñar los parámetros como una cadena normal o una cadena JSON. Por ejemplo:

      ETHUSDT:100:0.002|LTCUSDT:20:0.1
      

      En este caso, el resultado es el resultado de un análisis de datos de cada variedad.ETHUSDT:100:0.002En la actualidad, la mayor parte de las transacciones de ETH_USDT se realizan en el mercado de divisas.LTCUSDT:20:0.1El control de la transacción LTC_USDT; el intermediario "gozo" es el divisor.ETHUSDT:100:0.002, donde ETHUSDT indica lo que vas a hacer, 100 es el intervalo de la red, 0.002 es el número de monedas de ETH en cada transacción de la red, oh: el apodo es el de dividir estos datos (por supuesto, estas reglas de parámetros están hechas por el diseñador de la estrategia, puedes diseñar en lo que sea según tus necesidades). Dentro de estas cadenas se contiene la información de los parámetros de cada variedad que se va a hacer, se analizarán en la política, se asignarán variables específicas a la política y se controlará la lógica de transacción de cada variedad. ¿Cómo se analizará?

      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

      Así se resuelven los parámetros, y por supuesto, también puedes usar una cadena JSON directamente, más sencillo.

      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. Persistencia de los datos Las estrategias de combate real y las estrategias de enseñanza también son muy diferentes. La estrategia de enseñanza anterior es solo una prueba inicial de la lógica, el diseño y la estrategia. En combate real, hay más problemas a considerar. Aquí se necesita hacer una conservación permanente de los datos clave durante el funcionamiento del disco real, para poder leerlos al reiniciarlos y continuar funcionando. Se puede usar en la plataforma de intercambio cuantitativo de inventores_G()Funciones, o funciones de operación de la base de datosDBExec()En el caso de las aplicaciones, el usuario puede consultar el documento de la API de FMZ.

      Por ejemplo, diseñamos una función de barrido que usa_G()Funciones que guardan datos de la red.

      var net = null 
      function main() {  // 策略主函数
          // 首先读取储存的net
          net = _G("net")
          
          // ...
      }
      
      function onExit() {
          _G("net", net)
          Log("执行扫尾处理,保存数据", "#FF0000")
      }
      
      function onexit() {    // 平台系统定义的退出扫尾函数,在点击实盘停止时触发执行
          onExit()
      }
      
      function onerror() {   // 平台系统定义的异常退出函数,在程序发生异常时触发执行
          onExit()
      }
      
    • 5. Limitaciones como la precisión de la cantidad, el precio, la cantidad mínima y el monto mínimo de la orden.

      En el sistema de retrospección no hay restricciones tan estrictas sobre el volumen de pedido, la precisión del pedido, etc., pero en tiempo real, los intercambios pueden tener estándares estrictos sobre el precio del pedido, el volumen del pedido, y los límites de cada par de transacciones no son iguales.

      En el caso de las políticas multivariadas, la necesidad es más compleja. En las políticas monovarietales, puedes diseñar un parámetro para especificar información de precisión, etc., pero cuando diseñas políticas multivarietales, obviamente esta información se escribe en parámetros que parecen muy parámetros.

      En este momento, es necesario consultar la documentación de la API del intercambio para ver si existe una interfaz de transacción para la información relevante. Si existe una interfaz, se puede diseñar en la política la precisión de la interfaz de acceso automático para obtener información y configurarla para la información de transacción de la transacción que participa en la transacción (en pocas palabras, qué precisión se solicita automáticamente al intercambio para obtener información y luego se adapta a las variables relacionadas con los parámetros de la política).

    • 6. Adaptación a las diferentes bolsas ¿Por qué ponemos esta pregunta al final? El último problema se debe a que los métodos mencionados anteriormente se adaptan a los datos de interfaces de mercado agregados, acceden a la precisión de las transacciones de los intercambios, acceden a la información de las cuentas y tratan las transacciones por separado, y así sucesivamente. Hay diferencias en las llamadas de interfaces, diferencias en los mecanismos. Para los intercambios de efectivo, las diferencias son ligeras si la política de red se extiende a la versión de futuros. Las diferencias en los mecanismos de los intercambios son mayores. Una solución es diseñar una biblioteca de modelos FMZ. La desventaja de hacerlo es que se requiere escribir una biblioteca de clases de modelos, y en esta plantilla se realiza una diferencia específica para cada intercambio.

Diseñar una biblioteca de modelos

Sobre la base del análisis anterior, se diseñó una librería de modelos para reducir la congruencia entre las estrategias y los mecanismos e interfaces de la bolsa.

Podemos diseñar la biblioteca de clases de plantillas de la siguiente manera (deja de lado parte del 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
}

En la plantilla se puede escribir para intercambios específicos, por ejemplo, con WexApp, la plataforma de 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
            })
        })        
    }
}

La estrategia para usar esta plantilla es simple:

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

Estrategia en la realidad

Basado en la configuración de la plantilla anterior, la estrategia de redacción es muy simple, con aproximadamente 300+ líneas, lo que permite implementar una estrategia de cuadrícula multivariada de divisas digitales.

img

img

Ahora está perdiendo dinero.T_TEl código fuente no está disponible ahora.

Envíe algunos códigos de registro para que los interesados puedan conectar a WexApp y jugar:

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

En el caso de los más de 200 U, al levantarse, se encuentra con un gran movimiento unilateral, sangrado lentamente. La estabilidad también se ha convertido, no se ha movido desde el 27 de mayo hasta ahora, y la red de futuros no se atreve a intentarlo por el momento.


Relacionados

Más.

Cuantificación de la microbiologíaGracias a la torre, cuantificó. Hay farolas en la calle.

Nueve soles¡El jefe de la policía!

Bios de la trayectoriaGracias.

Un sueño pequeño.¡Gracias por el apoyo!

Un sueño pequeño.¡Gracias por el apoyo!