3
Seguir
1444
Seguidores

Tutorial básico de redacción de estrategias para la plataforma cuantitativa FMZ (lectura obligatoria)

Creado el: 2019-08-13 17:47:27, Actualizado el: 2021-08-06 10:29:46
comments   33
hits   69033

[TOC] Este tutorial contiene el conocimiento inicial de la escritura de la estrategia, incluyendo la introducción de la API, retroalimentación, gráficos, etc. Después de aprender este tutorial básico, el usuario será capaz de manejar la API básica y escribir una estrategia de disco duro estable. Antes de aprender este tutorial, es necesario aprenderIntroducción a la plataforma de cuantificación de los inventores de FMZ 。

La versión anterior del tutorial:Inventor de cuantificar las estrategias de FMZ.COM para escribir un manual de uso completo 2.0El tutorial incluye una lista de muchos de los post indexados, también se recomienda que los busques.

Preliminares para la elaboración de la estrategia

Descripción de la API

La interfaz de programación (API, por sus siglas en inglés) es un tipo de interfaz de programación (API, por sus siglas en inglés) en la que un programa se conecta a través de una API y un intercambio para realizar automáticamente la compra y venta de acuerdo con la intención de diseño o para realizar otras funciones.

Actualmente, los intercambios de monedas digitales tienen dos protocolos de interfaz principales: REST y Websocket. El protocolo REST requiere un acceso por cada vez que se obtienen datos. Por ejemplo, la API de la bolsa de simulación wex.app, abierta directamente en el navegador https://api.wex.app/api/v1/public/ticker?market=BTC_USDT, obtiene los resultados:

