En la carga de los recursos... Cargando...

Las instrucciones de la API FMZ

El autor:No hay nada, Creado: 2020-04-20 10:19:00, Actualizado: 2023-04-12 14:44:56

en los últimos 10 registros y borrar el resto LogReset (Restablecer el registro)
}


```Python
def main():
    LogReset(10)
void main() {
    LogReset(10);
}

LogVacuum (en inglés)

LogVacuum(), después de llamar a laLogReset()Función para limpiar el registro, recupera el espacio de almacenamiento ocupado porEs muy bueno.La función no devuelve ningún valor. La razón es queSQLiteno recupera el espacio ocupado al eliminar datos, por lo que necesita realizarVACUUMCuando se llama esta función, la operación de movimiento de archivo se producirá con un gran retraso. Se recomienda llamarla en un intervalo de tiempo apropiado.

API de cotizaciones de mercado

Las principales funciones de la interfaz de mercado:

Nombre de la función Descripción
¿ Qué haces? Obtener datos de citas de ticks
Obtener registros Obtener datos de la línea K.
Obtener Profundidad Obtener datos del libro de pedidos (datos de profundidad de pedidos)
Obtener Trades Obtener los últimos registros de operaciones en el mercado

Las siguientes funciones se pueden llamar a través deexchangeo bienexchanges[0]objetos; por ejemplo: funciones, comoexchange.GetTicker();o bienexchanges[0].GetTicker();, devuelve las cotizaciones de mercado de los pares de operaciones actuales y los contratos de fijación.

Consejos importantes para llamar funciones API con acceso a la red:Cuando se llama a cualquier función API que accede a una interfaz de plataforma (comoexchange.GetTicker(), exchange.Buy(Price, Amount), exchange.CancelOrder(Id)Por lo tanto, debemos hacer un procesamiento tolerante a fallos para la llamada de estas funciones.exchange.GetTicker()La función de obtención de datos de mercado puede, debido a problemas en los servidores de la plataforma y problemas de transmisión de la red, etc., provocar que el valor de retorno de los datos de mercado se reduzca.exchange.GetTicker()la función esnullEntonces, el valor de retorno deexchange.GetTicker()El tratamiento de los datos debe realizarse mediante un procesamiento tolerante a fallos.

Los datos devueltos por elexchange.GetTicker()La función en el código siguiente se asigna a latickerLa variabilidad de la velocidad de un motor es variable, y necesitamos tratar con la tolerancia a fallas antes de utilizar elticker variable.

function main() {
    var ticker = exchange.GetTicker()
    if(!ticker){
        // Recall once, or use other processing logic
        ticker = exchange.GetTicker()
    }
}
def main():
    ticker = exchange.GetTicker()
    if not ticker:
        ticker = exchange.GetTicker()
void main() {
    auto ticker = exchange.GetTicker();
    if(!ticker.Valid) {
        ticker = exchange.GetTicker();
        Log("Test");
    }
}

Además, para las pruebas de rendimiento de la estrategia en materia de tolerancia a fallos, FMZ ha añadido específicamente unamodo tolerante a fallosEl sistema de backtest puede devolver aleatoriamente algunas llamadas de API que ocurrirán cuando se accede a la red de acuerdo con los parámetros establecidos, y devolver los valores de retorno de algunas llamadas fallidas. Puede probar rápidamente la robustez del programa en el bot. Cambiar a la página del sistema de backtest en la página de edición de la estrategia, haga clic en eltriángulo invertidocontrol desplegable en el lado derecho del botón Start Backtest, y el botón Backtest Fault Tolerant aparecerá.

El cambio.GetTicker ((()

exchange.GetTicker()Obtiene las cotizaciones de mercado actuales de los pares y contratos de negociación actuales, con el valor de rendimiento:Tickerla estructura. En el sistema de backtest, elTickerdatos devueltos por elexchange.GetTicker()función, dondeHighyLowson valores simulados, tomados desde el momento actual de venta 1 y compra 1 en el bot. La criptomoneda en funcionamiento real es el precio más alto y el precio más bajo en un cierto período definido por el intercambioTick interface.

function main(){
    var ticker = exchange.GetTicker()
    /*
        The platform interface may not be accessible due to network problems (even if the device's docker program can open the platform website, the API may not be accessible)
        At this time, ticker is null, when accessing ticker. When it is "High", it will cause an error; so when testing, ensure that you can access the platform interface
    */
    Log("High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Volume:", ticker.Volume)
}
def main():
    ticker = exchange.GetTicker()
    Log("High:", ticker["High"], "Low:", ticker["Low"], "Sell:", ticker["Sell"], "Buy:", ticker["Buy"], "Last:", ticker["Last"], "Volume:", ticker["Volume"])
void main() {
    auto ticker = exchange.GetTicker();
    Log("High:", ticker.High, "Low:", ticker.Low, "Sell:", ticker.Sell, "Buy:", ticker.Buy, "Last:", ticker.Last, "Volume:", ticker.Volume);
}

En el bot real (no backtest), elInfoatributo en el valor de retorno de laexchange.GetTicker()La función almacena los datos originales devueltos cuando se llama la interfaz.

El cambio.GetDepth()

exchange.GetDepth()Obtiene los datos del libro de órdenes de cambio de los pares y contratos de negociación actuales.Depth structure.

Depthestructura contiene dos conjuntos de estructuras, a saber,Asks[]yBids[], AsksyBidscontener las siguientes variables estructurales:

Tipo de datos Nombre de la variable Descripción
Número Precio precio
Número Importe cantidad

Por ejemplo, si quiero obtener el precio de segunda venta actual, puedo escribir el código así:

function main(){
    var depth = exchange.GetDepth()
    /*
       The platform interface may not be accessible due to network reasons (even if the device's docker program can open the platform website, the API may not be accessible)
       At this time, depth is null. When accessing depth.Asks[1].Price, it will cause an error; so when testing, ensure that you can access the platform interface
    */
    var price = depth.Asks[1].Price
    Log("Sell 2 price is:", price)
}
def main():
    depth = exchange.GetDepth()
    price = depth["Asks"][1]["Price"]
    Log("Sell 2 price is:", price)
void main() {
    auto depth = exchange.GetDepth();
    auto price = depth.Asks[1].Price;
    Log("Sell 2 price is:", price);
}

En cambio.GetTrades ((()

exchange.GetTrades()Obtiene el historial de operaciones de la plataforma (no el suyo).TradeLos datos específicos devueltos dependen de los registros comerciales dentro del rango, de acuerdo con circunstancias específicas. Los datos devueltos son una matriz, donde la secuencia de tiempo de cada elemento es la misma que la secuencia de datos devueltos delexchange.GetRecordsfunción, es decir, el último elemento de la matriz es los datos más cercanos a la hora actual.

// In the simulated backtest, the data is empty; to have a trading history, there must be a real bot running
function main(){
    var trades = exchange.GetTrades()
    /*
        The platform interface may not be accessible due to network reasons (even if the device's docker program can open the platform website, the API may not be accessible)
        At this time, "trades" is null. When accessing trades[0].Id, it will cause an error; so when testing, ensure that you can access the platform interface
    */
    Log("id:", trades[0].Id, "time:", trades[0].Time, "Price:", trades[0].Price, "Amount:", trades[0].Amount, "type:", trades[0].Type)
}
def main():
    trades = exchange.GetTrades()
    Log("id:", trades[0]["Id"], "time:", trades[0]["Time"], "Price:", trades[0]["Price"], "Amount:", trades[0]["Amount"], "type:", trades[0]["Type"])
void main() {
    auto trades = exchange.GetTrades();
    Log("id:", trades[0].Id, "time:", trades[0].Time, "Price:", trades[0].Price, "Amount:", trades[0].Amount, "type:", trades[0].Type);
}

El intercambio.GetRecords ((()

exchange.GetRecords(Period)devuelve datos de línea K. período de línea K se especifica al crear el bot; si especifica los parámetros cuando elexchange.GetRecords()Si no hay un parámetro especificado, los datos de línea K se devuelven de acuerdo con el período de línea K establecido en los parámetros del bot o el período de línea K establecido en la página de backtest.

ParámetroPeriod:

  • PÉRIODO_M1: se refiere a 1 minuto
  • PÉRIODO_M5: se refiere a 5 minutos
  • PÉRIODO_M15: se refiere a 15 minutos
  • PÉRIODO_M30: se refiere a 30 minutos
  • PÉRIODO_H1: se refiere a 1 hora
  • PÉRIODO_D1: se refiere a 1 día El valor del parámetro dePeriodsólo puede pasar los períodos estándar definidos anteriormente, pero también puede pasar números, en la unidad de segundo.

El valor de retorno deexchange.GetRecords(Period)Función: El valor de retorno es una matriz deRecordEn el caso de las estructuras, los datos de línea K devueltos se acumularán con el tiempo, el límite superior de las barras de línea K acumuladas se ve afectado por laexchange.SetMaxBarLenEl límite superior predeterminado es de 5000 barras de la línea K cuando no está establecido. Cuando los datos de la línea K alcanzan el límite de acumulación de la barra de la línea K, se actualizarán agregando una barra de la línea K y eliminando la barra de la línea K más temprana (por ejemplo, cola de entrada/salida).

Número de barras de línea K recogidas cuando elGetRecordsLa función se llama inicialmente.

  • Las primeras 1000 barras de la línea K en el momento de inicio del período de backtesting se toman por adelantado en el sistema de backtesting como datos iniciales de la línea K.
  • El número específico de barras de línea K que se adquieren durante el bot real se basa en la cantidad máxima de datos que puede adquirir la interfaz de línea K del intercambio.

Para elexchange.GetRecords(Period)La función, el bot y el backtest decriptomonedaambos soportan períodos personalizados, y el parámetroPeriodes el número de segundos. Por ejemplo:

function main() {
    // Print K-line data with a K-line period of 120 seconds (2 minutes)
    Log(exchange.GetRecords(60 * 2))         
    // Print K-line data with a K-line period of 5 minutes
    Log(exchange.GetRecords(PERIOD_M5))      
}
def main():
    Log(exchange.GetRecords(60 * 2))
    Log(exchange.GetRecords(PERIOD_M5))
void main() {
    Log(exchange.GetRecords(60 * 2)[0]);
    Log(exchange.GetRecords(PERIOD_M5)[0]);
}

ConfiguraciónPeriodel parámetro a 5 es para solicitar datos de línea K con un período de 5 segundos. Si elPeriodel parámetro no se divide uniformemente por 60 (es decir, el período representado es un período de minutos no disponibles), la capa inferior del sistema utiliza la interfaz correspondiente deGetTradesobtener datos de registros de operaciones y sintetizar los datos de línea K requeridos. Si elPeriodel parámetro se divide uniformemente por 60, entonces los datos de línea K requeridos se sintetizan utilizando un mínimo de datos de línea K de 1 minuto (usando un período más largo para sintetizar los datos de línea K requeridos si es posible).

function main(){
    var records = exchange.GetRecords(PERIOD_H1)
    /*
        The platform interface may not be accessible due to network reasons (even if the device's docker program can open the platform website, the API may not be accessible)
        At this time, "records" is null. When accessing records[0].Time, it will cause an error; so when testing, ensure that you can access the platform interface
    */
    Log("The first k-line data is, Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High)
    Log("The second k-line data is, Time:", records[1].Time ,"Close:", records[1].Close)
    Log("Current K-line (latest)", records[records.length-1], "Current K-line (latest)", records[records.length-2])
}
def main():
    records = exchange.GetRecords(PERIOD_H1)
    Log("The first k-line data is, Time:", records[0]["Time"], "Open:", records[0]["Open"], "High:", records[0]["High"])
    Log("The second k-line data is, Time:", records[1]["Time"], "Close:", records[1]["Close"])
    Log("Current K-line (latest)", records[-1], "Current K-line (latest)", records[-2])
void main() {
    auto records = exchange.GetRecords(PERIOD_H1);
    Log("The first k-line data is, Time:", records[0].Time, "Open:", records[0].Open, "High:", records[0].High);
    Log("The second k-line data is, Time:", records[1].Time, "Close:", records[1].Close);
    Log("Current K-line (latest)", records[records.size() - 1], "Current K-line (latest)", records[records.size() - 2]);
}

exchange.GetRecords()La función tiene dos condiciones para obtener datos de línea K:

  • El intercambio proporciona una interfaz de datos de línea K. En este caso, los datos adquiridos son los datos enviados directamente por el intercambio.

  • El intercambio no proporciona una interfaz de datos de línea K. El programa FMZ docker obtiene los últimos registros comerciales del intercambio cada vez que el programa de estrategia llamaexchange.GetRecords(), es decir, se llama elexchange.GetTrades()Función para obtener datos y sintetizar datos de línea K.

La prueba de retroceso a nivel de simulación en el sistema debe establecer elperíodo de la línea K subyacente(cuando el sistema de backtesting simula el nivel de backtesting, los datos de línea K correspondientes se utilizan para generar datos de tick de acuerdo con el conjuntoperíodo de la línea K subyacente); cabe señalar que el período de los datos de la línea K obtenidos en la estrategia no puede ser inferior ael período de la línea K subyacentePorque en el backtest de nivel de simulación, los datos de la línea K de cada período se sintetizan por los datos de la línea K correspondientes a los períodos de la línea K subyacentes en el sistema de backtest.

En elcpplenguaje, si necesita construir sus propios datos de línea K, hay los siguientes ejemplos de código:

#include <sstream>
void main() { 
    Records r;
    r.Valid = true;
    for (auto i = 0; i < 10; i++) {
        Record ele;
        ele.Time = i * 100000;
        ele.High = i * 10000;
        ele.Low = i * 1000;
        ele.Close = i * 100;
        ele.Open = i * 10;
        ele.Volume = i * 1;
        r.push_back(ele);
    }
    // Output display: Records[10]
    Log(r);                      
    auto ma = TA.MA(r,10);       
    // Output display: [nan,nan,nan,nan,nan,nan,nan,nan,nan,450]
    Log(ma);                     
}

cambio.GetPeriod (()

Elexchange.GetPeriod()función devuelve el período de línea K establecido en la página web de la plataforma FMZ cuando se ejecutan estrategias enPrueba posteriorybot (bot)El valor de retorno es un número entero en la unidad de segundo.

function main() {
    // For example, in the backtest and bot, set the K-line period on the website page of FMZ platform to 1 hour
    var period = exchange.GetPeriod()
    Log("K-line period:", period / (60 * 60), "hour")
}
def main():
    period = exchange.GetPeriod()
    Log("K-line period:", period / (60 * 60), "hour")
void main() {
    auto period = exchange.GetPeriod();
    Log("K-line period:", period / (60 * 60.0), "hour");
}

En cambio. SetMaxBarLen ((Len)

Elexchange.SetMaxBarLen(Len)la función afecta a dos aspectos durante el tiempo de ejecución de la estrategia de criptomonedas:

  • afectando al número de barras de línea K (BAR) obtenidas por primera vez.
  • afectando al límite superior de las barras de línea K (BAR).
function main() {
    exchange.SetMaxBarLen(50)
    var records = exchange.GetRecords()
    Log(records.length, records)
}
def main():
    exchange.SetMaxBarLen(50)
    r = exchange.GetRecords()
    Log(len(r), r)
void main() {
    exchange.SetMaxBarLen(50);
    auto r = exchange.GetRecords();
    Log(r.size(), r[0]);
}

¿Qué está pasando?

exchange.GetRawJSON()devuelve el contenido en bruto (cuadros) devuelto por el últimoRESTrequisito, que se puede utilizar para analizar los datos por usted mismo. Valor de retorno: tipo de cadena, válido solo en el entorno de negociación en vivo de criptomonedas. Backtest no admite la función. Las estrategias encppEl lenguaje no soporta la función.

function main(){
    exchange.GetAccount(); 
    var obj = JSON.parse(exchange.GetRawJSON());
    Log(obj);
}
import json
def main():
    exchange.GetAccount()
    obj = json.loads(exchange.GetRawJSON())
    Log(obj)
void main() {
    auto obj = exchange.GetAccount();
    // C++ doe not support "GetRawJSON" function
    Log(obj);
}

El cambio.GetRate()

exchange.GetRate()devuelve los tipos de cambio de la moneda actualmente utilizada en el intercambio y la moneda de precios actualmente mostrada, y un valor devuelto de 1 indica que la conversión de tipos de cambio está desactivada.

Nota:

  • Si esexchange.SetRate()No se ha llamado a establecer el tipo de cambio, el valor del tipo de cambio devuelto porexchange.GetRate()es 1 por defecto, es decir, la conversión del tipo de cambio que se muestra actualmente no se ha intercambiado.
  • Si elexchange.SetRate()se ha utilizado para establecer un valor de tipo de cambio, por ejemplo:exchange.SetRate(7), entonces toda la información de precios del objeto de cambio actual que representa la moneda en circulación de la plataforma de negociación, como cotizaciones, profundidad, precios de orden, etc., se multiplicará por el tipo de cambio 7 previamente establecido para la conversión.
  • Si elexchangecorresponde a un intercambio con USD como moneda de fijación de precios, después de llamarexchange.SetRate(7), todos los precios del bot se convertirán a precios cercanos al yuan por multiplicación por 7.exchange.GetRate()es 7.

En cambio. Obtener USDCNY ((()

exchange.GetUSDCNY()Devuelve el último tipo de cambio del dólar estadounidense (fuente de datos proporcionada poryahooEl valor devuelto: tipo numérico.

intercambio.Conjunto de datos (clave, valor)

Elexchange.SetData(Key, Value)La función se utiliza para establecer los datos cargados en el momento en que se ejecuta la estrategia, que puede ser cualquier indicador económico, datos de la industria, índice relevante, etc. Se puede utilizar para cuantificar toda la información cuantificable para las estrategias comerciales y también apoyar el uso en el sistema de backtest.

Método de llamada deexchange.SetData(Key, Value)Función:

  • Escribir datos directamente en la estrategia El formato de los datos es el siguiente:datavariable en el siguiente ejemplo.

    /*backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
    function main() {
        var data = [
            [1579536000000, "abc"],
            [1579622400000, 123],
            [1579708800000, {"price": 123}],
            [1579795200000, ["abc", 123, {"price": 123}]]
        ]
        exchange.SetData("test", data)
        while(true) {
            Log(exchange.GetData("test"))
            Sleep(1000)
        }
    }
    
    '''backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    '''  
    
    def main():
        data = [
            [1579536000000, "abc"],
            [1579622400000, 123],
            [1579708800000, {"price": 123}],
            [1579795200000, ["abc", 123, {"price": 123}]]
        ]
        exchange.SetData("test", data)
        while True:
            Log(exchange.GetData("test"))
            Sleep(1000)
    
    /*backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */  
    
    void main() {
        json data = R"([
            [1579536000000, "abc"],
            [1579622400000, 123],
            [1579708800000, {"price": 123}],
            [1579795200000, ["abc", 123, {"price": 123}]]
        ])"_json;
        
        exchange.SetData("test", data);
        while(true) {
            Log(exchange.GetData("test"));
            Sleep(1000);
        }
    }
    

    Cuando se ejecute el código de ensayo anterior, se obtendrán los datos correspondientes en el momento correspondiente, como se muestra en la figura:

    img

    Como podemos ver, el tiempo correspondiente de la marca de tiempo1579622400000es2020-01-22 00: 00: 00; cuando el programa de estrategia se ejecute después de este tiempo, antes de la siguiente fecha y hora de los datos1579708800000, es decir, antes de la2020-01-23 00: 00: 00Llama a laexchange.GetData(Source)La función para obtener los datos. Todo lo obtenido es el contenido de[1579622400000, 123]A medida que el programa continúa ejecutándose y el tiempo cambia, obtener datos pieza por pieza datos como este.

  • Solicitar datos a través de enlaces externos

    Formato de datos solicitado

    {
        "schema":["time","data"],
        "data":[
            [1579536000000, "abc"],
            [1579622400000, 123],
            [1579708800000, {"price": 123}],
            [1579795200000, ["abc", 123, {"price": 123}]]
        ]
    }
    

    ¿Dónde está?schemaes el formato de datos de cada registro en el cuerpo principal de los datos cargados, el formato se fija como["time", "data"], correspondiente a ladataEl formato de los atributos de los datos uno por uno.datael atributo almacena el cuerpo principal de los datos, y cada pieza de los datos está compuesta por marcas de tiempo y contenido de datos a nivel de milisegundos (el contenido de los datos puede ser cualquier dato codificado en JSON).

    El programa de servicio para las pruebas está escrito enGoLenguaje:

    package main
    import (
        "fmt"
        "net/http"
        "encoding/json"
    )  
    
    func Handle (w http.ResponseWriter, r *http.Request) {
        defer func() {
            fmt.Println("req:", *r)
            ret := map[string]interface{}{
                "schema": []string{"time","data"},
                "data": []interface{}{
                    []interface{}{1579536000000, "abc"},
                    []interface{}{1579622400000, 123},
                    []interface{}{1579708800000, map[string]interface{}{"price":123}},
                    []interface{}{1579795200000, []interface{}{"abc", 123, map[string]interface{}{"price":123}}},
                },
            }
            b, _ := json.Marshal(ret)
            w.Write(b)
        }()
    }  
    
    func main () {
        fmt.Println("listen http://localhost:9090")
        http.HandleFunc("/data", Handle)
        http.ListenAndServe(":9090", nil)
    }
    

    Después de recibir la solicitud, el programa responde a los datos:

    {
        "schema":["time","data"],
        "data":[
            [1579536000000, "abc"],
            [1579622400000, 123],
            [1579708800000, {"price": 123}],
            [1579795200000, ["abc", 123, {"price": 123}]]
        ]
    }
    

    Código de la estrategia de ensayo:

    /*backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
    function main() {
        while(true) {
            Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
            Sleep(1000)
        }
    }
    
    '''backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    '''  
    
    def main():
        while True:
            Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
            Sleep(1000)
    
    /*backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */  
    
    void main() {
        while(true) {
            Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"));
            Sleep(1000);
        }
    }
    

intercambio.GetData ((Fuente)

Elexchange.GetData(Source)La función se utiliza para obtener los datos cargados por elexchange.SetData(Key, Value)Los datos se obtienen en un momento durante la prueba de retroceso, y los datos se almacenan en caché durante un minuto durante la negociación real.

  • Obtención del método de llamada de datos escritos directamente

    /*backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
    function main() {
        exchange.SetData("test", [[1579536000000, _D(1579536000000)], [1579622400000, _D(1579622400000)], [1579708800000, _D(1579708800000)]])
        while(true) {
            Log(exchange.GetData("test"))
            Sleep(1000 * 60 * 60 * 24)
        }
    }
    
    '''backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    '''  
    def main():
        exchange.SetData("test", [[1579536000000, _D(1579536000000/1000)], [1579622400000, _D(1579622400000/1000)], [1579708800000, _D(1579708800000/1000)]])
        while True:
            Log(exchange.GetData("test"))
            Sleep(1000 * 60 * 60 * 24)
    
    /*backtest
    start: 2020-01-21 00:00:00
    end: 2020-02-12 00:00:00
    period: 1d
    basePeriod: 1d
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */    
    void main() {
        json arr = R"([[1579536000000, ""], [1579622400000, ""], [1579708800000, ""]])"_json;
        arr[0][1] = _D(1579536000000);
        arr[1][1] = _D(1579622400000);
        arr[2][1] = _D(1579708800000);
        exchange.SetData("test", arr);
        while(true) {
            Log(exchange.GetData("test"));
            Sleep(1000 * 60 * 60 * 24);
        }
    }
    
  • Método de llamada de datos desde enlaces externos

    function main() {
        Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
        Log(exchange.GetData("https://www.fmz.com/upload/asset/32bf73a69fc12d36e76.json"))
    }
    
    def main():
        Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"))
        Log(exchange.GetData("https://www.fmz.com/upload/asset/32bf73a69fc12d36e76.json"))
    
    void main() {
        Log(exchange.GetData("http://xxx.xx.x.xx:9090/data"));
        Log(exchange.GetData("https://www.fmz.com/upload/asset/32bf73a69fc12d36e76.json"));
    }
    
  • Utilice los datos fundamentales del centro de datos de la plataforma Utilice elexchange.GetData(Source)Función para obtenerDatos fundamentales.

Cuando se llama a laexchange.GetData(Source)En el sistema de backtest, al usar la interfaz de acceso para solicitar datos, el sistema de backtest agregará parámetros from (segundos de marca de tiempo), a (segundos de marca de tiempo), período (período subyacente de la línea K, milisegundos de marca de tiempo) y otros parámetros automáticamente a la solicitud, para determinar el rango de tiempo de los datos a obtener.

API para el comercio

Las siguientes funciones se pueden llamar a través de laexchangeo bienexchanges[0]objetos, por ejemplo:exchange.Sell(100, 1);indica que la siguiente orden es una orden de venta con un precio de 100 y una cantidad de 1 en la bolsa.

cambio.Comprar ((Precio, monto)

exchange.Buy(Price, Amount)se utiliza para realizar una orden de compra y devolver un ID de orden. Valor del parámetro:Pricees el precio de la orden expresado en número, yAmountes el importe de la orden expresado en número. Valor de devolución: tipo de cadena o tipo numérico (el tipo específico depende del tipo de devolución de cada plataforma de intercambio).

El número de pedido devuelto se puede utilizar para consultar la información del pedido y cancelar pedidos.

function main() {
    var id = exchange.Buy(100, 1);
    Log("id:", id);
}
def main():
    id = exchange.Buy(100, 1)
    Log("id:", id)
void main() {
    auto id = exchange.Buy(100, 1);
    Log("id:", id);
}
  • Ordenes de futuros

    Al realizar órdenes de futuros, debemos prestar atención a si la dirección de negociación está establecida correctamente. Si la dirección de negociación y la función de negociación no coinciden, se reportará un error. El número de órdenes realizadas en un intercambio de futuros de criptomonedas es el número de contratos a menos que se especifique lo contrario. Por ejemplo:

    // The following is the wrong call
    function main() {
        exchange.SetContractType("quarter")
      
        // Set short direction
        exchange.SetDirection("sell")     
        // Place a buy order, and you will get an error, so you can only sell short
        var id = exchange.Buy(50, 1)      
    
        // Set short direction
        exchange.SetDirection("buy")      
        // Place a sell order, and you will get an error, so you can only buy long
        var id2 = exchange.Sell(60, 1)    
      
        // Set close long position direction
        exchange.SetDirection("closebuy")    
        // Place a buy order, and you will get an error, so you can only sell short
        var id3 = exchange.Buy(-1, 1)        
      
        // Set close short position direction
        exchange.SetDirection("closesell")   
        // Place a sell order, and you will get an error, so you can only buy long
        var id4 = exchange.Sell(-1, 1)       
    }
    
    # The following is the wrong call
    def main():
        exchange.SetContractType("quarter")
        exchange.SetDirection("sell")
        id = exchange.Buy(50, 1)
        exchange.SetDirection("buy")
        id2 = exchange.Sell(60, 1)
        exchange.SetDirection("closebuy")
        id3 = exchange.Buy(-1, 1)
        exchange.SetDirection("closesell")
        id4 = exchange.Sell(-1, 1)
    
    // The following is the wrong call
    void main() {
        exchange.SetContractType("quarter");
        exchange.SetDirection("sell");
        auto id = exchange.Buy(50, 1);
        exchange.SetDirection("buy");
        auto id2 = exchange.Sell(60, 1);
        exchange.SetDirection("closebuy");
        auto id3 = exchange.Buy(-1, 1);
        exchange.SetDirection("closesell");
        auto id4 = exchange.Sell(-1, 1);
    }
    

    Mensajes de error:

    direction is sell, invalid order type Buy
    direction is buy, invalid order type Sell
    direction is closebuy, invalid order type Buy
    direction is closesell, invalid order type Sell
    
  • Orden del mercado

    Nota: La interfaz de orden de intercambio se requiere para soportar órdenes de mercado (cuando el tipo de orden es una orden de compra, el parámetro de importe de la orden es el importe en moneda de cotización), y el método de orden de mercado de los futuros de criptomonedas se utiliza para realizar órdenes, y la unidad del parámetro de cantidad es elnúmero de contratosAlgunos intercambios de comercio en vivo para monedas digitales no admiten interfaces de orden de mercado.

    // For example, trading pairs: ETH_BTC, bought in by market order
    function main() {
        // Buy a market order, and buy ETH coins equal to 0.1 BTC (quote currency) 
        exchange.Buy(-1, 0.1)    
    }
    
    def main():
        exchange.Buy(-1, 0.1)
    
    void main() {
        exchange.Buy(-1, 0.1);
    }
    

cambio.Venta ((Precio, monto)

exchange.Sell(Price, Amount)Pone una orden de venta y devuelve un ID de orden. Valor del parámetro:Pricees el precio de la orden, tipo numérico.Amountes el importe de la orden, tipo numérico. Valor de devolución: tipo de cadena o tipo numérico (el tipo específico depende del tipo de devolución de cada intercambio).

Número de pedido devuelto, que se puede utilizar para consultar información sobre el pedido y cancelar pedidos.

function main(){
    var id = exchange.Sell(100, 1)
    Log("id:", id)
}
def main():
    id = exchange.Sell(100, 1)
    Log("id:", id)
void main() {
    auto id = exchange.Sell(100, 1);
    Log("id:", id);
}
  • Ordenes de futuros

    Al realizar órdenes de futuros, debe prestar atención a si la dirección de negociación está establecida correctamente. Si la dirección de negociación y la función de negociación no coinciden, se reportará un error. El monto del pedido de las plataformas de futuros de criptomonedas es el número de contratos a menos que se especifique lo contrario.

  • Ordenes de mercado

    Nota: se requiere una interfaz de colocación de pedidos de la plataforma para admitir órdenes de mercado. (Cuando el tipo de orden es una orden de venta, el parámetro de monto del pedido es el número de monedas operativas vendidas), y los futuros de criptomonedas colocan pedidos por forma de órdenes de mercado, y la unidad de parámetro de monto del pedido es elnúmero de contratosAlgunos intercambios de divisas digitales en el comercio real no admiten interfaces de orden de mercado.

    // For example, trading pairs: ETH_BTC, sold out by market order 
    function main() {
        // Note: Sell by a market order, and sell 0.2 ETH coins 
        exchange.Sell(-1, 0.2)   
    }
    
    def main():
        exchange.Sell(-1, 0.2)
    
    void main() {
        exchange.Sell(-1, 0.2);
    }
    

Intercambio.Cancelación del pedido (Id)

exchange.CancelOrder(orderId), el propósito de esta función es cancelar una orden con Id. Valor del parámetro:Ides el número de pedido, en tipo de cadena o tipo numérico (el tipo específico depende del tipo de devolución al realizar un pedido en cada plataforma); valor de devolución: tipo bool.

Devuelve el resultado de la operación;truesignifica que la solicitud de cancelación del pedido se ha enviado correctamente;falsesignifica que la solicitud de orden de cancelación no se envía (el valor de retorno sólo indica si la solicitud de envío es exitosa o no, por lo que es mejor llamarexchange.GetOrders()para comprobar si la plataforma cancela la orden).

function main(){
    var id = exchange.Sell(99999, 1)
    exchange.CancelOrder(id)
}
def main():
    id = exchange.Sell(99999, 1)
    exchange.CancelOrder(id)
void main() {
    auto id = exchange.Sell(99999, 1);
    exchange.CancelOrder(id);
}

La función API de FMZ, que puede generar funciones de salida de registro, tales comoLog(...), exchange.Buy(Price, Amount)yexchange.CancelOrder(Id)Puede seguir los parámetros necesarios con algunos parámetros de salida adicionales, tales comoexchange.CancelOrder(orders[j].Id, orders[j])De esta manera, se está cancelandoorders[j]orden que se acompaña de la salida de esta orden información, a saber, elOrderestructura de lasorders[j].

function main() {
    Log("data1", "data2", "data3", "...")
    var data2 = 200
    var id = exchange.Sell(100000, 0.1, "Incidental data1", data2, "...")
    exchange.CancelOrder(id, "Incidental data1", data2, "...")
    LogProfit(100, "Incidental data1", data2, "...")
}
def main():
    Log("data1", "data2", "data3", "...")
    data2 = 200
    id = exchange.Sell(100000, 0.1, "Incidental data1", data2, "...")
    exchange.CancelOrder(id, "Incidental data1", data2, "...")
    LogProfit(100, "Incidental data1", data2, "...")
void main() {
    Log("data1", "data2", "data3", "...");
    int data2 = 200;
    auto id = exchange.Sell(100000, 0.1, "Incidental data1", data2, "...");
    exchange.CancelOrder(id, "Incidental data1", data2, "...");
    LogProfit(100, "Incidental data1", data2, "...");
}

En el caso de las operaciones de intercambio.GetOrder ((Id))

exchange.GetOrder(orderId)Obtiene los detalles de la orden de acuerdo con el número de orden.Ides el número de orden a obtener, yIdes de tipo de cadena o numérico (el tipo específico depende del tipo de devolución de cada intercambio).Orderla estructura. (No soportado por algunos intercambios)

  • Orderestructura
  • AvgPriceIndica el precio medio ejecutado (algunos intercambios no admiten este campo; si no lo admiten, ponlo en cero).
function main(){
    var id = exchange.Sell(1000, 1)
    // The parameter id is the order number, you need to fill in the number of the order you want to query
    var order = exchange.GetOrder(id)      
    Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:",
        order.DealAmount, "Status:", order.Status, "Type:", order.Type)
}
def main():
    id = exchange.Sell(1000, 1)
    order = exchange.GetOrder(id)
    Log("Id:", order["Id"], "Price:", order["Price"], "Amount:", order["Amount"], "DealAmount:", 
        order["DealAmount"], "Status:", order["Status"], "Type:", order["Type"])
void main() {
    auto id = exchange.Sell(1000, 1);
    auto order = exchange.GetOrder(id);
    Log("Id:", order.Id, "Price:", order.Price, "Amount:", order.Amount, "DealAmount:", 
        order.DealAmount, "Status:", order.Status, "Type:", order.Type);
}

El cambio.GetOrders (((

exchange.GetOrders()Obtiene todos los pedidos sin terminar.Orderel conjunto de estructuras. ParaOrderestructura, por favor, consulte elexchange.GetOrder()Cuando la cuenta representada por el objeto de cambioexchangeNo tiene órdenes pendientes, llameexchange.GetOrders()para devolver una matriz vacía, a saber:[].

function main(){
    exchange.Sell(1000, 1)
    exchange.Sell(1000, 1)
    var orders = exchange.GetOrders()
    Log("Information for unfinished order 1, ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount,
        "DealAmount:", orders[0].DealAmount, "type:", orders[0].Type)
    Log("Information for unfinished order 2, ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount,
        "DealAmount:", orders[1].DealAmount, "type:", orders[1].Type)
}
def main():
    exchange.Sell(1000, 1)
    exchange.Sell(1000, 1)
    orders = exchange.GetOrders()
    Log("Information for unfinished order 1, ID:", orders[0]["Id"], "Price:", orders[0]["Price"], "Amount:", orders[0]["Amount"], 
        "DealAmount:", orders[0]["DealAmount"], "type:", orders[0]["Type"])
    Log("Information for unfinished order 2, ID:", orders[1]["Id"], "Price:", orders[1]["Price"], "Amount:", orders[1]["Amount"],
        "DealAmount:", orders[1]["DealAmount"], "type:", orders[1]["Type"])
void main() {
    exchange.Sell(1000, 1);
    exchange.Sell(1000, 1);
    auto orders = exchange.GetOrders();
    Log("Information for unfinished order 1, ID:", orders[0].Id, "Price:", orders[0].Price, "Amount:", orders[0].Amount, 
        "DealAmount:", orders[0].DealAmount, "type:", orders[0].Type);
    Log("Information for unfinished order 2, ID:", orders[1].Id, "Price:", orders[1].Price, "Amount:", orders[1].Amount,
        "DealAmount:", orders[1].DealAmount, "type:", orders[1].Type);
}

Elexchange.GetOrders()La función obtiene la información de orden incompleta del conjunto actualPares de negociaciónDebe tenerse en cuenta que los futuros de criptomonedas tienen diferencias entre no solo pares comerciales sino también códigos de contrato.

// Test OKX contract tradings, to know whether "GetOrders" gets all unfinished contract orders
function main(){
    // The next weekly buy order; the price of the order minus 50 guarantees no execution; pending orders
    exchange.SetContractType("this_week")
    exchange.SetDirection("buy")
    var ticker = exchange.GetTicker()
    Log(ticker)
    exchange.Buy(ticker.Last - 50, 1)

    // The next quarterly sell order; the price plus 50 guarantees that it will not be executed, and the pending order has been switched to a quarterly contract
    exchange.SetContractType("quarter")
    exchange.SetDirection("sell")
    ticker = exchange.GetTicker()
    Log(ticker)
    exchange.Sell(ticker.Last + 50, 1)

    // Get the unfinished orders
    Log("orders", exchange.GetOrders())
}
def main():
    exchange.SetContractType("this_week")
    exchange.SetDirection("buy")
    ticker = exchange.GetTicker()
    Log(ticker)
    exchange.Buy(ticker["Last"] - 50, 1)

    exchange.SetContractType("quarter")
    exchange.SetDirection("sell")
    ticker = exchange.GetTicker()
    Log(ticker)
    exchange.Sell(ticker["Last"] + 50, 1)

    Log("orders", exchange.GetOrders())
void main() {
    exchange.SetContractType("this_week");
    exchange.SetDirection("buy");
    auto ticker = exchange.GetTicker();
    Log(ticker);
    exchange.Buy(ticker.Last - 50, 1);

    exchange.SetContractType("quarter");
    exchange.SetDirection("sell");
    ticker = exchange.GetTicker();
    Log(ticker);
    exchange.Sell(ticker.Last + 50, 1);

    Log("orders", exchange.GetOrders());
}

Información obtenida sobre el pedido no terminado:

[{"Id":17116430886,"Amount":1,"Price":808.4,"DealAmount":0,"AvgPrice":0,"Status":0,"Type":1,"ContractType":"quarter"}]

Se puede ver que en el comercio de criptomonedas, las órdenes obtenidas porexchange.GetOrders()sólo son las órdenes pendientes del contrato actualmente establecido.

El cambio.ConfiguraciónPrecisión(...)

exchange.SetPrecision(PricePrecision, AmountPrecision)establece la precisión decimal del precio y el importe de la orden del símbolo; se truncará automáticamente después de la configuración.PricePrecisiones de tipo numérico, utilizado para controlar el número de decimales en los datos de precios;AmountPrecisiones de tipo numérico, utilizado para controlar el punto decimal después del importe del pedido.PricePrecisionyAmountPrecisionEl backtest no admite la función, y la precisión numérica del backtest se procesará automáticamente.

function main(){
    // Set the decimal precision of the price to 2 digits, and set the precision of the quantity of the symbol order to 3 digits
    exchange.SetPrecision(2, 3)
}    
def main():
    exchange.SetPrecision(2, 3)
void main() {
    exchange.SetPrecision(2, 3);
}

cambio.Configuración de la tasa

exchange.SetRate(Rate)establece el tipo de cambio de la moneda de circulación en el mercado.Ratees denumbertipo. Valor devuelto:number type.

function main(){
    Log(exchange.GetTicker())
    // Set the exchange rate conversion
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    // Set to 1, without conversion
    exchange.SetRate(1)
}
def main():
    Log(exchange.GetTicker())
    exchange.SetRate(7)
    Log(exchange.GetTicker())
    exchange.SetRate(1)
void main() {
    Log(exchange.GetTicker());
    exchange.SetRate(7);
    Log(exchange.GetTicker());
    exchange.SetRate(1);
}

Nota:

  • Si ha establecido un valor de tipo de cambio utilizandoexchange.SetRate(Rate), como 7, entonces, toda la información de precios, incluido el precio de mercado actual, la profundidad y el precio de pedido, de la moneda de circulación representada por el precio de mercado actual.exchangeLos objetos, se multiplicarán por el tipo de cambio establecido de 7 para la conversión.

  • Por ejemplo,exchangees un tipo de cambio denominado en dólares estadounidenses.exchange.SetRate(7)En el caso de los precios de las transacciones reales, todos los precios se multiplican por 7 y se convierten en precios cercanos al yuan.

exchange.IO(…)

exchange.IO("api", httpMethod, resource, params, raw), llamar a otras interfaces funcionales del intercambio. Valor del parámetro:httpMehodes de tipo de cadena; llena el tipo de solicitud, comoPOSTo bienGET. resourcees de tipo de cadena, llena la ruta de solicitud.paramses de tipo de cadena, llena los parámetros de solicitud.rawes el parámetro original de la cadena JSON y puede omitirse.exchange.IO("api", httpMethod, resource, params, raw)Cuando se produce un error y la llamada falla, devuelve un valor nulo (la función con la solicitud de red, comoGetTicker()yGetAccount(), etc., devuelve valores nulos cuando las llamadas fallan).exchange.IO("api", ...) function.

Para el ejemplo de orden de lote OKX, use el parámetrorawpara pasar los parámetros de orden:

function main() {
    var arrOrders = [
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"},
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"2","posSide":"long"}
    ]
    
    // Call exchange.IO to directly access the platform batch ordering interface
    var ret = exchange.IO("api", "POST", "/api/v5/trade/batch-orders", "", JSON.stringify(arrOrders))
    Log(ret)
}
import json
def main():
    arrOrders = [
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"}, 
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"2","posSide":"long"}
    ]
    ret = exchange.IO("api", "POST", "/api/v5/trade/batch-orders", "", json.dumps(arrOrders))
    Log(ret)
void main() {
    json arrOrders = R"([
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"},
        {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"2","posSide":"long"}
    ])"_json;
    auto ret = exchange.IO("api", "POST", "/api/v5/trade/batch-orders", "", arrOrders.dump());
    Log(ret);
}

Para utilizar esta función, usted necesita ir a la intercambio para entender elAPIInterfaz del intercambio para extender las funciones que FMZ no ha añadido (no tiene que preocuparse por el proceso de cifrado de parámetros, firma y verificación cuando envíe unPOSTFMZ ha procesado completamente en la capa inferior, por lo que sólo necesita rellenar los parámetros correspondientes).

Nota: Si el valor clave en elparamsParámetro (es decir, el parámetro de solicitud HTTP) es una cadena, que necesita ser envuelto con comillas (símbolo') en ambos lados del valor del parámetro. Por ejemplo:bitfinex exchange.

var amount = 1
var price = 10
var basecurrency = "ltc"
function main () {
    // Notice that amount.toString() and price.toString() both have a ' character on the left and right
    var message = "symbol=" + basecurrency + "&amount='" + amount.toString() + "'&price='" + price.toString() + "'&side=buy" + "&type=limit"
    var id = exchange.IO("api", "POST", "/v1/order/new", message)
}
amount = 1
price = 10
basecurrency = "ltc"
def main():
    message = "symbol=" + basecurrency + "&amount='" + str(amount) + "'&price='" + str(price) + "'&side=buy" + "&type=limit"
    id = exchange.IO("api", "POST", "/v1/order/new", message)
void main() {
    auto amount = 1.0;
    auto price = 10.0;
    auto basecurrency = "ltc";
    string message = format("symbol=%s&amount=\"%.1f\"&price=\"%.1f\"&side=buy&type=limit", basecurrency, amount, price);
    auto id = exchange.IO("api", "POST", "/v1/order/new", message);
}

Ejemplo de accesoOKXInterfaz:

function main(){
    var ret = exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT")
    Log(ret)
}
def main():
    ret = exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT")
    Log(ret)
void main() {
    auto ret = exchange.IO("api", "GET", "/api/v5/trade/orders-pending", "instType=SPOT");
    Log(ret);
}

Datos devueltos durante el ensayo:

{"code":"0","data":[],"msg":""}

Otros ajustes delexchange.IOFunción:

  • Cambiar los pares de negociación del intercambio actual

    exchange.IO("currency", "ETH_BTC")

    function main() {
        // For example, set the current trading pair of the exchange object on the bot to BTC_USDT, and print the current trading pair market
        Log(exchange.GetTicker())
        // Switch trading pair to LTC_BTC      
        exchange.IO("currency", "LTC_BTC")
        Log(exchange.GetTicker())
    }
    
    def main():
        Log(exchange.GetTicker())
        exchange.IO("currency", "LTC_BTC")
        Log(exchange.GetTicker())
    
    void main() {
        Log(exchange.GetTicker());
        exchange.IO("currency", "LTC_BTC");
        Log(exchange.GetTicker());
    }
    

    De este modo, elPares de negociaciónconfiguradocuando se agrega el boto biense ejecuta el backtestSe cambiará a través de los códigos.

    Nota:

      1. El sistema de backtest ahora admite el cambio de pares de negociación (sólo los objetos de intercambio al contado de criptomonedas).ETH_BTC, que sólo se puede cambiar aLTC_BTC, noLTC_USDT.
      1. Si elwebsocketel modo de protocolo está activado en los objetos de intercambio spot Huobi, no se puede utilizarexchange.IO("currency", "XXX_YYY")para cambiar monedas.
      1. Para los intercambios de futuros de criptomonedas, si los pares comerciales se cambian, debe configurar el contrato nuevamente para determinar con qué contrato desea operar.
      1. También puede utilizar el nuevoexchange.SetCurrency(Symbol)la función de cambiar de par de operaciones, y utilizarexchange.IO("currency","XXX_YYY")el método para mantener la compatibilidad.
  • exchange.IOfunción de cambiar la dirección de base de la API del intercambio (contrato RESET; algunos intercambios no lo admiten). Ahora el uso deexchange.SetBase(Base)se ha apoyado la función para cambiar la dirección de base de la API de intercambio y utilizarexchange.IO("base","https://xxx.xxx.xxx")el método para mantener la compatibilidad.

    Por ejemplo: Cuando el objeto de intercambio está encapsulado, la dirección de base predeterminada eshttps://api.huobipro.com, para cambiar a:https://api.huobi.pro, utilice el siguiente código.

    function main () {
        // exchanges[0] is the first exchange object added when the bot is added 
        exchanges[0].IO("base", "https://api.huobi.pro")        
    }
    
    def main():
        exchanges[0].IO("base", "https://api.huobi.pro")
    
    void main() {
        exchanges[0].IO("base", "https://api.huobi.pro");
    }
    

    Cambiar la dirección de base de nuevo a:https://api.huobipro.com.

    function main () {
        exchanges[0].IO("base", "https://api.huobipro.com")
    }
    
    def main():
        exchanges[0].IO("base", "https://api.huobipro.com")
    

Más.