[TOC] ¿Qué quieres decir?

Instrucciones básicas

Cómo empezar

¿Qué puede hacer FMZ Quant Trading Platform?

FMZ Quant Trading es la comunidad cuantitativa más profesional en el campo del comercio cuantitativo. Aquí puedes aprender, escribir, compartir, comprar y vender estrategias cuantitativas; puedes realizar backtesting en línea y usar robots de simulación para realizar operaciones simuladas; también puedes ejecutar, publicar y ver operaciones en vivo.

Serie completa de tutoriales

Tutoriales gráficos:

Si hay algún problema, puede publicar preguntas y discutir en el foro en cualquier momento, o enviar un ticket, o ponerse en contacto con un administrador en el grupo de Telegram (Telegrama), en general, la pregunta será respondida rápidamente.

Apoyo a ChatGPT para la ayuda al desarrollo

FMZ Quantitative Trading Platform ha adoptado ChatGPT como herramienta de asistencia al desarrollo, a la que se puede acceder haciendo clic en ChatGPT en la barra de accesos directos en el Dashboard para ir a la página de inicio.Página de herramientas auxiliares de ChatGPT.

¿Qué lenguajes de programación están disponibles para implementar mis estrategias?

La plataforma de comercio de FMZ Quant es compatible con el usoJavaScript, TypeScript, Python, C++, Pine MylanguageyBlockly Visualizationpara escribir y diseñar estrategias.

ApoyaTypeScriptlenguaje, todavía ponerlo aJavaScriptestrategia cuando creamos estrategias, entonces escribimos// @ts-checkal principio del código de estrategia o haga clic en el botónTypeScripten la esquina superior derecha del área de edición de la estrategia para cambiar aTypeScriptLa plataforma reconocerá el código comoTypeScriptautomáticamente y le proporcionará el apoyo adecuado para la compilación y verificación de tipo de:

  • Seguridad por tipo:TypeScriptLa función de comprobación de tipo estático de la aplicación puede ayudarle a encontrar posibles errores al escribir código y mejorar la calidad del código.
  • Completación automática del código:TypeScriptEl sistema de tipos de Microsoft hace que sea más rápido encontrar los atributos y métodos que necesita al escribir código, mejorando la eficiencia del desarrollo.
  • Estructura de código más clara:TypeScript, puede organizar y mantener mejor su código, haciéndolo fácil de leer y entender.
  • Potentes características de programación orientada a objetos:TypeScriptproporciona poderosas características de programación orientada a objetos, como interfaces, clases, genéricos y así sucesivamente, ayudándote a escribir un código de estrategia más robusto y reutilizable.

Solo necesita dominar uno de estos lenguajes. Además de apoyar la forma de diseñar estrategias escribiendo código, también puede crear estrategias utilizando módulos visuales (Blockly). El módulo de visualización de empalme y estrategia de construcción, sin codificación, adopta una forma más intuitiva de diseñar estrategias, lo que es muy adecuado para cultivar interés en el diseño de estrategias para comenzar rápidamente con el comercio programático y cuantitativo.

BlocklyTutoriales de visualización:

Configurar elPythonel intérprete utilizado por elPythonPrograma de estrategia

Las estrategias escritas enPython, cuando se realiza backtesting o trading en vivo, si el entorno del sistema docker tiene ambosPython2yPython3instalado, se puede establecer elPythonLa versión que se lanzará en tiempo de ejecución en la primera línea de la estrategia, como#!python3y#!python2, para que el sistema encuentre el intérprete automáticamente. Y también puede especificar una ruta absoluta, como:#!/usr/bin/python3.

¿Qué es Docker?

Docker puede entenderse como el ejecutor de su estrategia comercial, responsable de las solicitudes de datos complejos, recepción de datos, enlaces de red, log postback y así sucesivamente.Linux, Las ventanas, Mac OS, Android, Raspberry Pi ARM Linuxy otros sistemas.Página de Docker, Etapas de instalación y actualización del docker de LinuxLos bots y registros administrados por el docker se almacenan en el directorio./logs/storageEl expediente es unSqlitearchivo de base de datos condb3, que puede ser editado directamente por elSqlitepara un archivo con extensióndb3En la base de datos de bots reales, el nombre del archivo es el bot ID.

Protocolos soportados

  • Activos de blockchain: más de 50 intercambios de activos de blockchain (criptomoneda) principales ahora son compatibles en nuestra plataforma.
  • Acceso al protocolo general:Protocolo general

Seguridad estratégica

Cuando se desarrollan estrategias de trading en la plataforma FMZ Quant Trading, el contenido de la estrategia solo es visible para los titulares de cuentas de FMZ.PythonEl paquete, que se carga en el código de la estrategia, de modo que la localización de contenido de la estrategia se puede realizar.

La seguridad dePythonel código: ¿Por qué?Pythones un lenguaje de código abierto que es extremadamente fácil de descompilar, si la estrategia no es para uso personal sino para alquiler, puede ejecutar la estrategia en su propio docker desplegado y alquilarla en forma de subcuenta o administración completa de docker si le preocupa la fuga de estrategia.

El cifrado dePythonCódigo de estrategia: Por defecto,PythonEl código de estrategia no está cifrado cuando es utilizado por el autor y está cifrado cuando se alquila a otros. Mediante la edición del siguiente código al comienzo delPythonEn el caso de la estrategia, puede especificar si desea cifrar el código de la estrategia para uso personal o alquiler.PythonLas versiones que admiten el cifrado de los códigos de estrategia son las siguientes:Python 2.7, Python 3.5yPython 3.6.

  • Los autores de la estrategia lo ejecutan ellos mismos y cifran el código de la estrategia para que otros lo usen a través del código de registro: Especificar#!pythoncomo la versión del intérprete de Python, y luego utilizar,para mantener separado; introduzca el comando de cifradoencryptSi no especifica la versión dePython, añadir#!,encrypt directly.
 #!python,encrypt

