avatar of 发明者量化-小小梦 发明者量化-小小梦
Seguir Mensajes Privados
4
Seguir
1271
Seguidores

Hablando sobre la experiencia de desarrollar estrategias comerciales

Creado el: 2019-08-06 17:15:13, Actualizado el: 2023-10-20 20:06:49
comments   4
hits   3417

Hablando sobre la experiencia de desarrollar estrategias comerciales

Hablando sobre la experiencia de desarrollar estrategias comerciales

El propósito de este artículo es compartir algunas experiencias y consejos en el desarrollo de estrategias, que puedan permitir a los lectores comprender rápidamente la experiencia en el desarrollo de estrategias comerciales. Cuando surgen problemas detallados similares en el diseño de una estrategia, se pueden concebir inmediatamente soluciones razonables. La plataforma de comercio cuantitativo Inventor se utiliza como plataforma para explicación, prueba y práctica. Lenguaje de programación de políticas: JavaScript Mercado comercial: mercado de activos blockchain (BTC, ETH, etc.)

  • ## Adquisición y procesamiento de datos

Por lo general, dependiendo de la lógica de la estrategia, es posible utilizar las siguientes interfaces diferentes para obtener datos del mercado, porque la lógica comercial de la estrategia generalmente está impulsada por los datos del mercado (por supuesto, hay algunas estrategias que no miran el mercado). , como las estrategias de inversión fija).

  • GetTicker: Obtenga información de ticks en tiempo real. Generalmente se utiliza para obtener rápidamente el último precio actual, el precio de compra y el precio de venta.

  • GetDepth: Obtenga cotizaciones de profundidad del libro de órdenes. Generalmente se utiliza para obtener el precio de cada nivel y el tamaño de la orden. Se utiliza para estrategias de cobertura, estrategias de creación de mercado, etc.

  • GetTrade: Obtenga los últimos registros de transacciones en el mercado. Generalmente se utiliza para analizar el comportamiento del mercado en un período corto de tiempo y analizar los micro cambios del mercado. Generalmente se utiliza en estrategias de alta frecuencia y estrategias algorítmicas.

  • GetRecords: Obtenga datos de la línea K del mercado. Se utiliza a menudo en estrategias de seguimiento de tendencias. Se utiliza para calcular indicadores.

  • Tolerancia a fallos

    Al diseñar estrategias, los novatos generalmente ignoran diversas situaciones de error y creen intuitivamente que los resultados de cada vínculo de la estrategia están predeterminados. Pero en realidad no es así. Al solicitar datos de mercado durante el funcionamiento del programa de estrategia, se pueden encontrar diversas situaciones inesperadas. Por ejemplo, algunas interfaces de mercado devuelven datos anormales:

    var depth = exchange.GetDepth()
    
    
    // depth.Asks[0].Price < depth.Bids[0].Price      卖一价格低于了买一价格,这种情况不可能存在于盘面上,
    //                                                因为卖出的价格低于买入的价格,必定已经成交了。
    // depth.Bids[n].Amount = 0                       订单薄买入列表第n档,订单量为0
    // depth.Asks[m].Price = 0                        订单薄卖出列表第m档,订单价格为0
    

    O exchange.GetDepth() devuelve directamente un valor nulo.

    Hay muchas situaciones extrañas como esta. Por lo tanto, se deben realizar tratamientos correspondientes a estos problemas previsibles, y este tipo de tratamiento se llama procesamiento tolerante a fallos.

    El enfoque habitual de tolerancia a fallos es descartar datos y recuperarlos nuevamente.

    Por ejemplo:

    function main () {
        while (true) {
            onTick()
            Sleep(500)
        }
    }
    
    
    function GetTicker () {
        while (true) {
            var ticker = exchange.GetTicker()
            if (ticker.Sell > ticker.Buy) {       // 以 检测卖一价格是不是小于买一价这个错误的容错处理为例,
                                                  // 排除这个错误,当前函数返回 ticker 。
                return ticker
            }
            Sleep(500)
        }
    }
    
    
    function onTick () {
        var ticker = GetTicker()                  // 确保获取到的 ticker 不会存在 卖一价格小于买一价格这种数据错误的情况。
        // ...  具体的策略逻辑
    }
    

    Otros procesos previsibles tolerantes a fallos se pueden gestionar de forma similar. El principio de diseño es que nunca se deben utilizar datos incorrectos para impulsar la lógica de la estrategia.

  • Uso de datos de la línea K

    Adquisición de datos de la línea K, llamar:

    var r = exchange.GetRecords()
    

    Los datos de la línea K obtenidos son una matriz como la siguiente:

    [
        {"Time":1562068800000,"Open":10000.7,"High":10208.9,"Low":9942.4,"Close":10058.8,"Volume":6281.887000000001},
        {"Time":1562072400000,"Open":10058.6,"High":10154.4,"Low":9914.5,"Close":9990.7,"Volume":4322.099},
        ...
        {"Time":1562079600000,"Open":10535.1,"High":10654.6,"Low":10383.6,"Close":10630.7,"Volume":5163.484000000004}
    ]
    

    Puedes ver que cada llave{}Incluye tiempo, precio de apertura (open), precio más alto (high), precio más bajo (low), precio de cierre (close) y volumen de negociación (volumen). Esto es un candelabro. Generalmente, los datos de la línea K se utilizan para calcular indicadores, como el promedio móvil MA, MACD, etc. Ingrese los datos de la línea K como parámetros (datos de la materia prima), luego configure los parámetros del indicador y calcule la función de los datos del indicador, a lo que llamamos función del indicador. Hay muchas funciones de indicador en la plataforma de comercio cuantitativo Inventor.

    Por ejemplo, cuando calculamos el indicador de media móvil, en base a los diferentes períodos de los datos de la línea K que pasamos, calculamos la media móvil del período correspondiente. Por ejemplo, si se pasan los datos diarios de la línea K (una barra de la línea K representa un día), el indicador calculado es el promedio móvil diario. De manera similar, si los datos de la línea K que se pasan a la función indicadora de promedio móvil son un período de 1 hora, entonces el indicador calculado es el promedio móvil de 1 hora.

    Por lo general, cuando calculamos indicadores, solemos pasar por alto un problema. Si quiero calcular el indicador de media móvil de 5 días, primero preparamos los datos de la línea K diaria:

    var r = exchange.GetRecords(PERIOD_D1)  // 给GetRecords 函数传入参数 PERIOD_D1就是指定获取日K线,
                                            // 具体函数使用可以参看:https://www.fmz.com/api#GetRecords
    

    Con los datos diarios de la línea K, podemos calcular el indicador de media móvil. Si queremos calcular la media móvil de 5 días, debemos establecer el parámetro indicador de la función indicadora en 5.

    var ma = TA.MA(r, 5)        // TA.MA() 就是指标函数,用来计算均线指标,第一个参数设置刚才获取的日K线数据r,
                                // 第二个参数设置5,计算出来的就是5日均线,其它指标函数同理。
    

    Hemos pasado por alto un problema potencial. ¿Qué sucede si el número de barras de la línea K en los datos de la línea K del día r es menor que 5? ¿Podemos calcular un indicador válido de promedio móvil de 5 días? La respuesta es definitivamente no. Porque el indicador de media móvil sirve para encontrar el promedio de los precios de cierre de un cierto número de barras de la línea K.

    Hablando sobre la experiencia de desarrollar estrategias comerciales

    Por lo tanto, antes de utilizar los datos de la línea K y las funciones del indicador para calcular los datos del indicador, es necesario determinar si el número de columnas de la línea K en los datos de la línea K cumple las condiciones para el cálculo del indicador (parámetros del indicador).

    Por lo tanto, antes de calcular la media móvil de 5 días, es necesario hacer un juicio. El código completo es el siguiente:

    function CalcMA () {
        var r = _C(exchange.GetRecords, PERIOD_D1)     // _C() 是容错函数,目的就是避免 r 为 null , 具体可以查询文档:https://www.fmz.com/api#_C
        if (r.length > 5) {
            return TA.MA(r, 5)                         // 用均线指标函数 TA.MA 计算出均线数据,做为函数返回值,返回。
        }
    
    
        return false 
    }
    
    
    function main () {
        var ma = CalcMA()
        Log(ma)
    }
    

    Hablando sobre la experiencia de desarrollar estrategias comerciales

    Las pruebas retrospectivas muestran: [null,null,null,null,4228.7,4402.9400000000005, … ]

    Se puede observar que los primeros cuatro indicadores de promedio móvil de 5 días calculados son nulos, porque el número de columnas de la línea K es menor que 5 y no se puede calcular el promedio. A partir de la quinta vela se puede calcular.

  • Consejos para evaluar las actualizaciones de la línea K

    Cuando escribimos algunas estrategias, a menudo surge el escenario en el que necesitamos procesar algunas operaciones o imprimir algunos registros cuando se completa cada ciclo de la línea K. ¿Cómo logramos esta funcionalidad? Para los principiantes que no tienen experiencia en programación, es posible que no se les ocurra qué mecanismo utilizar para solucionarlo. Aquí te daremos algunos consejos directamente.

    Podemos juzgar que un ciclo de columna de la línea K se completa al comenzar con el atributo de tiempo en los datos de la línea K. Cada vez que obtenemos datos de la línea K, juzgamos el atributo de tiempo en los datos de la última columna de la línea K. de estos datos de la línea K. Si este valor de atributo ha cambiado. Si ha cambiado, significa que se ha generado una nueva columna de la línea K (lo que demuestra que el ciclo de columna de la línea K anterior de la columna de la línea K recién generada ha se ha completado). Si no ha cambiado, significa que no hay Se genera una nueva vela (aún no se ha completado el último ciclo de velas actual).

    Entonces necesitamos una variable para registrar la hora de la última columna de velas de los datos de velas.

    var r = exchange.GetRecords()
    var lastTime = r[r.length - 1].Time       // lastTime 用来记录最后一根K线柱的时间。
    

    En aplicaciones prácticas, la estructura suele ser así:

    function main () {
        var lastTime = 0
        while (true) {
            var r = _C(exchange.GetRecords)
            if (r[r.length - 1].Time != lastTime) {
                Log("新K线柱产生")
                lastTime = r[r.length - 1].Time      // 一定要更新 lastTime ,这个至关重要。
    
    
                // ... 其它处理逻辑
                // ...
            }
    
    
            Sleep(500)
        }
    }
    

    Hablando sobre la experiencia de desarrollar estrategias comerciales

    Se puede ver que en el backtest, el período de la línea K se establece en el día (la función exchange.GetRecords se llama sin especificar parámetros, y el período de la línea K establecido según el backtest es el parámetro predeterminado). Siempre que un Aparece una nueva columna de la línea K y se imprime un registro A.

  • Cálculos numéricos

    • ### Calcular el tiempo que se tarda en acceder a la interfaz de intercambio

    Si desea mostrar o controlar el tiempo que tarda una estrategia en acceder a la interfaz del exchange, puede utilizar el siguiente código:

    function main () {
        while (true) {
            var beginTime = new Date().getTime()
            var ticker = exchange.GetTicker()
            var endTime = new Date().getTime()
    
    
            LogStatus(_D(), "GetTicker() 函数耗时:", endTime - beginTime, "毫秒")
            Sleep(1000)
        } 
    }
    

    En pocas palabras, la marca de tiempo registrada después de llamar a la función GetTicker se resta de la marca de tiempo antes de la llamada para calcular la cantidad de milisegundos que han pasado, es decir, el tiempo que tarda la función GetTicker en ejecutarse y devolver el resultado.

    • ### Utilice Math.min / Math.max para establecer límites superiores e inferiores en los valores

    Si desea un límite superior numérico, generalmente utiliza Math.min para limitar

    Por ejemplo, al realizar una orden de venta, el monto de la orden no debe ser mayor que la cantidad de monedas en la cuenta. Porque si es mayor al número de monedas disponibles en la cuenta se reportará un error al realizar un pedido.

    Generalmente se controla así: Por ejemplo, usted planea colocar una orden de venta por 0,2 monedas.

    var planAmount = 0.2
    var account = _C(exchange.GetAccount)
    var amount = Math.min(account.Stocks, planAmount)
    

    Esto garantiza que el monto del pedido a realizar no exceda la cantidad de monedas disponibles en la cuenta.

    De manera similar, Math.max se utiliza para garantizar un límite inferior para un valor. ¿A qué tipo de escenarios suele aplicarse esto? En general, los exchanges tienen un límite de cantidad mínima de pedido para ciertos pares de negociación. Si la cantidad del pedido es inferior a esta cantidad mínima, el pedido será rechazado. De esta manera el pedido fracasará. Supongamos que la cantidad mínima de pedido para BTC suele ser 0,01. A veces, la estrategia comercial puede calcular que la cantidad del pedido es menor a 0,01, por lo que podemos usar Math.max para garantizar la cantidad mínima del pedido.

    • ### Control de precisión de cantidad y precio de pedidos

    Puede ser utilizado_Función N() o función SetPrecision para controlar la precisión.

    La función SetPrecision() solo debe configurarse una vez y el sistema truncará automáticamente los decimales sobrantes en los valores de cantidad y precio del pedido.

    _La función N() se utiliza para truncar un valor a una cierta cantidad de decimales (control de precisión)

    Por ejemplo:

    var pi = _N(3.141592653, 2)
    Log(pi)
    

    El valor de pi se trunca a 2 decimales, que es: 3,14

    Consulte la documentación de la API para obtener más detalles.

  • Algunas configuraciones lógicas

    • ### Sincronización: realizar algunas operaciones en un período de tiempo determinado

    Puede utilizar este mecanismo para utilizar el método de detección de marca de tiempo para determinar la marca de tiempo actual menos la marca de tiempo de la última vez que se completó la tarea programada y calcular el tiempo transcurrido en tiempo real. Cuando el tiempo transcurrido excede un cierto período de tiempo establecido Después de eso , se ejecuta la nueva operación.

    Por ejemplo, se utiliza en estrategias de inversión fija.

    var lastActTime = 0
    var waitTime = 1000 * 60 * 60 * 12   // 一天的毫秒数
    function main () {
        while (true) {
            var nowTime = new Date().getTime()
            if (nowTime - lastActTime > waitTime) {
                Log("执行定投")
                // ... 具体的定投操作,买入操作。
    
    
                lastActTime = nowTime
            }
    
    
            Sleep(500)
        }
    }
    

    Este es un ejemplo sencillo.

    • ### Diseño de mecanismos automáticos de recuperación de estrategias

    Al utilizar la función cuantificada _G() del inventor y la función de guardar y salir, es muy conveniente diseñar una estrategia para salir y guardar el progreso, y reiniciar para restaurar automáticamente el estado.

    var hold = {
        price : 0, 
        amount : 0,
    }
    
    
    function main () {
        if (_G("hold")) {
            var ret = _G("hold")
            hold.price = ret.price
            hold.amount = ret.amount
            Log("恢复 hold:", hold)
        }
    
    
        var count = 1
        while (true) {
            // ... 策略逻辑
            // ... 策略运行中,可能开仓,交易,把开仓的持仓价格赋值给 hold.price ,开仓的数量赋值给 hold.amount,用以记录持仓信息。
    
    
            hold.price = count++     // 模拟一些数值
            hold.amount = count/10   // 模拟一些数值
    
    
            Sleep(500)
        }
    }
    
    
    function onexit () {    // 点击机器人上的停止按钮,会触发执行这个函数,执行完毕机器人停止。
        _G("hold", hold)
        Log("保存 hold:", JSON.stringify(hold))
    }
    

    Hablando sobre la experiencia de desarrollar estrategias comerciales

    Se puede observar que cada vez que se detiene el robot, se guardan los datos en el objeto de retención. Cada vez que se reinicia, se leen los datos y el valor de retención se restaura al estado en que se encontraba en la detención anterior. Por supuesto, lo anterior es un ejemplo simple. Si se utiliza en una estrategia real, debe diseñarse de acuerdo con los datos clave que se deben restaurar en la estrategia (generalmente información de la cuenta, posiciones, valores de ganancias, direcciones de operaciones, etc.). .). Por supuesto, también puedes establecer algunas condiciones para determinar si deseas restaurar.

Los anteriores son algunos consejos para desarrollar estrategias. ¡Espero que sean útiles para principiantes y desarrolladores de estrategias! ¡La forma más rápida de mejorar es practicar! Les deseo a todos que sigan obteniendo ganancias.