{"data:{"buy":"11351.73","high":"11595.77","last":"11351.85","low":"11118.45","open":"11358.74","quoteVol":"95995607137.00903936","sell":"11356.02","time":1565593489318,"vol":"3552.5153"}}

Esto permite ver el estado actual de la operación con el par BTC_USDT, que cambia cada vez que se actualiza.market=A continuación, los parámetros específicos de la pareja de transacciones, que se pueden modificar para obtener otros datos de la pareja de transacciones. Para las interfaces públicas, como el mercado, todos pueden acceder, por lo que no se requiere verificación, mientras que algunas interfaces, como las órdenes y las cuentas de acceso, requieren la identificación del usuario, en cuyo caso se debe firmar con la API-KEY. Websocket es un modelo de suscripción, después de enviar el contenido que necesita la suscripción, la bolsa enviará los datos actualizados al programa, sin necesidad de volver a visitarlo cada vez, por lo que es más eficiente.

La plataforma de comercio cuantitativo FMZ envuelve la interfaz REST de las distintas bolsas, utiliza una forma unificada de llamar y formato de datos, lo que hace que la programación de estrategias sea más sencilla y general. En la plataforma FMZ se puede soportar Websocket, que se describirá en detalle en el siguiente tutorial.

Diferentes lenguajes

La mayoría de la documentación de la API de la plataforma FMZ se basa en JavaScript, pero debido al envase, no hay diferencias entre los diferentes idiomas, solo hay que tener en cuenta los problemas gramaticales. C ++ es un poco especial, y los tutoriales posteriores tendrán una introducción especializada. Debido a que Js es más simple y no hay problemas de compatibilidad, se recomienda que los principiantes lo usen. La plataforma cuantitativa de FMZ admite Python completo, se puede instalar libremente en varios paquetes y se recomienda el uso de una cierta base de programación.

Puesto que hay diferentes versiones de Python, se puede especificar al inicio del programa, como#!Python2,#!Python3Nota: JavaScript ha sido recientemente actualizado para la gramática de ES6, los interesados pueden leerlo. A continuación se muestra el código de Python y Javascript para las mismas funciones, solo se pueden ver las diferencias gramaticales, por lo que la documentación de la API solo da ejemplos de Javascript, y este tutorial también incluirá casos de uso especiales de Python.

#python代码
def main():
    while True:
        Log(exchange.GetAccount().Balance)
        Sleep(2000)
#相应的Js代码
function main(){
    while(true){
        Log(exchange.GetAccount().Balance)
        Sleep(2000)
    }
}

Recursos recomendados

  • La documentación de la API de la plataforma FMZ, que en este tutorial no se describe en detalle cada interfaz, se puede consultar en este documento: https://www.fmz.com/api
  • Si quieres recibir señales de tradingview, puedes comprar y comprar en FMZ en este artículo: https://www.fmz.com/digest-topic/5533
  • Introducción rápida a Javascript, Python, y otras estrategias sencillas que no requieren una gramática compleja, solo requieren dominar algunos conceptos básicos, y se puede aprender a programar mientras se aprende este tutorial: https://www.fmz.com/bbs-topic/382 https://www.fmz.com/bbs-topic/417
  • Documentación en lenguaje Mac, para estrategias de tendencias, el lenguaje Mac es muy conveniente.
  • Un ejemplo de llamada en C++ para aquellos interesados en C++, pero no recomendado por ser un lenguaje interpretativo y difícil de debujar: https://www.fmz.com/strategy/61533
  • El curso de comercio cuantitativo de monedas digitales en la clase de NetEase Cloud, producto oficial de FMZ, solo cuesta 20 yuanes, el contenido es detallado, de poco a poco, adecuado para los principiantes.Enlace al curso
  • Algunas estrategias de enseñanza, adecuadas para el inicio de la etapa, mientras aprende estrategias básicas de margen: https://www.fmz.com/square/s:tag:%E6%95%99%E5%AD%A6/1
  • El código fuente de la estrategia detalla: https://www.fmz.com/bbs/s:tag: %E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%901

Herramientas de depuración

La plataforma de cuantificación FMZ proporciona una herramienta de depuración para la interfaz de API de depuración, https://www.fmz.com/m/debug 。 La herramienta de depuración solo admite JavaScript y solo se ejecuta durante un período de tiempo, sin necesidad de crear un disco duro para poder depurar la interfaz de la bolsa。 Los datos de retorno se devolverán como resultado y el código de la herramienta de depuración no se guardará。 En este tutorial, se puede usar la herramienta de depuración para realizar pruebas al mismo tiempo。 Tutorial básico de redacción de estrategias para la plataforma cuantitativa FMZ (lectura obligatoria)

Arquitectura de las políticas

La excepción es que, al igual que los programas normales, los programas de estrategia se ejecutan en orden de código y deben tener una función principal. Dado que la estrategia debe ejecutarse ininterrumpidamente, generalmente se requiere un ciclo más el tiempo de inactividad.

Otras funciones con funciones especiales son las siguientes:

  • onexit() La función de salida normal tiene un tiempo máximo de ejecución de 5 minutos, y puede no declararse, y si se excede el tiempo, se notifica un error de interrupción. Se puede usar para guardar algunos resultados al salir del proceso.
  • onerror() Función de salida por excepción, que tiene un tiempo máximo de ejecución de 5 minutos, puede no ser declarada。
  • init() Como función de inicialización, la política se llama automáticamente cuando comienza a ejecutarse, pero no se declara.
function onTick(){
   var ticker = exchange.GetTicker()
   var account = exchange.GetAccount()
    //在这里写策略逻辑,将会每6s调用一次
}
function main(){
    while(true){
        onTick()
        Sleep(6000)
    }
}

En el ejemplo anterior, si un error de acceso a la red puede causar que la política se detenga directamente, si desea una política similar a la de reinicio automático que no se detendrá, puede volver a usar la política de disco duro con el ciclo principal tolerante a errores try catch (no use try). Por supuesto, solo se recomienda esta operación cuando la política es estable, de lo contrario, no se reportarán todos los errores, y será difícil eliminar los problemas de la política.

function onTick(){
   var ticker = exchange.GetTicker()
   var account = exchange.GetAccount()
    //在这里写策略逻辑,将会每6s调用一次
}
function main(){
    try{
        while(true){
           onTick()
           Sleep(6000)
       }
    }catch(err){
        Log(err)
    }
}

Introducción a las API de las bolsas

Intercambio y configuración de pares de intercambio

Cuando se llama a cualquier API relacionada con una bolsa, se necesita especificar la bolsa y el par de transacciones.exchangeEn nombre de este objeto, comoexchange.GetTicker()Lo que se obtiene es el ticker de la bolsa de valores de esta pareja.

La plataforma de FMZ admite la adición simultánea de varios pares de intercambio, como BTC y ETH de una misma cuenta de intercambio, o BTC y ETH de otra. Tenga en cuenta que diferentes cuentas de la misma bolsa también se pueden agregar al mismo tiempo, según la distinción de etiquetas que se agregan al sitio web de FMZ.exchangesLos conjuntos se representan en la siguiente forma:exchanges[0]exchanges[1]…y así sucesivamente. El formato del par de transacciones es:BTC_USDTEl BTC es la moneda de cambio y el USDT es la moneda de cambio.

Tutorial básico de redacción de estrategias para la plataforma cuantitativa FMZ (lectura obligatoria)

Obviamente, si operamos con muchos pares de transacciones, este método puede ser problemático, pero podemos usar SetCurrency para intercambiar pares de transacciones, comoexchange.SetCurrency("BTC_USDT")En ese momento,exchangeEl par de transacciones vinculadas se convierte enBTC_USDTEl cambio de par será válido hasta la próxima vez que se llame para cambiar el par.Nota de retroalimentación para el soporte de los pares de intercambioA continuación un ejemplo concreto.

var symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT"]
var buyValue = 1000
function main(){
  for(var i=0;i<symbols.length;i++){
      exchange.SetCurrency(symbols[i])
      var ticker = exchange.GetTicker()
      var amount = _N(buyValue/ticker.Sell, 3)
      exchange.Buy(ticker.Sell, amount)
      Sleep(1000)
  }
}

Interfaces abiertas para acceder a información

Como los ejemplos mencionados anteriormente, las interfaces de mercado son generalmente interfaces públicas, accesibles para todos. Las interfaces de mercado habituales son: obtener ticker de mercado, obtener profundidad de profundidad, obtener K linerecords, obtener registro de transacción trades. El mercado es la base de la estrategia para realizar juicios de transacción, que se presentará a continuación, y es mejor que pueda probarlo por sí mismo en la herramienta de desinstalación.

Las interfaces generalmente tienenInfoCampo, que representa la cadena de datos original devuelta por el intercambio, que se puede utilizar para complementar la información adicional que se necesita analizar antes, usando JavaScriptJSON.parse()En Python, la librería json es utilizada.TimeLos campos indican el tiempo de la solicitud, que se puede utilizar para determinar el retraso.

El uso de interfaces de API en el disco real es posible si el acceso falla y se devuelvenullEl regreso de PythonNoneLa tolerancia a errores es muy importante, ya que el uso de estos datos puede causar errores y detener el disco duro.

GetTicker

Obtener la tendencia actual del mercado, probablemente sea la interfaz más utilizada, se puede consultar el precio de transacción anterior, el precio de compra y venta, el volumen de transacción reciente, etc. Se puede determinar el precio de la transacción basándose en la información del ticker antes de volver a ordenar. Un ejemplo de devolución en disco duro{"Info:{}, "High":5226.69, "Low":5086.37,"Sell":5210.63, "Buy":5208.5, "Last":5208.51, "Volume":1703.1245, "OpenInterest":0, "Time":1554884195976}

function main() {
    var ticker = exchange.GetTicker()
    Log(ticker) //在调试工具中 return ticker 。可以看到具体的结果。
    Log('上次成交价: ',ticker.Last, '买一价: ', ticker.Buy)
}

GetDepth

Obtenga información sobre la profundidad de la lista de colgantes. Aunque GetTicker contiene una lista de compra y venta, si desea consultar más profundamente, puede usar esta interfaz, generalmente puede consultar las siguientes 200 listas de colgantes. Puede usar esta interfaz para calcular el precio de impacto. A continuación se muestra un resultado de devolución real.

{
    "Info":null,
    "Asks":[
        {"Price":5866.38,"Amount":0.068644},
        {"Price":5866.39,"Amount":0.263985},
        ......
        ]
    "Bids":[
        {"Price":5865.13,"Amount":0.001898},
        {"Price":5865,"Amount":0.085575},
        ......
        ],
    "Time":1530241857399
}

Ejemplos de la utilización de acceso profundo a las cuentas:

function main() {
    var depth = exchange.GetDepth()
    Log('买一价个: ', depth.Bids[0].Price, '卖一价格: ', depth.Asks[0].Price)
}

GetRecords

Obtenga la línea K, una de las interfaces más usadas, que puede devolver información de precios de mayor duración a la vez, para calcular la base de varios indicadores. El ciclo de la línea K no se puede especificar si no se especifica el ciclo predeterminado que se usará al agregar el disco. La longitud de la línea K no se puede especificar, aumenta con el tiempo y se acumula, hasta 2000 raíces, con una primera llamada de aproximadamente 200 raíces (… diferentes intercambios devuelven diferente).

exchange.SetMaxBarLen(Len)Se puede configurar el número de líneas K que se obtienen por primera vez (es compatible con algunos exchanges) y el número máximo de líneas K que se pueden obtener.Por ejemplo:exchange.SetMaxBarLen(500)

GetRecords puede especificar el período: PERIOD_M1:1 minutos, PERIOD_M5:5 minutos, PERIOD_M15:15 minutos, PERIOD_M30:30 minutos, PERIOD_H1:1 horas, PERIOD_D1:1 días. Se utiliza específicamente paraexchange.GetRecords(PERIOD_M1)Después de la actualización de los nuevos administradores, soportará el ciclo de personalización, el segundo de ciclo de transmisión directa como parámetro, la personalización a nivel de minuto se sintetizará en función de la línea K de 1 minuto, la línea K inferior a 1 minuto se sintetizará a través de GetTrades (), los futuros de mercancías se sintetizarán en función de tick,En el tutorial se encontrará algo similar.PERIOD_M1Las variables en mayúsculas, que son las variables globales por defecto de FMZ, pueden ser registradas por los interesados en su propio valor específico, que normalmente se usa directamente.

Ejemplo de datos devueltos:

[
    {"Time":1526616000000,"Open":7995,"High":8067.65,"Low":7986.6,"Close":8027.22,"Volume":9444676.27669432},
    {"Time":1526619600000,"Open":8019.03,"High":8049.99,"Low":7982.78,"Close":8027,"Volume":5354251.80804935},
    {"Time":1526623200000,"Open":8027.01,"High":8036.41,"Low":7955.24,"Close":7955.39,"Volume":6659842.42025361},
    ......
]

Ejemplos de líneas K iterativas:

function main(){
    var close = []
    var records = exchange.GetRecords(PERIOD_H1)
    Log('total bars: ', records.length)
    for(var i=0;i<records.length;i++){
        close.push(records[i].Close)
    }
    return close
}

GetTrades

Obtener datos de transacciones de un período de tiempo determinado (no sus propios datos de transacciones), algunos intercambios no lo admiten. Es un uso menos común, puede consultar la documentación de la API para obtener más información.

Acceso a una cuenta para realizar transacciones

Debido a que estas interfaces están relacionadas con las cuentas y no se pueden acceder directamente, se requiere el uso de la firma API-KEY. La plataforma FMZ ya se ha procesado automáticamente en el fondo y se puede usar directamente.

Obtener una cuenta en GetAccount

Obtener información de la cuenta. Una de las interfaces más usadas, que se debe llamar antes de realizar el pedido para evitar un saldo insuficiente.{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}。 donde Stocks es el saldo disponible en moneda de negociación de la pareja de operaciones, FrozenStocks es el saldo congelado de las órdenes pendientes, Balance es el saldo disponible en moneda de cotización, y FrozenBalance es el saldo congelado.BTC_USDTEn el caso de las acciones, se refiere al BTC y el saldo al USDT.

Tenga en cuenta que el resultado que se devuelve es el resultado de un par de operaciones especificado, que la información de otras monedas en la cuenta de operaciones se encuentra en el campo Info, y que no se requiere llamar varias veces para operar varios pares de operaciones.

Un disco duro que muestra el valor total de la pareja de transacciones en curso:

function main(){
    while(true){
        var ticker = exchange.GetTicker()
        var account = exchange.GetAccount()
        var price = ticker.Buy
        var stocks = account.Stocks + account.FrozenStocks
        var balance = account.Balance + account.FrozenBalance
        var value = stocks*price + balance
        Log('Account value is: ', value)
        LogProfit(value)
        Sleep(3000)//sleep 3000ms(3s), A loop must has a sleep, or the rate-limit of the exchange will be exceed
        //when run in debug tool, add a break here
    }
}

Compra bajo el precio

El precio es el siguiente:exchange.Buy(Price, Amount)oexchange.Buy(Price, Amount, Msg),Price es el precio, Amount es la cantidad, Msg es una cadena adicional que se puede mostrar en el registro del disco, no es obligatorio. Este método es para la lista de pedidos, si no se puede completar la transacción de inmediato, se generará una orden no completada, la orden se devolverá con éxito como resultado de la orden id, y si no es así, se devolverá como resultado de la orden idnullPara consultar el estado de los pedidos.

Si quieres comprar a precio de venta, el precio es 1, la cantidad es el valor de la orden, comoexchange.Buy(-1, 0.5)La transacción es correcta.ETH_BTCAlgunos intercambios no soportan el listado de precios de mercado, ni el retroceso de futuros.

Todos los precios y la cantidad de precisión requerida para la transacción parcial está disponible_N()La función de precisión para el control. Para el comercio de futuros Buy y Sell tiene otros significados, que se presentarán por separado.

Un ejemplo de una compra al precio correspondiente:

function main(){
    while(true){
        var ticker = exchange.GetTicker()
        var price = ticker.Sell
        if(price >= 7000){
            exchange.Buy(_N(price+5,2), 1, 'BTC-USDT')
            break
        }
        Sleep(3000)//Sleep 3000ms
    }
    Log('done')
}

Vender y vender abajo

El precio de venta es el mismo que el precio de compra.exchange.Sell(-1, 0.2), representando el precio de venta de 0.2 ETH.

GetOrder para obtener pedidos

Obtener información sobre el pedido basado en la identificación del pedido. Interfaz de uso común, modo de invocaciónexchange.GetOrder(OrderId),OrderId es el id del pedido, que se devuelve cuando se hace el pedido.Cuidado con el tipo de pedidoTypeCampos y estado del pedidoStatusLos valores reales son números que representan diferentes significados, pero no son útiles para el recuerdo, por lo que la FMZ utiliza constantes globales para representar estos valores, como los de los pedidos pendientes.StatusEl valor de 0 es igual aORDER_STATE_PENDINGTodas estas constantes globales se pueden ver en la documentación.❚ Devuelve el resultado:

{
    "Id":125723661, //订单id
    "Amount":0.01, //订单数量
    "Price":7000, //订单价格
    "DealAmount":0, //已成交数量
    "AvgPrice":0, //成交均价
    "Status":0, // 0:未完全成交, 1:已成交, 2:已撤单
    "Type":1,// 订单类型,0:买单, 1:卖单
    "ContractType":"",//合约类型,用于期货交易
    "Info":{} //交易所返回原始信息
    }
}

Una estrategia para comprar una cantidad determinada de monedas:

function main(){
    while(true){
        var amount = exchange.GetAccount().Stocks
        var ticker = exchange.GetTicker()
        var id = null
        if(5-amount>0.01){
            id = exchange.Buy(ticker.Sell, Math.min(5-amount,0.2))
        }else{
            Log('Job completed')
            return //return the main function, bot will stop
        }
        Sleep(3000) //Sleep 3000ms
        if(id){
            var status = exchange.GetOrder(id).Status
            if(status == 0){ //这里也可以用 status == ORDER_STATE_PENDING 来判断。
                exchange.CancelOrder(id)
            }
        }
    }
}

GetOrders no ha entregado el pedido

Obtenga la lista de todos los pedidos pendientes de la transacción actual. Si no hay pedidos pendientes, devuelva una matriz vacía. Obtenga el resultado específico de la lista de pedidos, como GetOrder.

Ejemplos de cancelación de transacciones en curso para todos los pedidos:

function CancelAll(){
    var orders = exchange.GetOrders()
    for(var i=0;i<orders.length;i++){
        exchange.CancelOrder(orders[i].Id) // cancel order by orderID
    }
}
function main(){
    CancelAll()
    while(true){
        //do something
        Sleep(10000)
    }
}

Cancelar el pedido

Cancelar un pedido basado en la identidad de la orden.exchange.CancelOrder(OrderId)。 la cancelación es exitosa y devuelve true, y si no es exitosa y devuelve false。 la cancelación es un fracaso si el pedido ya ha sido completado。

Contratos a plazo y a perpetuidad

El comercio de futuros de moneda digital es diferente del comercio de efectivo. La función de comercio de efectivo anterior también se aplica al comercio de futuros, el comercio de un solo plazo tiene una función exclusiva. Antes de realizar el comercio de futuros de moneda digital, debe familiarizarse con las operaciones manuales en el sitio web y comprender los conceptos básicos, como abrir posición, estar en posición baja, estar en posición total, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja, estar en posición baja.

Los contratos de perpetuidad son similares a los contratos de futuros, pero no tienen el concepto de tener más de un espacio al mismo tiempo.

Si la bolsa apoya simultáneamente a los futuros en efectivo, como los futuros de OKEX y Huobi, se necesita seleccionar separadamente en la interfaz de la bolsa el cuadro de futuros de OKEX y el cuadro de futuros de Huobi para agregar, en FMZ, un intercambio diferente al de los futuros.

Tipo de contrato establecido

El primer paso para el comercio de futuros es configurar el contrato a negociar, por ejemplo, en los futuros de OKEX, para crear un par de operaciones de BTC en el disco o en la retrospectiva, también se necesita configurar en el código el contrato de la semana, la semana siguiente o el trimestre. Si no se configura, se le pediráinvalid contract typeA diferencia de los pares de divisas, los contratos de futuros suelen estar garantizados con monedas de negociación como el BTC, los pares de negociación que agregan BTC suelen representar el par de transacciones BTC_USD garantizado con BTC, y si existen futuros garantizados con USDT, es necesario crear un par de transacciones BTC_USDT agregado a la plataforma. Por ejemplo, los futuros de divisas como OKEX tienen un contrato de renovación permanente que existe a la vez en el nivel de la moneda y el nivel de USDT.Después de configurar el par de transacciones, también se debe configurar un tipo de contrato específico, como permanente, semanal, semanal, semanal, etc. Después de configurar el contrato, se pueden realizar operaciones de compra y venta.

Los contratos de Bitcoin, OKEX, HuobiDM, etc. que existen en Bitcoin y USDT, necesitan ser distinguidos al agregar contratos de configuración de disco duro. La configuración específica es la siguiente.

//OKEX期货
exchange.SetContractType("swap")        // 设置为永续合约
exchange.SetContractType("this_week")   // 设置为当周合约
exchange.SetContractType("next_week")   // 设置为次周合约
exchange.SetContractType("quarter")     // 设置为季度合约

//HuobiDM
exchange.SetContractType("this_week")   // 设置为当周合约 
exchange.SetContractType("next_week")   // 设置为次周合约
exchange.SetContractType("quarter")     // 设置为季度合约
exchange.SetContractType("swap")        // 设置为永续合约

//币安期货
exchange.SetContractType("swap")   // 设置为永续合约,注意币本位和USDT本位都存在永续
exchange.SetContractType("quarter")   // 设置为当季合约
exchange.SetContractType("next_quarter")  // 设置为次季合约

//BitMEX
exchange.SetContractType("XBTUSD")    // 设置为永续合约
exchange.SetContractType("XBTM19")  // 具体某个时间结算的合约,详情登录BitMEX查询各个合约代码

//GateIO
exchange.SetContractType("swap")      // 设置为永续合约,不设置默认为swap永续合约。 

//Deribit
exchange.SetContractType("BTC-27APR18")  // 具体某个时间结算的合约,详情参看Deribit官网。

GetPosition mantiene posiciones

Obtener la lista de información de la posición actual, OKEX(OKCOIN) los futuros pueden pasarse un parámetro que especifique el tipo de contrato que se desea obtener. Si no se tiene una posición, se devuelve la lista vacía[]La información sobre la tenencia regresa de la siguiente manera, hay mucha información específica que necesita ser analizada en combinación con la información sobre el comercio.

Tipo de datos Nombre de la variable ilustrar

La estructura original devuelta por el intercambio de objetos El número de divisas, el nivel de margen y el tamaño de la barra, OKCoin es 10 o 20, el modo de reserva total de OK Futures regresa a 10 fijo, ya que la API nativa no lo soporta “number” es el monto de la reserva, “OKCoin” es el número de partes en el contrato, “ (un número entero mayor que 1) ” “La cantidad congelada es la cantidad de almacenamiento congelado”. El precio de la cantidad de dinero que tiene. El número de Margin es el número de garantía congelada. “number” y “Profit” en el mercado de futuros de OKCoin: pérdidas en la bolsa de valores, monedas digitales: ((unidad de monedas digitales: BTC/LTC, unidad de futuros tradicionales: RMB, nota: OKCoin en el mercado de futuros de OKCoin se refiere a un superávit en caso de que la bolsa esté llena, no a pérdidas en la bolsa de valores, pérdidas en la bolsa de valores) const PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG PD_LONG string ContractType

function main(){
    exchange.SetContractType("this_week");
    var position = exchange.GetPosition();
    if(position.length>0){ //特别要注意引用前要先判断position长度再引用,否则会出错
        Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
            position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,"ContractType:", position[0].ContractType)
    }
}

Los pronósticos se cerraron.

En primer lugar, hay que configurar el tamaño de la palanca y la forma en que se llama:exchange.SetMarginLevel(10)El 10 representa el 10 por 10 de la palanca, el tamaño de la palanca que se apoya en particular, y ver el correspondiente intercambio.Tenga en cuenta que el apalancamiento debe estar configurado en la plataforma de intercambio y que el código debe ser consistente con el de la plataforma de intercambio, de lo contrario se producirá un errorTambién puede no estar configurado, usando el control predeterminado. Luego, configure la dirección de la transacción y la forma en que se llama:exchange.SetDirection(Direction)En respuesta a la apertura de una posición en el mercado,A diferencia de los futuros, si un contrato de perpetuidad no tiene el concepto de tener un exceso de espacio al mismo tiempo, es decir, no se permite la posesión de una sola posición, hacer un exceso de espacio automáticamente eliminará el exceso de espacio, todo lo que se necesita es establecerbuyysellSe necesita una configuración si se admite la tenencia bidireccional.closebuy,closebuyRelaciones específicas:

Las operaciones Los parámetros de SetDirection Función de orden de baja
Abrir más posiciones exchange.SetDirection(“buy”) exchange.Buy()
Punto y posición exchange.SetDirection(“closebuy”) exchange.Sell()
Posiciones abiertas exchange.SetDirection(“sell”) exchange.Sell()
Posiciones abiertas exchange.SetDirection(“closesell”) exchange.Buy()

Finalmente, el código de posición abierta y cerrada es específico, y el volumen de la orden es diferente en diferentes bolsas, como los futuros de huobi por número de tiradas, una de 100 dólares. Tenga en cuenta que la retroalimentación de los futuros no respalda el precio de mercado.

function main(){
    exchange.SetContractType("this_week")    // 举例设置 为OKEX期货 当周合约
    price = exchange.GetTicker().Last
    exchange.SetMarginLevel(10) //设置杠杆为10倍 
    exchange.SetDirection("buy") //设置下单类型为做多 
    exchange.Buy(price+10, 20) // 合约数量为20下单 
    pos = exchange.GetPosition()
    Log(pos)
    Log(exchange.GetOrders()) //查看是否有未成交订单
    exchange.SetDirection("closebuy"); //如果是永续合约,直接设置exchange.SetDirection("sell")
    exchange.Sell(price-10, 20)
}

A continuación se muestra un ejemplo concreto de una estrategia de posiciones cerradas en su totalidad

function main(){
    while(true){
        var pos = exchange.GetPosition()
        var ticker = exchange.GetTicekr()
        if(!ticker){
            Log('无法获取ticker')
            return
        }
        if(!pos || pos.length == 0 ){
            Log('已无持仓')
            return
        }
        for(var i=0;i<pos.length;i++){
            if(pos[i].Type == PD_LONG){
                exchange.SetContractType(pos[i].ContractType)
                exchange.SetDirection('closebuy')
                exchange.Sell(ticker.Buy, pos[i].Amount - pos[i].FrozenAmount)
            }
            if(pos[i].Type == PD_SHORT){
                exchange.SetContractType(pos[i].ContractType)
                exchange.SetDirection('closesell')
                exchange.Buy(ticker.Sell, pos[i].Amount - pos[i].FrozenAmount)
            }
        }
        var orders = exchange.Getorders()
        Sleep(500)
        for(var j=0;j<orders.length;j++){
            if(orders[i].Status == ORDER_STATE_PENDING){
                exchange.CancelOrder(orders[i].Id)
            }
        }
    }
}

Negociaciones con apalancamiento de moneda digital

El cambio a una cuenta de apalancamiento en el código es el mismo que el cambio a una cuenta en efectivo.

Utiliza exchange.IO ((“trade_margin”) para cambiar a la modalidad de cuenta de ganancias, ordenar y obtener los activos de la cuenta se accederá a la interfaz de palanca de la bolsa. Utiliza exchange.IO ((“trade_normal”) para cambiar de nuevo al modo de cuenta normal.

Las plataformas de intercambio apoyadas:

  • OKEX V3: El modelo de cuenta de apalancamiento de los pares de transacciones es diferente al normal, y algunos pares de transacciones pueden no existir.
  • Bitcoin: El modelo de cuenta de apalancamiento es diferente a los pares normales, y algunos pares no lo son.
  • ZB: los fondos se pueden transferir como QC, el sector de negociación de levadura, la independencia de fondos entre los diferentes pares de negociación, es decir, el número de monedas QC bajo la pareja de negociación ETH_QC, no se ve en BTC_QC
  • FCoin
  • La moneda más popular es el Bitcoin.

Commodity Futures Trading (FFT) (en inglés)

Las operaciones de futuros de mercancías y las operaciones de futuros de monedas digitales tienen una gran diferencia. En primer lugar, el tiempo de negociación de los futuros de mercancías es corto, las monedas digitales se negocian las 24 horas; los acuerdos de los futuros de mercancías no son una API REST común; la frecuencia de negociación de los futuros de mercancías y las restricciones de cantidad de pedidos, las monedas digitales son muy flexibles, etc. Por lo tanto, las operaciones de futuros de mercancías tienen muchos lugares que requieren atención especial, y se recomienda tener una amplia experiencia de operación manual.

La plataforma cuantitativa FMZ, como proveedor de operaciones programadas, solicita la licencia del software a los diferentes proveedores de servicios de futuros, los usuarios pueden usarlo sin necesidad de solicitarlo directamente, en la página de búsqueda de futuros agregados se puede ver la lista de solicitudes de FMZ que se han solicitado. Posiciones de referencia específicas: https://www.fmz.com/bbs-topic/3860 ❚ Si su proveedor de futuros ya no está en la lista, solo puede solicitarlo por sí mismo o volver a apoyar a los operadores abiertos, generalmente toma 2 días.

Debido a las ventajas de la arquitectura de la plataforma FMZ, los usuarios también pueden agregar varias cuentas de comerciantes de futuros, y lograr algunas funciones que otros programas de comercio de futuros de mercancías no pueden hacer, como la síntesis de ticks de alta frecuencia, consulta: https://www.fmz.com/bbs-topic/1184

Marco de políticas

En primer lugar, debido a que no se trata de una transacción de 24 horas y se requiere una operación de inicio de sesión, es necesario juzgar el estado del enlace antes de realizar la transacción.exchange.IO("status")paratrueIndica que se conectó a la bolsa. Si no se logró la conexión, se llamó a la API y no se le indicó ‘not login’. Se puede dormir después del inicio de la estrategia ((2000), dar un cierto tiempo para iniciar sesión. También se puede volver a intentar la suscripción._C(exchange.SetContractType,"MA888")El objetivo es asegurar el éxito del aterrizaje.

El código de acceso y transacción de los futuros de mercancías es el mismo que el de los futuros de moneda digital. Aquí se describen las diferencias y las áreas a tener en cuenta.

function main(){
    _C(exchange.SetContractType,"MA888") //没登陆成功是无法订阅合约的,最好重试一下
    while(true){
        if(exchange.IO("status")){
            var ticker = exchange.GetTicker()
            Log("MA888 ticker:", ticker)
            LogStatus(_D(), "已经连接CTP !")//_D获取事件
        } else {
            LogStatus(_D(), "未连接CTP !")
            Sleep(1000)
        }
    }
}

Se recomienda usar el comercio de la galería de futuros de mercancías (más adelante), en este caso el código será muy simple y no tendrá que lidiar con los detalles tediosos.

function main() {
    // 使用了商品期货类库的CTA策略框架
    $.CTA(Symbols, function(st) {
        var r = st.records
        var mp = st.position.amount
        var symbol = st.symbol
        /*
        r为K线, mp为当前品种持仓数量, 正数指多仓, 负数指空仓, 0则不持仓, symbol指品种名称
        返回值如为n: 
            n = 0 : 指全部平仓(不管当前持多持空)
            n > 0 : 如果当前持多仓,则加n个多仓, 如果当前为空仓则平n个空仓,如果n大于当前持仓, 则反手开多仓
            n < 0 : 如果当前持空仓,则加n个空仓, 如果当前为多仓则平n个多仓,如果-n大于当前持仓, 则反手开空仓
            无返回值表示什么也不做
        */
        if (r.length < SlowPeriod) {
            return
        }
        var cross = _Cross(TA.EMA(r, FastPeriod), TA.EMA(r, SlowPeriod));
        if (mp <= 0 && cross > ConfirmPeriod) {
            Log(symbol, "金叉周期", cross, "当前持仓", mp);
            return Lots * (mp < 0 ? 2 : 1)
        } else if (mp >= 0 && cross < -ConfirmPeriod) {
            Log(symbol, "死叉周期", cross, "当前持仓", mp);
            return -Lots * (mp > 0 ? 2 : 1)
        }
    });
}

Modos de obtención de datos de CTP

Los futuros de mercancías utilizan el protocolo CTP, todos los movimientos y transacciones de pedidos se notifican solo cuando hay cambios, mientras que las consultas de pedidos, cuentas y posiciones son consultas activas. Por lo tanto, es adecuado para escribir estrategias de alta frecuencia impulsadas por eventos.GetTickerGetDepthGetRecordsCuando hay cambios en la situación, ticker, profundidad, y los registros se actualizan. En este momento, la llamada de cualquiera de las interfaces se devuelve de inmediato, el estado de la interfaz que se ha llamado se pone en modo de espera de actualización, la próxima vez que se llame a la misma interfaz, se esperará a que regresen nuevos datos. Algunas situaciones de cerrazón fría o caída de la oferta pueden ocurrir durante mucho tiempo sin transacciones, esto es normal para la estrategia.

Si quieres obtener datos cada vez que obtienes una actualización, incluso datos antiguos, puedes cambiar a la actualización inmediata de la actualización.exchange.IO("mode", 0)❚ En este momento la estrategia no puede ser escrita como impulsada por eventos, y se necesita agregar un evento de SLeep para evitar un ciclo de muerte rápido. Algunas estrategias de baja frecuencia pueden usar este modelo, y la estrategia es simple de diseño.exchange.IO("mode", 1)Se puede volver al modo de caché por defecto.

En el caso de contratos individuales, se puede usar el modo predeterminado. Sin embargo, si se trata de varios contratos, es posible que un contrato no se actualice, lo que provoca el bloqueo de la interfaz de actualización, y no se pueden obtener actualizaciones de otros contratos. Para resolver este problema, se puede usar el modo de actualización inmediata, pero no es conveniente escribir una estrategia de alta frecuencia.exchange.IO("wait")Si se añade más de un objeto de intercambio, lo cual es raro en los futuros de mercancías, se puede usarexchange.IO("wait_any")El índice devuelto indica el índice de la bolsa devuelto.

El cambio de tick de la transacción fue enviado por: {Event:"tick", Index:交易所索引(按实盘上交易所添加顺序), Nano:事件纳秒级时间, Symbol:合约名称} Enviado por:{Event:"order", Index:交易所索引, Nano:事件纳秒级时间, Order:订单信息(与GetOrder获取一致)}

En este punto la estructura de la estrategia se puede escribir como:

function on_tick(symbol){
    Log("symbol update")
    exchange.SetContractType(symbol)
    Log(exchange.GetTicker())
}

function on_order(order){
    Log("order update", order)
}

function main(){
    while(true){
        if(exchange.IO("status")){ //判断链接状态
            exchange.IO("mode", 0)
            _C(exchange.SetContractType, "MA888")//订阅MA,只有第一次是真正的发出订阅请求,接下来都是程序切换,不耗时间。
            _C(exchange.SetContractType, "rb888")//订阅rb
            while(true){
                var e = exchange.IO("wait")
                if(e){
                    if(e.event == "tick"){
                        on_tick(e.Symbol)
                    }else if(e.event == "order"){
                        on_order(e.Order)
                    }
                }
           }
        }else{
            Sleep(10*1000)
        }
    }
}

Diferencias entre los futuros de mercancías y la moneda digital

También hay que tener en cuenta la diferencia entre los futuros de mercancías y las bolsas de divisas digitales. Por ejemplo, GetDepth en realidad solo tiene una profundidad de arco (los cargos de profundidad de 5 arcos son caros), y GetTrades no obtiene el historial de transacciones (se basan en la simulación de los cambios en la posesión, no hay un registro real de transacciones). Los futuros de mercancías tienen límites de alza y baja, cuando se detiene, el precio de venta de la lista de ventas en profundidad es el precio de alza y baja, el volumen de pedidos es 0, cuando se detiene, el precio de compra y compra es el precio de alza y baja, el volumen de pedidos es 0.

Establecimiento de un contrato

exchange.IO ((“instruments”): devuelve la lista de todos los contratos de la bolsa en formato de diccionario, soportando solo el disco físico. exchange.IO ((“products”): devuelve la lista de todos los productos de la bolsa en formato de diccionario, sólo soporta disco físico. exchange.IO ((“subscribed”): devuelve el contrato al que se ha suscrito, en el mismo formato, sólo soporta disco físico.

Los futuros CTP tradicionalesContractTypeEs decir, la identificación del contrato, con distinción en mayúsculas y minúsculas. Por ejemplo:exchange.SetContractType("au1506")❚ Configurar el contrato con éxito y devolver la información detallada del contrato, como la cantidad mínima de compra, los gastos, el tiempo de entrega, etc. ❚ Cuando se suscribe a varios contratos, solo se envía una solicitud de suscripción real por primera vez, y luego solo se cambia el par de transacciones a nivel de código, sin perder tiempo. ❚ Los contratos de secuencia principal tienen un código como 888 como MA888, los contratos de índice en serie como 000 como MA000, 888 y 000 solo soportan la retrospectiva para el comercio de contratos virtuales, los discos reales solo soportan el acceso.Sin embargo, el lenguaje Mac puede manejar el contrato de dominio, y el programa cambia automáticamente la posición, es decir, elimina la posición no dominante y abre una nueva posición en la posición dominante.

Si el inicio de sesión no es exitoso, no se puede configurar el contrato, pero también se devuelve de inmediato, por lo que se puede volver a intentarlo con _C, sabiendo que el inicio de sesión de CTP está terminado. Una vez que el inicio de sesión es exitoso, configurar el contrato de nuevo no lleva tiempo y no genera un acceso real a la red.

Posiciones abiertas y cerradas

SetDirectionSe puede obtener la direcciónbuy, closebuy, sell, closesellCuatro parámetros, más productos futurosclosebuy_todayyclosesell_todayLa gente no tiene idea de lo que está sucediendo.closebuy/closesellPara la posición de ayer, solo la variedad de la fecha anterior se distingue entre hoy y ayer, lo que puede afectar a los honorarios, por lo que se necesita prioridad para la posición de ayer. Para los futuros tradicionales de CTP, se puede configurar un segundo parámetro de 1 o 2 o 3 puntos, que se refiere a la caja de especulación, la caja de ganancias y la caja de seguridad, sin establecer especulación por defecto.Las operaciones concretas de compra y venta, adquisición de posiciones, adquisición de órdenes, cancelación de facturas y adquisición de cuentas son las mismas que las transacciones de futuros de moneda digital, consulte el capítulo anterior.

Las operaciones Los parámetros de SetDirection Función de orden de baja
Abrir más posiciones exchange.SetDirection(“buy”) exchange.Buy()
Punto y posición exchange.SetDirection(“closebuy”) exchange.Sell()
Posiciones abiertas exchange.SetDirection(“sell”) exchange.Sell()
Posiciones abiertas exchange.SetDirection(“closesell”) exchange.Buy()

El siguiente ejemplo es una función de posición cerrada concreta, tenga en cuenta que este ejemplo es demasiado simple, también hay que considerar si se encuentra en el momento de negociación, no se ha completado la negociación, cómo poner una prueba pesada, cuál es el volumen máximo de la orden, si la frecuencia es demasiado alta, específicamente si el precio es de desviación o de apertura, etc.El almacenamiento abierto en disco duro recomienda el uso de un repositorio de clases envasado en la plataforma, https://www.fmz.com/strategy/12961。 En el capítulo de bibliotecas hay información específica, también se recomienda aprender el código fuente de la biblioteca de clases。

function Cover(contractType, amount, slide) {
    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType != contractType) {
            continue;
        }
        var depth = _C(e.GetDepth);
        if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
            exchange.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
            exchange.Sell(depth.Bids[0]-slide, amount, contractType, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
        } else {
            exchange.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
            exchange.Buy(depth.Asks[0]+slide, amount, contractType, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
        }
    }
}

Commodity Futures soporta tipos de órdenes personalizadas (soporta disco físico, no soporta retroalimentación), especifica la forma de la barra posterior y se agrega en la barra_Por ejemplo, en la parte posterior de la pared.

exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")

El sufijo específico es:

  • ioc se completa inmediatamente o se revoca el THOST_FTDC_TC_IOC
  • gfs Esta sección es válida para THOST_FTDC_TC_GFS
  • gfd vigente en el día THOST_FTDC_TC_GFD
  • gtd válido hasta la fecha especificada THOST_FTDC_TC_GTD
  • gtc válido antes de su revocación THOST_FTDC_TC_GTC
  • gfa El conjunto de ofertas es válido THOST_FTDC_TC_GFA

Interfaz fácil de usar

Por defecto, en los operadores de futuros de mercancías se abre la interfaz CTP, que se puede cambiar a la interfaz EASY si se solicita. A través del paquete FMZ, la forma de llamada es la misma. La diferencia es que las cuentas, los pedidos y los depósitos son en modo de envío, por lo que el custodio mantiene estos datos localmente y, cuando se llama a la interfaz correspondiente, se devuelve de inmediato y no se envía una solicitud real.

Los tipos de órdenes personalizadas del protocolo de estabilidad son los siguientes:

  • gfd vigente en el día TAPI_ORDER_TIMEINFORCE_GFD
  • gtc TAPI_ORDER_TIMEINFORCE_GTC vigente hasta su revocación
  • gtd válido hasta la fecha especificada TAPI_ORDER_TIMEINFORCE_GTD
  • TAPI_ORDER_TIMEINFORCE_FAK La entrega de una parte y la revocación de la parte restante
  • ioc Se debe completar de inmediato, o se debe revocar TAPI_ORDER_TIMEINFORCE_FAK
  • TAPI_ORDER_TIMEINFORCE_FOK no se ha completado la transacción y se ha revocado la totalidad

Funciones globales de uso común

Log Logs y WeChat

En la interfaz de disco rígido, un registro de registro, después de la cadena de caracteres, se agrega el carácter @ para que el mensaje entre en la cola de envío, y se envía directamente después de que se conecte a WeChat o Telegram.Log('推送到微信@')

El color del registro también puede ser personalizadoLog('这是一个红色字体的日志 #ff0000')#ff0000Es decir, 16 veces el color RGB.

Todos los archivos de registro se encuentran dentro de la base de datos sqlit en disco en el directorio del administrador, se pueden descargar y abrir con el software de la base de datos, o se pueden usar para copiar la recuperación de la copia de seguridad (el nombre de la base de datos y la identidad del disco físico son los mismos).

LogProfit para imprimir sus ganancias

Registra los beneficios y traza una curva de beneficios en la interfaz del disco, que se puede conservar después de reiniciar el disco.LogProfit(1000)Cuidado.LogProfitLos parámetros no necesariamente son ganancias, pueden ser cualquier número y se deben rellenar ellos mismos.

LogStatus muestra la tabla de estado (incluye la tabla)

El estado del disco duro, ya que los registros de registro se guardan y se actualizan constantemente, se puede usar si se necesita mostrar solo información no guardada.LogStatusfunción.LogStatusLos parámetros de la tabla son strings, que también pueden ser usados para representar la información de la tabla.

Ejemplo de una tabla que muestra la ubicación del estado de un disco concreto:

var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]}; 
LogStatus('`' + JSON.stringify(table) + '`'); // JSON序列化后两边加上`字符, 视为一个复杂消息格式(当前支持表格) 
LogStatus('第一行消息\n`' + JSON.stringify(table) + '`\n第三行消息'); // 表格信息也可以在多行中出现 
LogStatus('`' + JSON.stringify([table, table]) + '`'); // 支持多个表格同时显示, 将以TAB显示到一组里 
LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n'); // 上下排列显示多个表

El sueño.

Los parámetros son milisegundos, por ejemplo:Sleep(1000)Un segundo para dormir. Debido a la limitación de la frecuencia de acceso a todas las transacciones, la estrategia general es agregar el tiempo de reposo en el ciclo muerto.

_G Conservación de datos

Cuando el disco duro se reinicia, el programa se reinicia, y si se quiere guardar información permanente, se puede cambiar el disco duro para el disco duro y el disco duro para el disco duro._GEs muy conveniente y práctico, ya que permite guardar contenido secuenciado en JSON._GLa función se escribe enonexit()En este caso, cada vez que se detiene la estrategia, se guarda automáticamente la información que se necesita. Si quieres guardar más datos en formato, tienes que usar un archivo de archivo._La función G no es muy útil, ya que se puede escribir directamente en la base de datos con Python.

”` function onexit(){ _G(‘profit’, profit) } function main(){ _G(“num”, 1); // 设置一个全局变量num, 值为1 s _G(“num”, “ok”); // 更改一个全局变量num, 值为字符串ok