¿ O qué?

  #!encrypt
  • No cifrará los códigos de estrategia cuando los escritores de estrategia corran para su propio uso y comparten con otros a través del código de registro:
  #!python, not encrypted

¿ O qué?

  #!not encrypted

Utilice el códigoos.getenv('__FMZ_ENV__')para determinar si el código de cifrado es válido; la devolución de la cadena"encrypt"Indica que ha entrado en vigor. Sólo es válido en el bot real, y el backtest no cifrará elPythonCódigos de estrategia.

#!encrypt
def main():
    ret = os.getenv('__FMZ_ENV__')
    # If the print variable ret is the string "encrypt" or ret == "encrypt" is true, that means the encryption is valid. 
    Log(ret, ret == "encrypt")

Seguridad clave

Los datos confidenciales, como la información de la cuenta y las cadenas cifradas en los parámetros de estrategia configurados en la plataforma de negociación de FMZ Quant, se cifran en el navegador web. Toda la información almacenada en la plataforma de negociación de FMZ Quant está cifrada (no datos de texto plano), y solo los usuarios pueden descifrar y usar la información, lo que mejora enormemente la seguridad de los datos confidenciales.

  • Nuestra plataforma admite la configuración localizada de información confidencial, como la información de la cuenta de intercambio y la clave secreta En la página donde la plataforma configura la información de intercambio, todos los controles de caja de texto cifrados con máscaras admiten la forma de configurar la ruta del archivo para cargar el archivo local del docker.RSA KEYmétodo de autenticación del intercambio como un ejemplo para explicar en detalle cómo configurar información confidencial localmente en el dispositivo donde se encuentra el programa docker.
  1. Crear clave pública y clave privada RSA. Por ejemplo, crear claves públicas y privadas en el formato dePKCS#8, hay muchas herramientas disponibles para la creación, tales comoopenssl.
  2. Crear unaRSA KEYen el intercambio, y subir la clave pública creada enPaso 1durante la creación.
  3. Guardar la clave privada creada enPaso 1en el mismo directorio del docker en el formato detxtarchivo, o en otras rutas en el directorio del programa docker.
  4. Al configurar el intercambio en la plataforma FMZ, complete elRSA KEYCreado por el intercambio en el cuadro de edición de la configuraciónAccess Key.
  5. Al configurar el intercambio en la plataforma FMZ, complete la ruta deltxtarchivo colocado en el mismo directorio de nivel del docker en elPaso 3en el cuadro de edición de la configuraciónSecret KeyPor ejemplo, si el nombre del archivo colocado es:rsaKey.txt, y el archivo y el docker se llenan en el mismo directorio de nivel:file:///rsaKey.txt. Si el archivo está en el directorio al lado del directorio del programa dockerrsa_key, cumplimentar:file:///rsa_key//rsaKey.txtSi usted colocarsaKey. txtEn cualquier otro lugar de su computadora o servidor siga estas instrucciones en consecuencia, debe tenerse en cuenta que este archivo sólo se puede colocar en directorios de mismo nivel o subdirectorios con respecto a Docker.

Esto hace que sea más seguro localizar y guardar la clave privada, se puede referir aVideo de explicaciónpara un proceso detallado.

Sistema de pruebas de retroceso

¿Qué es un sistema de backtest y para qué se utiliza?

Después de haber completado el diseño de una estrategia comercial cuantitativa, ¿cómo puede conocer la situación básica de su estrategia, como la lógica de la estrategia y la dirección de los retornos de la estrategia?

¿Son exactos los datos del sistema de backtest y qué pasa con la exactitud de los resultados de backtest?

La plataforma de comercio de FMZ Quant divide el sistema de backtest ennivel de mercado realynivel de simulaciónEl nivel real del mercado es para backtest completamente de acuerdo con los datos históricos completos; mientras que el nivel de simulación backtest generatickLos datos se basan en datos históricos reales, pero los datos reales de mercado son más precisos y los resultados más creíbles.Descripción del mecanismo de prueba de retroceso FMZSin embargo, el backtesting es solo el rendimiento de la estrategia según los datos históricos. Los datos históricos no pueden representar completamente el mercado futuro. El mercado histórico puede repetirse, o también puede conducir al Cisne Negro. Por lo tanto, los resultados del backtest deben tratarse de manera racional y objetiva.

Cuestiones a tener en cuenta al hacer pruebas de retroceso de diferentes estrategias de lenguaje de programación:

El backtest deJavaScript tambiényC++estrategias de negociación se lleva a cabo en el navegador, y el bot de mercado real oWexApp es una aplicaciónEn la actualidad, el mercado real de divisas emulado (es decir, elWexApp es una aplicaciónEmulado de intercambio de FMZ Quant Trading plataforma) se ejecuta sin instalar ningún otro software, bibliotecas o módulos. La prueba de retroceso dePythonLa operación de mercado real y la backtest se basan en el funcionamiento de la plataforma de comercio de FMZ.PythonSi se necesitan algunas bibliotecas, deben instalarse manualmente (sólo se admiten bibliotecas comunes en servidores públicos).

Datos de pruebas de retroceso en el sistema

Hay dos tipos de pruebas de retroceso de la plataforma de comercio de FMZ Quant: pruebas de retroceso de nivel de simulación y pruebas de retroceso de nivel de mercado real.tickCada período de línea K generará 12 puntos de tiempo de backtesting; sin embargo, el nivel real del mercado recogeticksEl mecanismo de backtest de FMZ permite que la estrategia de trading se negocie varias veces en una sola línea K, evitando la situación en la que la negociación solo se puede ejecutar al precio de cierre. Es más precisa teniendo en cuenta la velocidad de backtest.el Enlace.

Método de estrategia DEBUG en el sistema de backtesting

Prueba de estrategia de backtesting de JavaScript en Chrome DevTools

Intercambios admitidos en el sistema de pruebas de retroceso

  • Valor de la moneda encriptada (Criptomoneda)

    Nombre Tipo de producto Instrucciones
    Bitfinex objeto de intercambio al contado apoyar pares de operaciones limitados, tales como:BTC_USD, ETH_USDyLTC_USD, etc. (observe que la moneda de cotización de los pares de operaciones esUSDel dólar)
    Binance objeto de intercambio al contado apoyar pares de operaciones limitados, tales como:BTC_USDT, ETH_USDT, ETH_BTCyLTC_BTC, etc.
    No hay problema. objeto de intercambio al contado apoyar pares de operaciones limitados, tales como:BTC_USDT, ETH_USDT, ETH_BTCyLTC_BTC, etc.
    - ¿ Qué? objeto de intercambio al contado apoyar pares de operaciones limitados, tales como:BTC_USDT, ETH_USDT, ETH_BTCyLTC_BTC, etc.
    Futuros de OKX Objeto de cambio de futuros apoyar pares de operaciones limitados, tales como:BTC_USDyETH_USD, etc.; la moneda de cotización de los pares de negociación esUSD; después de la fijación del código de contrato específico (consulte la funciónexchange.SetContractType), el contrato es un contrato de criptomonedas con margen; los códigos de contrato admitidos incluyen:this_week, next_week, quarteryswap
    - ¿ Qué es eso? Objeto de cambio de futuros HuobiDM es Huobi Futures (Contrato Huobi), que admite pares de operaciones limitados, como:BTC_USDyETH_USD, etc.; la moneda de cotización de los pares de operaciones esUSD; después de la fijación del código de contrato específico (consulte la funciónexchange.SetContractType), el contrato es un contrato de criptomonedas con margen; los códigos de contrato admitidos incluyen:this_week, next_week, quarteryswap.
    BitMEX Objeto de cambio de futuros el par de operaciones esXBT_USD; después de la fijación del código de contrato específico (consulte la funciónexchange.SetContractType), el contrato es un contrato de criptomonedas con margen; el código de contrato soportado es:XBTUSD
    Futures de Binance Objeto de cambio de futuros apoyar pares de operaciones limitados, tales como:BTC_USDTyETH_USDT, etc.; la moneda de cotización de los pares de negociación esUSD; después de la fijación del código de contrato específico (consulte la funciónexchange.SetContractType), el contrato es unUSDT- contrato con margen; el código del contrato apoyado esswap
    Opciones derivadas Objeto de cambio de futuros los pares de negociación son:BTC_USDyETH_USD; después de la fijación del código de contrato específico (consulte la funciónexchange.SetContractType), el contrato es un contrato de criptomonedas con margen; deben establecerse códigos específicos de contratos de opciones

    Para los objetos de intercambio de futuros en el sistema de backtest, el cambio de pares de negociación no está soportado temporalmente en los códigos de estrategia.

Nivel de simulación

La prueba de retroceso de nivel de simulación se basa en los datos subyacentes de la línea K del sistema de prueba de retroceso, simulando los datos de tick en el marco de los valores del precio más alto, precio más bajo, precio de apertura y precio de cierre de una barra de línea K subyacente dada de acuerdo con un determinado algoritmo.tickdatos cuando se solicita la interfaz.Descripción del mecanismo de prueba posterior de nivel de simulación cuántica FMZ.

Nivel de mercado real

La prueba de retroceso a nivel de mercado real es latickEn el caso de las estrategias basadastickEn el caso de los datos de nivel de mercado real, el uso del nivel de mercado real para backtest está más cerca de la realidad.tickLos datos son datos registrados reales, no simulados. Soporta datos de profundidad, reproducción de datos de registro de las operaciones de mercado, profundidad personalizada y cada dato comercial individual. El tamaño máximo de la prueba de retroceso de datos a nivel de mercado real es de hasta un máximo de 50MB, sin límite en el rango de tiempo de prueba posterior dentro del límite superior del conjunto de datos. Si necesita ampliar el rango de tiempo de prueba posterior tanto como sea posible, puede reducir el valor del equipo de configuración de profundidad de llamada y no utilizar cada dato comercial individual para aumentar el rango de tiempo de prueba posterior.GetDepth,GetTradesEn un momento de los datos del mercado en la línea de tiempo, llamandoGetTicker,GetTrades, GetDepthyGetRecordsno empujará el tiempo varias veces cuando el tiempo se mueve en la línea de tiempo de backtest (lo que no desencadenará un salto al siguiente momento de datos del mercado). Las llamadas repetidas a una de las funciones anteriores empujarán el tiempo de backtest para moverse en la línea de tiempo de backtest (saltar al siguiente momento de datos del mercado). Cuando se utiliza el nivel real del mercado para backtest, no se recomienda elegir un tiempo anterior. Puede que no haya datos de nivel real del mercado en el período de tiempo prematuro.

El backtest de nivel de mercado real apoya actualmente:

  • Binance
  • Se aplicará el método de cálculo de las emisiones de CO2 en el caso de las emisiones de gases de efecto invernadero.
  • La Comisión consideró que la Comisión no tenía motivos para oponerse a las medidas adoptadas por la Comisión.

Optimización de parámetros del sistema de pruebas posteriores

La función de optimización de parámetros del sistema de backtest de la plataforma FMZ Quant Trading es establecer optimizaciones de acuerdo con cada opción de optimización de parámetros durante la backtest, y las opciones se muestran de la siguiente manera:

  • Valor mínimo: para limitar el valor inicial de los parámetros.
  • Valor máximo: para limitar el valor máximo de los parámetros después de cambios incrementales.
  • Tamaño del paso: el valor de la variable incremental de los parámetros.

Generar combinaciones de parámetros, y recorrer todas esas combinaciones para backtest (es decir, backtesting cada combinación de parámetros una vez).NúmeroEl sistema de backtesting puede optimizar el tipo de prueba.

Por ejemplo, establecer opciones de optimización de parámetros en la página de backtest:

img

La prueba posterior del modo de optimización de parámetros:

img

Guardar las configuraciones de prueba de retroceso

En la página de edición de estrategias, en la paginación de Backtest (es decir, el sistema de backtest), puede establecer opciones como configuraciones de backtest y parámetros de estrategia para backtestar la estrategia. Las configuraciones de backtest se refieren al rango de tiempo de backtest, plataforma de intercambio, punto de deslizamiento y tarifa de servicio, etc.; mientras que los parámetros de estrategia se utilizan para establecer opciones de parámetros para estrategias. Cuando las configuraciones de estrategia están todas configuradas, puede backtestar la estrategia de acuerdo con las configuraciones. Entonces, ¿cómo guarda estas configuraciones configuradas para su uso en la siguiente página de backtest (las opciones establecidas durante el refresco de la página se restablecerán)? Puede hacer clic en el botón Guardar configuraciones en la página de estrategia, y todas las configuraciones de backtest (incluidas las configuraciones de backtest y configuraciones de parámetros de estrategia de prueba) se registrarán en forma de código fuente en la página de código de la estrategia de

img

TomarJavaScriptestrategia como ejemplo, y haga clic en Guardar configuraciones de prueba de retroceso en el archivo de origen:

img

Hay ligeras diferencias en Guardar configuraciones de pruebas de retroceso en el archivo fuente entreJavaScript, Python, cppyMylanguage:

/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
'''backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Binance","currency":"BTC_USDT"}]
'''
/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

Mi lenguaje:

(*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
platforms: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
*)

Fuente de datos personalizada

El sistema utiliza elGETmétodo para solicitar una URL personalizada (URL accesible públicamente) para obtener una fuente de datos externa para backtest.

Parámetro Significado Explicación
El símbolo Nombre del símbolo el valor de las acciones de la entidad
El día de Eid Los intercambios como OKCoin_EN
En redondo Precisión de los precios como 3, el precio en los datos devueltos debe multiplicarse por 1000 y redondearse
Alrededor Precisión de las cantidades como 2, la cantidad en los datos devueltos debe multiplicarse por 100 y redondearse
Periodo de tiempo Período de barras (millisegundos) como 60,000 indicando la barra que solicita un minuto
Profundidad Niveles de profundidad 1-20
Negocios Si es necesario dividir datos verdadero/falso
Desde Tiempo de inicio el tiempo de unix
¿Por qué? El tiempo del fin el tiempo de unix

Nota:

Round and V-Round are two parameters designed to avoid losing the precision of floating-point numbers during network transmission. The price data, trading volume and order amount, are all transmitted using integers.

Un ejemplo de los datos cosidos:

http://customserver:80/data?symbol=BTC_USD_OKCoin_EN&eid=OKCoin_EN&round=3&vround=3&period=900000&from=1564315200&to=1567267200

El formato devuelto debe ser uno de los dos formatos siguientes (que el sistema reconocerá automáticamente):

Prueba de retroceso ordinaria a nivel de barra

{
    "schema":["time","open","high","low","close","vol"],
    "data":[[1564315200000,9531300,9531300,9497060,9497060,787],[1564316100000,9495160,9495160,9474260,9489460,338]]
}

Datos de backtest de nivel de tick (incluida la información sobre la profundidad del mercado, una matriz con un formato de profundidad de [precio, volumen]; puede haber múltiples niveles de profundidad; asks se refiere a la orden ascendente del precio y bids se refiere a la orden inversa del precio).

{
    "schema":["time","asks", "bids","trades","close","vol"],
    "data":[[1564315200000,[[9531300,10]], [[9531300,10]],[[1564315200000,0,9531300,10]],9497060,787]]
}

Descripción

El campo Descripción
Esquema Especifica los atributos de las columnas de la matriz de datos, que es sensible a mayúsculas y minúsculas y está limitado a time, open, high, low, close, vol, asks y bids
Datos obtenidos Una matriz que almacena datos por esquema

Formato de datos

El campo Descripción
solicitudes/ofertas [precio, volumen],...]
las operaciones [tiempo, dirección, precio, volumen,...]

Proporcionar datos sobre las tasas de financiación:

Por ejemplo, cuando se realiza la prueba de retroceso de Binance Futures, es necesario tener datos adicionales de la tasa de financiación, que deben proporcionarse por una fuente de datos personalizada.

{
  "detail": {},
  "symbol": "futures_binance.eth_usdt.funding",
  "schema": ["time", "open", "high", "low", "close", "vol"],
  "data": [
    [1582876800000, 25289, 25289, 25289, 25289, 0],
    [1582905600000, 30522, 30522, 30522, 30522, 0],
    [1582934400000, 40998, 40998, 40998, 40998, 0],
        ...
    [1626652800000, 198, 198, 198, 198, 0],
    [1626681600000, 691, 691, 691, 691, 0],                  // The adjacent periodic interval is 8 hours
    [1626710400000, 310, 310, 310, 310, 0],                  // The funding rate of Binance updates every 8 hours, and why the data of the funding rate turns out to be 310?
    [1626739200000, 310, 310, 310, 310, 0],                  // Like the bars data, to avoid losing the precision of floating-point numbers during network transmission, the data uses integer, so the data needs to be processed according to round parameter; the data, returned to the backtest system after processing, is 310 
    [1626768000000, -41610, -41610, -41610, -41610, 0],      // The funding rate might be a negative value
    [1626796800000, -5125, -5125, -5125, -5125, 0],
        ...   
    [1627977600000, 10000, 10000, 10000, 10000, 0]
  ]
}

Un ejemplo de la solicitud de datos del sistema de backtest:

http://customserver:80/data?symbol=futures_binance.eth_usdt.funding&eid=Futures_Binance&round=8&vround=5&depth=20&trades=1&custom=0&period=3600000&from=1360771200&to=1628006400

Ejemplo de fuente de datos personalizada:

Especifique la fuente de datos, URL:http://xxx.xx.x.xx:9090/dataPersonalizar el servidor de datos, escrito en golang:

package main 
import (
    "fmt"
    "net/http"
    "encoding/json"
)

func Handle (w http.ResponseWriter, r *http.Request) {
    // e.g. set on backtest DataSourse: http://xxx.xx.x.xx:9090/data
    // r.URL: /data?depth=20&detail=true&eid=Binance&from=1566820800&period=900000&round=3&symbol=BTC_USDT_Binance&to=1569686400&trades=1&vround=5
    // response
    defer func() {
        // response data
        /* e.g. data
        {
            "schema":["time","open","high","low","close","vol"],
            "data":[
                [1564315200000,9531300,9531300,9497060,9497060,787],
                [1564316100000,9495160,9495160,9474260,9489460,338]
            ]
        }
        */
        ret := map[string]interface{}{
            "schema" : []string{"time","open","high","low","close","vol"},
            "data" : []interface{}{
                []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                []int64{1564316100000,9495160,9495160,9474260,9489460,338},
            },
        }
        b, _ := json.Marshal(ret)
        w.Write(b)
    }()
}

func main () {
    fmt.Println("listen http://localhost:9090")
    http.HandleFunc("/data", Handle)
    http.ListenAndServe(":9090", nil)
}

Estrategia de ensayoJavaScriptEjemplo:

/*backtest
start: 2019-07-28 00:00:00
end: 2019-07-29 00:00:00
period: 1m
platforms: [{"eid":"OKX","currency":"BTC_USDT","feeder":"http://120.24.2.20:9090/data"}]
*/

function main() {
    var ticker = exchange.GetTicker()
    var records = exchange.GetRecords()
    Log(ticker)
    Log(records)
}

Gráficos dibujados por los datos personalizados en el sistema de backtest:

Estrategia Imprimir información:

Motor de pruebas de retroceso local

La plataforma de comercio de FMZ Quant ha sido de código abierto para elJavaScriptLa versión y elPythonversión del motor local de pruebas de retroceso, configuración compatiblePeríodo de la línea K subyacentedurante el backtesting.

teclas de acceso directo de la página de prueba posterior

  • tecla de acceso directo para cambiar entre la página de estrategia Edición y la página Backtesting

    Usa la llave.Ctrl +,para volver a la página Backtest y Edit Strategy.CtrlPresiona la tecla.,.

  • Clave de acceso directo para la estrategia de ahorro

    Usa la llave.Ctrl + spara salvar estrategias.

  • Acceso directo para iniciar la estrategia backtest

    Usa la llave.Ctrl + bpara permitir Comenzar la prueba de retroceso.

Descripción del código

Funciones de entrada

Nombre de la función Descripción
main() Es una función de entrada.
onexit() Es una función de limpieza cuando se sale normalmente, su tiempo máximo de ejecución es de 5 minutos, que puede dejarse sin declarar; si se produce el tiempo de espera, uninterrumpirse informará del error.
onerror() Es una función de salida anormal, su tiempo máximo de ejecución es de 5 minutos, que puede dejarse sin declarar.Pythonycppno soporta esta función.
init() Es una función de inicialización, su programa de estrategia se llamará automáticamente cuando comience a ejecutarse, que puede dejarse sin declarar.
  • Descripción:
    1. El sistema de backtest no admite la funciónonerror().
    1. Si la funciónonerror()se activa en el bot, la funciónonexit()No se activará.

Un exito

onexit(), procesando trabajos de limpieza, con un tiempo máximo de ejecución de 5 minutos, que es realizado por el usuario.

function main(){
    Log("Start running, stop after 5 seconds, and execute onexit function!")
    Sleep(1000 * 5)
}

// onexit function implementation
function onexit(){
    var beginTime = new Date().getTime()
    while(true){
        var nowTime = new Date().getTime()
        Log("The program stops counting down..The cleaning starts and has passed:", (nowTime - beginTime) / 1000, "Seconds!")
        Sleep(1000)
    }
}
import time 
def main():
    Log("Start running, stop after 5 seconds, and execute onexit function!")
    Sleep(1000 * 5)

def onexit():
    beginTime = time.time() * 1000
    while True:
        ts = time.time() * 1000
        Log("The program stops counting down..The cleaning starts and has passed:", (ts - beginTime) / 1000, "Seconds!")
        Sleep(1000)
void main() {
    Log("Start running, stop after 5 seconds, and execute onexit function!");
    Sleep(1000 * 5);
}

void onexit() {
    auto beginTime = Unix() * 1000;
    while(true) {
        auto ts = Unix() * 1000;
        Log("The program stops counting down..The cleaning starts and has passed:", (ts - beginTime) / 1000, "Seconds!");
        Sleep(1000);
    }
}

En el caso de los

El usuario implementa la función de inicializacióninit(), que ejecutará automáticamente la funcióninit()al comienzo de la estrategia para completar la tarea de inicialización.

function main(){
    Log("The first line of the code executed in the program!", "#FF0000")
    Log("Exit!")
}

// Initialization Function
function init(){     
    Log("Initialization!")
}
def main():
    Log("The first line of the code is executed!", "#FF0000")
    Log("Exit!")

def init():
    Log("Initialization!")
void main() {
    Log("The first line of the code is executed!", "#FF0000");
    Log("Exit!");
}

void init() {
    Log("Initialization!");
}

¿Qué pasa?

La ejecución de la funciónonerror()Esta función no admite las estrategias escritas enPythonycpp.

function main() {
    var arr = []
    Log(arr[6].Close)
}

function onerror() {
    Log("error")
}
# not supported by python 
// not supported by C++ 

Marco estratégico clásico

En las estrategias escritas enJavaScript, Pythonycpp, elSleep()En el bot, se utiliza para controlar los intervalos de votación de estrategias, y también controlar la frecuencia de solicitud de acceso a la interfaz API del intercambio.

  • Ejemplos básicos de estrategias de marco de criptomonedas:

    function onTick(){
        //Write strategy logic here, and it will be called constantly, such as printing market information
        Log(exchange.GetTicker())
    }
    
    function main(){
        while(true){
            onTick()
            //The function "Sleep" is mainly used to control the polling frequency of cryptocurrency strategies to prevent accessing the exchange API interafce too frequently 
            Sleep(60000)
        }
    }
    
    def onTick():
        Log(exchange.GetTicker())
    
    def main():
        while True:
            onTick()
            Sleep(60000)
    
    void onTick() {
        Log(exchange.GetTicker());
    }
    
    void main() {
        while(true) {
            onTick();
            Sleep(60000);
        }
    }
    

    Tomemos el ejemplo más simple, si quiero colocar una orden de compra con un precio de 100 y una cantidad de 1 en el intercambio cada segundo, puedo escribirlo así:

    function onTick(){
        // It is just an example; for all the assets will be used to place orders fast during backtest or in the bot, do not implement the example in the bot
        exchange. Buy(100, 1)
    }
    
    function main(){
        while(true){
            onTick()
            // The pause period can be customized in millisecond (1 second = 1000 milliseconds)
            Sleep(1000)
        }
    }
    
    def onTick():
        exchange.Buy(100, 1)
    
    def main():
        while True:
            onTick()
            Sleep(1000)
    
    void onTick() {
        exchange.Buy(100, 1);
    }
    
    void main() {
        while(true) {
            onTick();
            Sleep(1000);
        }
    }
    

Biblioteca de plantillas

Elbiblioteca de plantillases un módulo de código reutilizable en la plataforma de negociación FMZ Quant, que funciona como una categoría de códigos de estrategia de negociación.Biblioteca de plantillas, una plantilla se agrega en la página Estrategia de la cuenta que actualmente se ha iniciado sesión en la plataforma FMZ Quant Trading.

Biblioteca de plantillas enJavaScript:

img

Biblioteca de plantillas enPython:

img

Biblioteca de plantillas encpp:

img

  • Función de exportación de Biblioteca de plantillas La función de exportación es una función de interfaz de Biblioteca de plantillas, y puede ser llamada por la estrategia que hace referencia a Biblioteca de plantillas.

    /*
    -- This method is called directly with $.Test() after the strategy refers to the template
    -- The "main" function will not be triggered in the strategy, and it is only used as the entry point for template debugging
    */
    $.Test = function() {
        Log('Test')
    }
    
    function main() {
        $.Test()
    }
    
    def Test():
        Log("template call")
    
    # Export "Test" function; the main strategy can be called by ext.Test()
    ext.Test = Test 
    
    // The strategy refers to the template and calls this method directly with ext::Test()
    void Test() {
        Log("template call");
    }
    
  • Biblioteca de plantillas parámetros Biblioteca de plantillas también puede establecer sus propios parámetros de interfaz, que se utilizan en forma de variables globales en el código de Biblioteca de plantillas.

    Configuración de parámetros de la biblioteca de plantillas:

    img

    Códigos de la biblioteca de plantillas:

    $.SetParam1 = function(p1) {
        param1 = p1
    }
    
    $.GetParam1 = function() {
        Log("param1:", param1)
        return param1
    }
    
    def SetParam1(p1):
        global param1
        param1 = p1
    
    def GetParam1():
        Log("param1:", param1)
        return param1
    
    ext.SetParam1 = SetParam1
    ext.GetParam1 = GetParam1
    
    void SetParam1(float p1) {
        param1 = p1;
    }
    
    float GetParam1() {
        Log("param1:", param1);
        return param1;
    }
    

    Consulte el código de estrategia en elBiblioteca de plantillasejemplo mencionado anteriormente:

    function main () {
        Log("call $.GetParam1:", $.GetParam1())
        Log("call $.SetParam1:", "#FF0000")
        $.SetParam1(20)
        Log("call $.GetParam1:", $.GetParam1())
    }
    
    def main():
        Log("call ext.GetParam1:", ext.GetParam1())
        Log("call ext.SetParam1:", "#FF0000")
        ext.SetParam1(20)
        Log("call ext.GetParam1:", ext.GetParam1())
    
    void main() {
        Log("call ext::GetParam1:", ext::GetParam1());
        Log("call ext::SetParam1:", "#FF0000");
        ext::SetParam1(20);
        Log("call ext::GetParam1:", ext::GetParam1());
    }
    

    img

  • Cita Biblioteca de plantillas

    Después de comprobar la referencia en la columna de plantilla de la página de edición de la estrategia, guarde la estrategia.

    img

Estructura integrada

Variables globales

Intercambio

ExchangeEl objeto de intercambio se considera como el primer objeto de intercambio añadido en los parámetros de la estrategia.

  • Añadir objetos de intercambio en Backtest

  • Añadir objetos de intercambio en la página Bot

Los objetos de intercambio añadidos corresponden a laexchangeobjetos en el código:

function main() {
    Log("The name of the first exchange object added on the bot page or backtest page:", exchange.GetName(), ", Label:", exchange.GetLabel())
}
def main():
    Log("The name of the first exchange object added on the bot page or backtest page:", exchange.GetName(), ", Label:", exchange.GetLabel())
void main() {
    Log("The name of the first exchange object added on the bot page or backtest page:", exchange.GetName(), ", Label:", exchange.GetLabel());
}
Los intercambios

Se puede entender como una matriz que almacena todos los objetos de intercambio comoexchangeobjetos de intercambio, que pueden contener múltiples objetos de intercambio;exchanges[0]esexchange.

Los objetos de intercambio añadidos corresponden aexchanges[0], exchanges[1], exchanges[2]... y así sucesivamente en el código de estrategia.

function main() {
    for(var i = 0; i < exchanges.length; i++) {
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "Label:", exchanges[i].GetLabel())
    }
}
def main():
    for i in range(len(exchanges)):
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "Label:", exchanges[i].GetLabel())
void main() {
    for(int i = 0; i < exchanges.size(); i++) {
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "Label:", exchanges[i].GetLabel());
    }
}
Estado de la orden

El atributoStatusEn elOrder structure.

Nombre constante Definición Valor
El estado de la orden está pendiente no terminado 0
Se ha cerrado el proceso de entrega. terminado 1
El estado de la orden está cancelado. cancelado 2
El estado de la orden es desconocido. estado desconocido (otros estados) 3

El estado de la orden es desconocido.El estado puede llamarexchange.GetRawJSON()para obtener la información de estado del pedido original, consultar el archivo de intercambio y ver la descripción específica. Los nombres constantes del formulario pueden utilizarse directamente en el código de estrategia para comparar con el atributoStatusEn elOrderLa impresión de los nombres de las constantes mostrará el estado de los ordenes.nombres constantesy sus correspondientesvalores, y otros nombres constantes abajo funcionan de la misma manera, por lo que no habrá descripciones más detalladas sobre ellos.

Tipo de operación de orden

El atributoTypeEn elOrder structure.

Nombre constante Definición Valor
El valor de las operaciones de compra y venta Orden de compra 0
El valor de las operaciones de transferencia Orden de venta 1
Tipo de posición

El atributoTypeEn elPosition structure.

Nombre constante Definición Descripción Aplicable Valor
Se trata de un sistema de gestión de datos. Posición larga Uso de futuros de criptomonedasexchange.SetDirection("closebuy")para establecer la dirección de la posición de cierre, y cerrar este tipo de posiciones Futuros de criptomonedas 0
PD_SHORT Posición corta Uso de futuros de criptomonedasexchange.SetDirection("closesell")para establecer la dirección de la posición de cierre, y cerrar este tipo de posiciones Futuros de criptomonedas 1
Direcciones de apertura y cierre de las posiciones de futuros

El atributoOffsetEn elOrder structure.

Nombre constante Definición Valor
Se puede utilizar el código de código de la aplicación. Ordenes de posiciones abiertas 0
Se puede utilizar el código de código de la aplicación. Ordenes de cierre de posiciones 1
Parámetros de la estrategia

En los códigos de estrategia de negociación, los parámetros de estrategia establecidos en la interfaz de estrategia se reflejan en forma de variables globales.JavaScriptEn la interfaz de estrategia, el lenguaje puede acceder directamente a los valores de parámetros establecidos o modificados.Pythonestrategias, la palabra claveglobalEl objetivo de la estrategia es modificar las variables globales de la misma.

Tipo de parámetro:

img

Variable Descripción Las observaciones Tipo de producto Valor por defecto Descripción
Número Tipo numérico Las observaciones Número (número) 1 La estrategia en C++ es un tipo de coma flotante
Cuadrícula la cuerda Las observaciones Cuadrícula (cuadrícula) Hola FMZ El valor predeterminado no necesita ser citado. La entrada se trata como una cadena
Envases ComboBox Las observaciones ComboBox (seleccionado) 1|2|3 La variable combobox en sí es un valor numérico, que representa el índice de la columna seleccionada por el control Combobox. El valor del primer ComboBox es 1, y los demás es 0, y así sucesivamente
- ¿ Qué? Opciones de verificación Las observaciones Boolean (verdadero/falso) Es cierto Si se comprueba, la variable bool es verdadera; si no se comprueba, la variable bool es falsa
SecretoString Cuadrícula cifrada Las observaciones Cuadrícula cifrada (cuadrícula) Contraseña Con el mismo uso que una cadena, la cadena cifrada se enviará por cifrado y no se transmitirá en texto plano
  • Los parámetros de interfaz se establecen en la sección de parámetros de estrategia debajo de la sección de edición de código de la página de edición de estrategia.
  • Los parámetros de interfaz existen como variables globales en el código de estrategia, es decir, los parámetros de interfaz se pueden modificar en el código.
  • Los nombres de las variables de los parámetros de interfaz en el código de estrategia (véase el formulario anterior):number, string, combox, bool, secretString.
  • Opción de descripción: los nombres de los parámetros de la interfaz en la interfaz de estrategia.
  • Opción de observación: la descripción detallada de los parámetros de la interfaz; la descripción se mostrará cuando el ratón pase sobre los parámetros de la interfaz.
  • Opción de tipo: el tipo de parámetros de la interfaz.
  • Opción de valor predeterminado: los valores predeterminados de los parámetros de la interfaz.

Configuración de dependencia de parámetros: Un parámetro puede ser establecido para permitir que otro parámetro se muestre y oculte en función de la selección del parámetro.numberA, que es un tipo numérico.numberAse muestran o ocultan basado en si el parámetroisShowA(tipo booleano) es verdadero o falso.numberAen los parámetros de interfaz como:numberA@isShowA.

img

De esta manera, si el parámetroisShowAno se comprueba, el parámetronumberAEn cuanto a los parámetros del tipo de control ComboBox, la parte dependiente de los parámetros es juzgar si el valor del parámetro es igual al valor de lavalor del índiceDe la misma manera, tomar parámetroisShowACuando se establecen las variables en los parámetros, escribir:numberA@combox==2. El parámetronumberAmostrará o ocultará, según si el parámetrocomboxse comprobará que es la tercera opción (donde el índice 0 corresponde a la primera opción, el índice 1 corresponde a la segunda y el índice 2 corresponde a la tercera).

Parámetros de interfaz de estrategia, controles interactivos y función de agrupación de parámetros en Template: Sólo añade(?First group)al comienzo de la descripción del parámetro que inicia la agrupación, tal como se muestra en la figura siguiente:

img

Cuando se utiliza la estrategia, los parámetros se muestran en grupos:

img

Guardar el valor predeterminado del parámetro: Los parámetros de la estrategia se muestran en la figura. Durante la prueba de retroceso, si desea guardar los valores predeterminados de los parámetros de la estrategia, puede hacer clic en elSave settingsbotón después de modificar los parámetros de la estrategia.

img

img

Puede guardar la configuración de parámetros de estrategia en forma de código:

/*backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",2],["string","Hello FMZ.COM"],["combox",2],["bool",false],["numberA@isShowA",666],["isShowA",true]]
*/
'''backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",2],["string","Hello FMZ.COM"],["combox",2],["bool",false],["numberA@isShowA",666],["isShowA",true]]
'''
/*backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",2],["string","Hello FMZ.COM"],["combox",2],["bool",false],["numberA@isShowA",666],["isShowA",true]]
*/

Estructura de datos

Algunas funciones estarán acompañadas del originalJSONdatos solicitados durante la llamada.JSONLos datos se almacenan en el atributoInfoDado que el backtest no es para acceder a una interfaz de plataforma, los datos devueltos durante el backtest no tienen ningún atributoInfoLa siguiente es una descripción de los principales atributos de cada estructura de datos.

Comercio

Obtener todo el historial de operaciones (no el mismo), devuelto por la funciónexchange.GetTrades().

{
    Id      : 9585306,          // Trading record ID; if the exchange interface does not provide order ID, use the timestamp to fill in 
    Time    : 1567736576000,    // Time (Unix timestamp milliseconds)
    Price   : 1000,             // Price
    Amount  : 1,                // Volume
    Type    : 0                 // Order Type; refer to the order type in the constants; 0 is ORDER_TYPE_BUY, meaning the value of ORDER_TYPE_BUY is 0
}
El tick

Las cotizaciones de mercado son devueltas por la funciónexchange.GetTicker().

{
    Info    : {...},             // After requesting the platform interface, this attribute is not available in the raw data that the exchange interface responds to, during the backtest
    High    : 1000,              // Highest price; if the platform interface does not provide the 24-hour highest price, use sell price 1 to fill in 
    Low     : 500,               // Lowest price; if the platform interface does not provide the 24-hour lowest price, use buy price 1 to fill in 
    Sell    : 900,               // Sell price 1
    Buy     : 899,               // Buy price 1 
    Last    : 900,               // Last executed price
    Volume  : 10000000,          // Recent trading volume; in principle, the unit of spot trading volume is base currency, and the unit of futures trading volume is contract quantity. If the platform interface does not provide this kind of data, use the existing data of the platform interface to fill in; for instance, it might be a trading volume in the unit of quote currency  
    Time    : 1567736576000      // Millisecond-level timestamp
}
Registro

La normaOHLCLa estructura se utiliza para dibujar K-líneas y el cálculo y análisis de indicadores de proceso.exchange.GetRecords()devuelve la matriz de estructuras.Recordla estructura representa una barra de k líneas, es decir, una línea kBAREl.TimeEn elRecordes la hora de inicio del período de barras de la línea K.

{
    Time    : 1567736576000,     // A timestamp, accurate to millisecond, in the same format as the result obtained by Javascript's newDate().GetTime()
    Open    : 1000,              // Open price
    High    : 1500,              // Highest price
    Low     : 900,               // Lowest price
    Close   : 1200,              // Close price 
    Volume  : 1000000            // Trading volume; in principle, the unit of spot trading volume is base currency, and the unit of futures trading volume is contract quantity. If the platform interface does not provide this kind of data, use the existing data of the platform interface to fill in; for instance, it might be a trading volume in the unit of quote currency
}
El orden

La estructura de orden puede ser devuelta por funciones, incluyendoexchange.GetOrder()yexchange.GetOrders(). La funciónexchange.GetOrders()devuelve la matriz o una matriz vacía de la estructura (si no hayorden pendiente sin terminar, regresar[], es decir, una matriz vacía).

{
    Info        : {...},         // After requesting the platform interface, this attribute is not available in the raw data that the exchange interface responds to, during the backtest
    Id          : 123456,        // Unique ide