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

su dirección IP es10.0.3.15 }


#### exchange.SetTimeout(...)

```exchange.SetTimeout(Millisecond)```, in which the parameter **Millisecond** is a millisecond value.

Only for the ```rest``` protocol, it is used to set the time-out period for ```rest``` requests, and it takes effect only by setting it once.
For example: ```exchange.SetTimeout(3000)```, set the timeout time of the ```rest``` request of the exchange object ```exchange```, if it exceeds 3 seconds, timeout will return ```null```.

Note:
* The parameter ```Millisecond``` is millisecond, and 1,000 milliseconds equals 1 second. 
* Only need to set once.
* Only for the **rest** protocol.
* ```SetTimeout``` is not a global function, but an exchange object method. 

### Special Requirements for C++ Written Strategies   
The main difference between ```C++``` written strategy and ```JavaScript``` written strategy is the returned data differences of **FMZ API** interface. For example, the ```exchange.GetTicker()``` function.

- JavaScript
```exchange.GetTicker()``` returns an object if the call succeeds, or returns ```null``` if the call fails (due to the exchange server problems or network problems, etc.).

```javascript
function main() {
    var ticker = exchange.GetTicker()
    // Determine if the call to "exchange.GetTicker" function failed, and return "null" when it failed
    if (ticker){
        Log(ticker)
    }
}
  • C++exchange.GetTicker()devuelve un objeto, cuando la llamada tiene éxito. Si la llamada falla, el objeto devuelto sigue siendo un objeto, que se distingue del objeto devuelto normal por el atributoValid.

    void main() {
        auto ticker = exchange.GetTicker();
        // Determine if the call to "exchange.GetTicker()" function failed and if the "Valid" attribute of the returned object is "false"
        if (ticker.Valid) {
            Log(ticker);
        }
    }
    

La diferencia entre elmain()La función en elC++la estrategia escrita y lamain()Función en el estándar C11: El valor de retorno de laC++Función de entrada del programamain()en C11 es deintEn el caso de losC++la estrategia escrita en la plataforma FMZ, la función de inicio de la estrategia es también la funciónmain(), pero estos dos no son la misma función, sólo con el mismo nombre.main()La función en elC++La estrategia es devoid type.

void main() {
    // Use "Test" function to test
    if (!Test("c++")) {
        // Show an exception to stop the program
        Panic("Please download the latest-versioned docker");
    }

    // Determine if the return of all objects is valid with "Valid" 
    LogProfitReset();
    LogReset();
    Log(_N(9.12345, 2));
    Log("use _C", _C(exchange.GetTicker), _C(exchange.GetAccount));
}

Asuntos especiales de JavaScript

Por razones del lenguaje JavaScript (el lenguaje JavaScript soporta cadenas integradasasciiyutf-16codificación sólo, con el fin de no perder datos), cuando se encontró con una cadena que no puede ser codificada, se devolverá elArrayBufferTodas las interfaces API que pueden pasar los parámetros de cadena también admiten pasar elArrayBuffer type.

JavaScript con múltiples hilos

Es realmente compatible con la función de múltiples hilos de laJavaScriptestrategia de lenguaje desde la parte inferior del sistema, incluyendo: ejecución simultánea de funciones de ejecución personalizadas; soporte para la comunicación entre hilos concurrentes, soporte para la comunicación entre hilos concurrentes y el hilo principal; almacenamiento, uso compartido de variables en el entorno del hilo y otras funciones.https://www.fmz.com/bbs-topic/9974.

_Filado

El__Thread(function, arguments...)function crea un hilo que se ejecuta simultáneamente. No admite referencia directa a variables distintas de la función de ejecución de hilo (se ejecuta como un entorno aislado). Las referencias a variables externas no se compilarán. Las referencias a otras funciones de cierre tampoco son compatibles. Todas las API de la plataforma se pueden llamar dentro del hilo, pero no se pueden llamar otras funciones definidas por el usuario.functionpuede ser una función de referencia o una función anónima.argumentses el parámetro delfunctionfunción (el parámetro real transmitido), yarguments...significa que se pueden pasar múltiples parámetros. Valor de retorno: el ID del hilo.

function testFunc(n) {
    Log("Execute the function testFunc, parameter n:", n)
}

function main() {
    var testThread1 = __Thread(function () {
        Log("Executes an anonymous function with no parameters.")
    })

    var testThread2 = __Thread(testFunc, 10)   // parameter n : 10
    
    __threadJoin(testThread1)                  // You can use the __threadJoin function to wait for concurrent threads to complete
    __threadJoin(testThread2)                  // If you don't wait for the execution of testThread1 and testThread2 to complete, the main thread will automatically release the concurrent thread after the execution is completed first, and terminate the execution function of the concurrent thread
}

Apoya el método de llamada de__Thread([function, arguments...], [function, arguments...], ...), es decir, múltiples funciones de ejecución de hilos se ejecutan secuencialmente en los hilos creados.

function threadTestFuncA(a) {
    Log(a)
    threadTestFuncC(4)
    
    // The threadTestFuncC function can be called, but the threadTestFuncB function cannot be called

    // this.d
    Log(d)
}

function threadTestFuncB(b) {
    Log(b)
    threadTestFuncC(2)

    this.d = 5
}

function main() {
    // Execute the threadTestFuncB function first, and then execute the threadTestFuncA function
    // threadTestFuncC will not be executed automatically, but it can be called by other thread execution functions
    var threadId = __Thread([threadTestFuncA, 3], [threadTestFuncB, 1], ["function threadTestFuncC(c) {Log(c)}"])
    __threadJoin(threadId)
}

La función de ejecución simultánea pasó al__ThreadLa función se ejecutará en orden inverso.Logfunción para imprimir1 ~ 5Las variables compartidas entre diferentes funciones de ejecución de hilo son compatibles.this.dLa variable en el ejemplo anterior puede asignarse en elthreadTestFuncBFunción y se utiliza en elthreadTestFuncAEs compatible con la transmisión de cadenas de funciones, tales como"function threadTestFuncC(c) {Log(c)}"en el ejemplo anterior, que permite a los hilos ejecutar llamadas de funciones a funciones externas y bibliotecas importadas por este método.

Para la importación de bibliotecas externas, un ejemplo de uso específico es el siguiente:

function ml(input) {
    const net = new brain.NeuralNetwork();
    net.train([
        { input: [0, 0], output: [0] },
        { input: [0, 1], output: [1] },
        { input: [1, 0], output: [1] },
        { input: [1, 1], output: [0] },
    ]);
    return net.run(input);
}

function main() {
    Log(__threadJoin(__Thread([ml, [1, 0]], [HttpQuery("https://unpkg.com/brain.js")])))
}

__thread PeekMessage (Mensaje de vista)

El__threadPeekMessage(threadId, timeout)función lee los datos del canal de comunicación del hilo, el parámetrothreadIdes el ID devuelto por el__Thread()función, estableciendo el parámetrothreadIdsignifica recibir los datos enviados por el hilo representado por el threadId. Cuando está establecido en 0, significa recibir los datos enviados por el hilo principal, es decir, la función principal actual (el parámetro threadId está establecido en 0, que solo se admite en funciones de ejecución de hilo concurrentes). El parámetrotimeoutes una configuración de tiempo de espera, que bloqueará y esperará según el número de milisegundos establecidos por este parámetro.timeoutestá configurado para:-1, significa bloquear y esperar hasta que se reciban los datos en el canal. Cuando el hilo remitente del canal termina la ejecución y no hay datos, el__threadPeekMessageEl valor de retorno: datos recibidos.

Cuando se escriben programas, es necesario prestar atención al problema del cierre de hilo.testFuncdel hilo concurrente creado y elmainfunción del hilo principal y función de ejecución del hilotestFuncserá ejecutado primero.

function testFunc() {
    for(var i = 0 ; i < 5 ; i++) {                // 0 ~ 5, after sending to the main thread 5 times, the execution of the thread function is completed, and the __threadPeekMessage function in the main function fetches all the data, it will not block again, and returns a null value immediately
        __threadPostMessage(0, i)                 // Send data to the main thread
        var msg = __threadPeekMessage(0, -1)      // Listen for data from the main thread
        Log("from main msg:", msg)
        Sleep(500)
    }
    Log("testFunc execution is complete")
}

function main() {
    var testThread = __Thread(testFunc)           // Create a thread with an Id of 1 
    
    for (var i = 0 ; i < 10 ; i++) {
        __threadPostMessage(1, i)                 // Send data to the thread whose Id is 1, that is, the thread that executes the testFunc function in this example
        var msg = __threadPeekMessage(1, -1)      // Listen to the data sent by the thread whose Id is 1, that is, the data sent by the thread that executes the testFunc function in the example
        Log("from testFunc msg:", msg)
        Sleep(500)
    }
}

__threadPostMensaje

El__threadPostMessage(threadId, data)función escribe datos al canal de comunicación de hilo, el parámetrothreadIdes el ID devuelto por el__Thread()Función, establezca el parámetrothreadIdsignifica enviar datos al hilo representado por el threadId, y cuando está establecido en 0, significa enviar datos al hilo principal, es decir, a la función principal actual (el parámetro threadId está establecido en 0, que solo se admite en funciones de ejecución de hilo concurrentes).datapuede pasar valores, cadenas, valores booleanos, objetos, matrices y otros tipos de datos.

Cuando el__threadPostMessageCuando una función es llamada en la función de ejecución de un hilo para enviar señales y datos, también se generará un evento de mensaje.EventLoop()Función para recibir notificaciones de mensajes.

function testFunc() {
    for(var i = 0 ; i < 10 ; i++) {
        Log("post msg, i:", i)
        __threadPostMessage(0, {msg: "testFunc", i: i})
        Sleep(100)
    }
}

function main() {
    var testThread = __Thread(testFunc)
    
    for (var i = 0 ; i < 10 ; i++) {
        var e = EventLoop()
        Log("e:", e)
        // e: {"Seq":1,"Event":"thread","Index":1,"Nano":1677745512064773600,"Deleted":0,"Symbol":"","Ticker":{"Info":null,"High":0,"Low":0,"Sell":0,"Buy":0,"Last":0,"Volume":0,"OpenInterest":0,"Time":0}}
        if (e.Event == "thread") {
            var msg = __threadPeekMessage(testThread, -1)
            Log("msg:", msg, "#FF0000")
        }
        Sleep(500)
    }
    
    var retThreadJoin = __threadJoin(testThread)
    Log("retThreadJoin:", retThreadJoin)
}

_threadJúntate

El__threadJoin(threadId, timeout)La función se utiliza para esperar a que el hilo con el ID especificado para salir y recuperar los recursos del sistema.threadIdes el ID devuelto por el__Thread()función, y el parámetrotimeoutes la configuración de tiempo de espera para el final del hilo, en milisegundos. Si el tiempo de espera no está establecido, significa esperar hasta el final de la ejecución del hilo.undefined.

Estructura de valor de la rentabilidad, por ejemplo:

{
    "id":1,                 // Thread Id
    "terminated":false,     // Whether the thread is terminated forcibly
    "elapsed":2504742813,   // The running time of the thread (nanoseconds)
    "ret": 123              // The return value of the thread function
}

__threadTerminación

El__threadTerminatefunción se utiliza para terminar el hilo forzosamente y liberar los recursos de hardware utilizados por el hilo creado (el __threadJoin ya no se puede utilizar para esperar el final). El parámetrothreadIdes el ID devuelto por el__Thread()Valor de retorno: valor booleano, que indica el resultado de la ejecución.

function testFunc() {
    for(var i = 0 ; i < 10 ; i++) {
        Log("i:", i)
        Sleep(500)
    }
}

function main() {
    var testThread = __Thread(testFunc)
    
    var retThreadTerminate = null 
    for (var i = 0 ; i < 10 ; i++) {
        Log("main i:", i)
        if (i == 5) {
            retThreadTerminate = __threadTerminate(testThread)
        }
        Sleep(500)
    }
    
    Log("retThreadTerminate:", retThreadTerminate)
}

__threadGetData es el nombre de la aplicación.

__threadGetData(threadId, key), la función se utiliza para acceder a las variables compartidas entre los hilos. Los datos son válidos cuando el hilo no ha ejecutado el__threadJoinFunción (esperando una salida exitosa) y no ha ejecutado el__threadTerminateFunción (terminó el hilo por la fuerza).threadIdes el ID de hilo, y el parámetrokeyes el nombre clave del archivokey-valueValor de retorno: devuelve el valor de la clave correspondiente akeyEn elkey-value pair.

threadIdes 0 para indicar el hilo principal (es decir, el hilo dondemainfunción se encuentra), se puede utilizar__threadId()función para obtener el ID del hilo actual, establecer el parámetrothreadIdTambién puede leer las variables en el entorno del hilo del ID especificado.

function main() {
    var t1 = __Thread(function() {
        Sleep(2000)
        var id = __threadId()                                                   // Get the Id of the current thread
        Log("id:", id, ", in testThread1 print:", __threadGetData(id, "msg"))   // Retrieve the key value corresponding to the key name msg in the current thread, i.e. "testThread2"
        Log("id:", 2, ", in testThread1 print:", __threadGetData(2, "msg"))     // Read the key value corresponding to the key name msg in the thread with thread Id 2, i.e. 99
    })

    var t2 = __Thread(function(t) {
        __threadSetData(t, "msg", "testThread2")                                // Set a key-value pair to the thread with Id t1 (Id 1), with the key name msg and the key value "testThread2"
        __threadSetData(__threadId(), "msg", 99)                                // Set the key-value pair in the current thread (Id is 2) with the key name msg and the key value 99
        __threadSetData(0, "msg", 100)                                          // Set up a key-value pair in the main thread, with the key name msg and the key value 100
    }, t1)
    
    __threadJoin(t1)   // You can check the __threadJoin(threadId, timeout) function, which is used to wait for the end of thread execution
    Log("in main, get msg:", __threadGetData(0, "msg"))
}

__threadSetDatos

__threadSetData(threadId, key, value), que se utiliza para almacenar variables en el entorno del hilo.threadIdes el ID del hilo, el parámetrokeyes el nombre clave del archivokey-valuepareja, y el parámetrovaluees el valor clave. La función no tiene valor de retorno.

threadIdes 0 para indicar el hilo principal (es decir, el hilo dondemainLa función se encuentra), y se puede utilizar el__threadId()función para obtener la ID del hilo actual.valueNo se especifican los medios para eliminarkey. Soporta el acceso mutuo a variables compartidas entre hilos. Los datos son válidos cuando el hilo no ha ejecutado el__threadJoinFunción (esperando una salida exitosa) y no ha ejecutado el__threadTerminateEl valor del parámetrovaluedebe ser una variable serializable.

function testFunc() {
    var id = __threadId()                  // Get the current thread Id
    __threadSetData(id, "testFunc", 100)   // Stored in the current thread environment
    __threadSetData(0, "testFunc", 99)     // Stored in the main threaded environment
    Log("testFunc execution is complete")
}

function main() {
    // threadId is 1, the created thread with threadId 1 will be executed first, as long as the thread resources are not recycled, the variables stored locally in the thread will be valid
    var testThread = __Thread(testFunc)
    
    Sleep(1000)

    // Output in main, get testFunc: 100
    Log("in main, get testFunc:", __threadGetData(testThread, "testFunc"))

    // Output in main, get testFunc: 99
    Log("in main, get testFunc:", __threadGetData(0, "testFunc"))

    // Delete the testFunc key-value pair in the thread environment with Id testThread
    __threadSetData(testThread, "testFunc")

    // After deleting and reading again, the __threadGetData function returns undefined
    Log("in main, get testFunc:", __threadGetData(testThread, "testFunc"))
}

- ¿Qué quieres decir?

__threadId(), que se utiliza para obtener el ID del hilo actual, sin parámetros.threadIddel hilo actual.

function testFunc() {
    Log("in testFunc, __threadId():", __threadId())
}

function main() {
    __Thread(testFunc)

    // If the execution of the main thread is completed, the created child thread will stop executing, so here Sleep(1000), wait for 1 second
    Sleep(1000)
    Log("in main, __threadId():", __threadId())
}

Apoyo a la codificación

En elJavaScriptEn la estrategia de lenguaje, el código hexagonal del archivo wasm puede cargarse, instanciarse y ejecutarse.JavaScriptCódigo, tiene una cierta ventaja de velocidad.

wasm.parseModule

wasm.parseModule(data), que analiza un modelo de cadena hexadecimal.dataParámetro es la codificación de wasm que se ha convertido en una cadena hexadecimal.Ejemplo de estrategia.

Por ejemplo, el siguiente código de función c ++ se puede compilar en código wasm, y luego se convierte en una cadena hexadecimal, que se puede utilizar como eldataParámetro delwasm.parseModule(data) function.

// Recursive Algorithm for Fibonacci Numbers
int fib(int f) {
    if (f < 2) return f;
    return fib(f - 1) + fib(f - 2);   
}

wasm.buildInstance

wasm.buildInstance(module, opt), que crea una instancia de modelo de gusano.moduleel parámetro es el modelo de wasm, y eloptParámetro es la información de configuración, que se utiliza para establecer el espacio de pila asignado al programa de instancia de wasm.

optEjemplo de configuración de parámetros:

{
    stack_size: 65*1024*1024,
}

llamadaFunción

callFunction(funcName, param1, ...), que es un método de la instancia del modelo wasm, utilizado para ejecutar la función en la instancia del modelo wasm.funcNameParámetro es el nombre de la función a ejecutar, y elparam1Parámetro es el parámetro enviado al ejecutar la función (especificado por el parámetrofuncName).

Blockchain (cámara de bloques)

La plataforma Quant Trading de FMZ es oficialmente accesible para apoyar la llamada interactiva de laweb3En la actualidad, la mayoría de losdefiintercambio fácil.

Ethereum

Configuración

En la plataforma FMZ Quant Trading, escriba código de estrategia para implementar la llamada de método del contrato inteligente en la cadena Ethereum a través delexchange.IOEn primer lugar, configure el nodo de acceso en la plataforma de comercio de FMZ Quant. Los nodos de acceso pueden ser nodos autoconstruidos o utilizar servicios de terceros, tales comoinfura.

En la página deCambio FMZ plataforma Quant Trading, selecciona el protocolo: criptomoneda, y luego selecciona el intercambioWeb3. ConfigurarRpc Address(dirección de servicio del nodo de acceso) yPrivate KeyApoya el despliegue localizado de claves privadas, verSeguridad clave].

Registro de la ABI

Llamando a un contrato que es un estándarERC20El método no requiere registro y puede ser llamado directamente.exchange.IO("abi", tokenAddress, abiContent). Para obtener el contenido de ABI de un contrato, puede utilizar la siguiente URL para obtenerlo, tomando el campo de resultados sólo.

https://api.etherscan.io/api?module=contract&action=getabi&address=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

Método para llamar Ethereum RPC

Cuando el segundo parámetro delexchange.IOla función es"eth", puede llamar a los métodos RPC disponibles para el servidor de nodos directamente, por ejemplo:

  • Consulta el saldo de ETH en la billetera

    function main() {
        // "owner" needs to be replaced with a specific wallet address
        // "latest" parameter labels for string position: 'latest', 'earliest' or 'pending', please refer to https://eth.wiki/json-rpc/API#the-default-block-parameter
        // The return value ethBalance is a hexadecimal string: 0x9b19ce56113070
        var ethBalance = exchange.IO("api", "eth", "eth_getBalance", "owner", "latest")
    
        // ETH has a precision unit of 1e18
        var ethDecimal = 18
    
        // Because of the JavaScript language precision, it is necessary to use the system underlying encapsulated function BigInt, BigDecimal to process.
        // Convert ethBalance to readable quantity, 0x9b19ce56113070 to 0.043656995388076145.
        Log(Number((BigDecimal(BigInt(ethBalance))/BigDecimal(Math.pow(10, ethDecimal))).toString()))
    }
    
  • Transferencia de ETH

    function mian() {
        // ETH has a precision unit of 1e18
        var ethDecimal = 18
    
        // Number of transfers, readable quantity e.g. 0.01 ETH
        var sendAmount = 0.01
    
        // Because of the JavaScript language precision, it is necessary to use the system underlying encapsulated function BigInt, BigDecimal to process, and converts readable quantities into data for processing on the chain.
        var toAmount = (BigDecimal(sendAmount)*BigDecimal(Math.pow(10, ethDecimal))).toFixed(0)
        
        // "toAddress" is the address of the recipient's ETH wallet at the time of the transfer, which needs to be filled in specifically, and toAmount is the number of transfers.
        exchange.IO("api", "eth", "send", "toAddress", toAmount)
    }
    
  • Precio de la consulta de gas

    function toAmount(s, decimals) {
        return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
    }  
    
    function main() {
        var gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
        Log("gasPrice:", toAmount(gasPrice, 0))   // 5000000000 , in wei (5 gwei)
    }
    
  • Encuesta et_estimateGas

    function toAmount(s, decimals) {
        // The toAmount function can convert the hex-encoded value to a decimal value
        return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
    }  
    
    function main() {
        // Encoding the call to the approve method
        var data = exchange.IO("encode", "0x111111111117dC0aa78b770fA6A738034120C302", "approve", "0xe592427a0aece92de3edee1f18e0157c05861564", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
        Log("data:", data)
        var gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
        Log("gasPrice:", toAmount(gasPrice, 0))
        var obj = {
            "from" : "0x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",   // walletAddress
            "to"  : "0x111111111117dC0aa78b770fA6A738034120C302",
            "gasPrice" : gasPrice,
            "value" : "0x0",
            "data" : "0x" + data,
        }
        
        var gasLimit = exchange.IO("api", "eth", "eth_estimateGas", obj)
        Log("gasLimit:", toAmount(gasLimit, 0))
        Log("gas fee", toAmount(gasLimit, 0) * toAmount(gasPrice, 0) / 1e18)
    }
    

Apoyo para la codificación

La funciónexchange.IOEncapsula elencodemétodo, que puede devolver la codificación de llamada de función ahexPuede consultar las plataformas accesibles al público Uniswap V3 Biblioteca de clases comerciales plantillaLa llamada de la codificaciónunwrapWETH9El método se utiliza aquí como ejemplo:

function main() {
    // Main network address of ContractV3SwapRouterV2: 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
    // To call the unwrapWETH9 method, you need to register the ABI first, omit the registration here.
    // "owner" represents the wallet address, it needs to fill in the specific, 1 represents the number of unwrapping, unwrap a WETH into ETH
    var data = exchange.IO("encode", "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", "unwrapWETH9(uint256,address)", 1, "owner")
    Log(data)
}

Cuando se llama a laexchange.IO("encode",...)función, si el segundo parámetro (tipo de cadena) comienza con0x, significa la llamada al método en el código (encode) contrato inteligente. Si no comienza con0x, se utiliza para codificar el orden de tipo especificado.abi.encodeEn elsolidityConsulte el siguiente ejemplo.

function main() {
    var x = 10 
    var address = "0x02a5fBb259d20A3Ad2Fdf9CCADeF86F6C1c1Ccc9"
    var str = "Hello World"
    var array = [1, 2, 3]
    var ret = exchange.IO("encode", "uint256,address,string,uint256[]", x, address, str, array)   // uint i.e. uint256 , the type length needs to be specified on FMZ
    Log("ret:", ret)
    /*
    000000000000000000000000000000000000000000000000000000000000000a    // x
    00000000000000000000000002a5fbb259d20a3ad2fdf9ccadef86f6c1c1ccc9    // address
    0000000000000000000000000000000000000000000000000000000000000080    // offset of str
    00000000000000000000000000000000000000000000000000000000000000c0    // offset of array
    000000000000000000000000000000000000000000000000000000000000000b    // the length of str
    48656c6c6f20576f726c64000000000000000000000000000000000000000000    // str data
    0000000000000000000000000000000000000000000000000000000000000003    // the length of the array
    0000000000000000000000000000000000000000000000000000000000000001    // array the first data
    0000000000000000000000000000000000000000000000000000000000000002    // array the second data
    0000000000000000000000000000000000000000000000000000000000000003    // array the third data
    */
}

Apoya la codificación secuencial de tuples o tipos que contienen tuples:

function main() {
    var types = "tuple(a uint256,b uint8,c address),bytes"
    var ret = exchange.IO("encode", types, {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }, "0011")
    Log("encode: ", ret)
}

Este tipo de orden está compuesto por:tupleybytes, por lo que hay que pasar dos parámetros al llamarexchange.IOEn elencode:

    1. Variables correspondientes al tipotuple:
    {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }
    

    Los parámetros transmitidos deben ser también coherentes con la estructura y el tipo detuple, tal como se define en eltypesParámetro:tuple(a uint256, b uint8, c address).

    1. Variables correspondientes al tipobytes:
    "0011"
    

Soporte para la codificación secuencial de matrices o tipos que contengan matrices:

function main() {
    var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"]   // ETH address, USDT address
    var ret = exchange.IO("encode", "address[]", path)
    Log("encode: ", ret)
}

Soporte para encodePacked

Por ejemplo, al llamar el método DEX deUniswap V3, usted necesita pasar en los parámetros, tales como la ruta de intercambio, por lo que necesita utilizar elencodePackagedoperación:

function main() {
    var fee = exchange.IO("encodePacked", "uint24", 3000)
    var tokenInAddress = "0x111111111117dC0aa78b770fA6A738034120C302"
    var tokenOutAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"
    var path = tokenInAddress.slice(2).toLowerCase()
    path += fee + tokenOutAddress.slice(2).toLowerCase()
    Log("path:", path)
}

Apoyo para decodificar

El procesamiento de datos no sólo admite la codificación (encode), pero también de decodificación (decode) Utilizar elexchange.IO("decode", types, rawData)La función para realizar eldecode operation.

function main() {
    // register SwapRouter02 abi
    var walletAddress = "0x398a93ca23CBdd2642a07445bCD2b8435e0a373f"
    var routerAddress = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
    var abi = `[{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"}]`
    exchange.IO("abi", routerAddress, abi)   // abi only uses the contents of the local exactOutput method, the full abi can be searched on the Internet

    // encode path
    var fee = exchange.IO("encodePacked", "uint24", 3000)
    var tokenInAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    var tokenOutAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7"
    var path = tokenInAddress.slice(2).toLowerCase()
    path += fee + tokenOutAddress.slice(2).toLowerCase()
    Log("path:", path)

    var dataTuple = {
        "path" : path, 
        "recipient" : walletAddress, 
        "amountOut" : 1000, 
        "amountInMaximum" : 1, 
    }
    // encode SwapRouter02 exactOutput 
    var rawData = exchange.IO("encode", routerAddress, "exactOutput", dataTuple)
    Log("method hash:", rawData.slice(0, 8))   // 09b81346
    Log("params hash:", rawData.slice(8))

    // decode exactOutput params
    var decodeRaw = exchange.IO("decode", "tuple(path bytes,recipient address,amountOut uint256,amountInMaximum uint256)", rawData.slice(8))
    Log("decodeRaw:", decodeRaw)
}

El ejemplo realiza laencodePackedla primera operación durante elpathEl procesamiento de parámetros, porque elexactOutputLlamada de método que necesita ser codificado más tarde necesita elpathEntonces, el parámetroencodeel método deexactOutputel contrato de enrutamiento tiene un solo parámetro, y el tipo de parámetro estupleEl métodoexactOutputnombre está codificado como0x09b81346, que se decodifica el resultadodecodeRawPor elexchange.IO ("decode",...)método, y es consistente con la variabledataTuple.

Soporte para cambiar claves privadas

Apoya el cambio de claves privadas para operar múltiples direcciones de billetera, por ejemplo:

function main() {
    exchange.IO("key", "Private Key")   // "Private Key" represents the private key string, which needs to be filled in specifically
}

Método de llamada del contrato inteligente

El primer parámetro delexchange.IOsu función es:"api"El segundo parámetro de la llamada de extensiónexchange.IOFunción es la dirección del contrato inteligente a ser llamado.

Si el método llamado tiene elpayableAtributo, usted necesita añadir un valor transferencia ETH después del nombre del método (el cuarto parámetro de laexchange.IOFunción), que puede ser de tipo numérico o pasar un valor en forma de cadena, por ejemplo, elmulticallmétodo deUniswap V3Los siguientes contenidos son ejemplos de algunas llamadas de métodos de contratos inteligentes:

  • números decimales

    Eldecimalsel método es unconstantmétodo deERC20que no generagasEn el caso de los datos de precisión de un determinadotokenEl.decimalsEl valor de retorno: los datos de precisión detoken.

    function main(){
        var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"    // The contract address of the token, in the example the token is 1INCH
        Log(exchange.IO("api", tokenAddress, "decimals"))                  // Query, print 1INCH tokens with precision index of 18
    }
    
  • el pago de una indemnización

    Elallowanceel método es unconstantmétodo deERC20que no generagasEn la actualidad, el consumo de energía está en aumento, y puede consultar la cantidad autorizada de un determinadotokenLa dirección de un contrato.allowanceEl valor de retorno: el importe de la autorización de la cartera.token.

    function main(){
        // The contract address of the token, in the example the token is 1INCH
        var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"            
    
        // For example, the query yields 10000000000000000000000, divided by the precision unit of the token 1e18, the current exchange object bound to the wallet to the spender address authorized 1 1INCH.
        Log(exchange.IO("api", tokenAddress, "allowance", "owner", "spender"))   
    }
    

    owner: La dirección de la billetera se reemplaza por la cadena owner en el ejemplo. En el uso real, debe rellenar la dirección.spender: La dirección autorizada del contrato se sustituye por la cadena spender en el ejemplo.Uniswap V3 router v1.

  • Aprobar el proyecto

    ElapproveEl método es un no-constantmétodo deERC20que generagasConsumo, que se utiliza para autorizar unatokenEl importe de la operación corresponde a una determinada dirección de contrato.approveEl método debe pasar en 2 parámetros, el primero es la dirección a autorizar y el segundo es la cantidad autorizada.txid.

    function main(){
        // The contract address of the token, in the example the token is 1INCH
        var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"   
    
        // The hexadecimal string of the authorization amount: 0xde0b6b3a7640000 , the corresponding decimal string: 1e18 , 1e18 divided by the precision unit of the token, i.e. 1 token amount, so this refers to the authorization of one token.
        Log(exchange.IO("api", tokenAddress, "approve", "spender", "0xde0b6b3a7640000"))  
    }
    

    spender: La dirección del contrato autorizado, el ejemplo se sustituye por la cadena spender, el uso real necesita rellenar la dirección específica, por ejemplo, puede serUniswap V3 router v1 address. 0xde0b6b3a7640000: El número de autorizaciones, representado aquí mediante una cadena hexadecimal, corresponde a un valor decimal de1e18, dividido por eltokenUnidad de precisión en el ejemplo (es decir, 1e18), que da 1token authorized.

    El tercer parámetro delexchange.IOLa función se pasa el nombre del métodoapprove, que también se puede escribir en forma demethodId, por ejemplo: 0x571ac8b0. También es posible escribir el nombre completo del método estándar, como approve(address,uint256) .

  • de llamadas múltiples

    ElmulticallEl método es un método no constante deUniswap V3, que generarágasEl consumo y ser utilizado para intercambiar fichas de múltiples maneras.multicallEl método puede tener múltiples métodos de transmisión de parámetros. Puede consultar el ABI que contiene el método para obtener detalles. Debe registrar el ABI antes de llamar al método.txid.

    Para ejemplos concretos demulticallLas llamadas de método, por favor, consulte el público Uniswap V3 Biblioteca de clases comerciales plantillade nuestra plataforma.

    El pseudocódigo se utiliza aquí para describir algunos detalles:

    exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)
    

    ContractV3SwapRouterV2: dirección del router v2 de Uniswap V3.value: La cantidad de ETH transferida, fijarla en 0 si eltokenInEl token para la operación de intercambio no es ETH.deadlineSe puede configurar en:(new Date().getTime() / 1000) + 3600, lo que significa que es válido durante una hora.data: Datos de la operación de embalaje que debe realizarse.

    También es posible especificar lagasLimit/gasPrice/nonceconfiguración para llamadas de métodos, usamos pseudocodo para describir de nuevo:

    exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})
    

    Puede establecer parámetros{gasPrice: 11, gasLimit: 111, nonce: 111}De acuerdo con sus necesidades específicas, el parámetro se establece en el último parámetro delexchange.IOPuede omitir la funciónnoncey utilizar los valores predeterminados del sistema, o no establecergasLimit/gasPrice/noncey utilizar todos los valores predeterminados del sistema.

    Debe tenerse en cuenta que en el ejemplo, el atributo destateMutabilityEn elmulticall(uint256,bytes[])el método espayable, y elvalueEl atributo destateMutability":"payable"se puede ver desde elABIEl.exchange.IOLa función determinará los parámetros requeridos de acuerdostateMutabilityatributo en elABISi elstateMutabilityel atributo esnonpayable, el parámetrovalueNo es necesario que se entregue.

Llamadas de funciones comunes

  1. Obtiene la dirección de la billetera configurada por el objeto de intercambio.
function main() {
    Log(exchange.IO("address"))         // Print the wallet address of the private key configured on the exchange object.
}
  1. Cambiar los nodos RPC de la cadena de bloques.
function main() {
    var chainRpc = "https://bsc-dataseed.binance.org"
    e.IO("base", chainRpc)    // Switch to BSC chain
}

Funciones del indicador

Al llamar a las funciones de indicador, usted necesita añadirTA.o bientalib.como prefijo

Ejemplos de llamadas a las funciones de indicador entalibla biblioteca yTALa biblioteca:

function main(){
    var records = exchange.GetRecords()
    var macd = TA.MACD(records)
    var atr = TA.ATR(records, 14)

    // Print the last row of indicator values
    Log(macd[0][records.length-1], macd[1][records.length-1], macd[2][records.length-1])
    Log(atr[atr.length-1])

    // Print all indicator data, and JavaScript written strategies have integrated a talib library on FMZ Quant Trading platform 
    Log(talib.MACD(records))
    Log(talib.MACD(records, 12, 26, 9))
    Log(talib.OBV(records))

    // The talib library can also be passed in an array of numbers, which can be passed in order. For example: OBV (Records [Close], Records [Volume]) requires the parameters of the two arrays, including "Close" and "Volume"
    Log(talib.OBV([1,2,3], [7.1, 6.2, 3, 3]))

    // You can also directly pass in the "records" array containing the "Close" and "Volume" attribute
    Log(talib.OBV(records))
    Log(TA.Highest(records, 30, 'High'))
    Log(TA.Highest([1,2,3,4], 0))
}
# Python needs to install the talib library separately 
import talib
def main():
    r = exchange.GetRecords()
    macd = TA.MACD(r)
    atr = TA.ATR(r, 14)
    Log(macd[0][-1], macd[1][-1], macd[2][-1])
    Log(atr[-1])

    # For Python, the system extends the attributes of the array returned by GetRecords, and adds "Open", "High", "Low", "Close" and "Volume" to facilitate the call of the functions in the talib library
    Log(talib.MACD(r.Close))
    Log(talib.MACD(r.Close, 12, 26, 9))
    Log(talib.OBV(r.Close, r.Volume))

    Log(TA.Highest(r, 30, "High"))
    Log(TA.Highest([1, 2, 3, 4], 0))
void main() {
    auto r = exchange.GetRecords();
    auto macd = TA.MACD(r);
    auto atr = TA.ATR(r, 14);
    Log(macd[0][macd[0].size() - 1], macd[1][macd[1].size() - 1], macd[2][macd[2].size() - 1]);
    Log(atr[atr.size() - 1]);

    Log(talib.MACD(r));
    Log(talib.MACD(r, 12, 26, 9));
    Log(talib.OBV(r));

    Log(TA.Highest(r.Close(), 30));
}

Los datos de los siguientes parámetros son todos los datos obtenidos por funciónexchange.GetRecords(Period)¿ Qué pasa? Preste atención a la longitud derecords, cuando la longitud no cumple los requisitos de cálculo de parámetros de la función de indicador, se devolverá un valor no válido.

TA - Biblioteca de indicadores de uso común

ElTALa biblioteca de indicadores de la plataforma Quant Trading de FMZ ha optimizado los algoritmos de indicadores comúnmente utilizados para soportar la llamada de estrategias escritas enJavaScript, Pythonycpp Código de la biblioteca TA de código abierto.

MACD - Promedio móvil de convergencia y divergencia

TA.MACD(data, fast period, slow period, signal period), con los parámetros de período predeterminados de (12, 26, 9) devuelve las matrices bidimensionales, que son[DIF, DEA, MACD] respectively.

function main(){
    // You can fill in different k-line periods, such as PERIOD_M1, PERIOD_M30 and PERIOD_H1...
    var records = exchange.GetRecords(PERIOD_M15)
    var macd = TA.MACD(records, 12, 26, 9)
    // You can see from the log that three arrays are returned, corresponding to DIF, DEA, MACD
    Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2])
}
def main():
    r = exchange.GetRecords(PERIOD_M15)
    macd = TA.MACD(r, 12, 26, 9)
    Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2])
void main() {
    auto r = exchange.GetRecords(PERIOD_M15);
    auto macd = TA.MACD(r, 12, 26, 9);
    Log("DIF:", macd[0], "DEA:", macd[1], "MACD:", macd[2]);
}

KDJ - Indicador estocástico

TA.KDJ(data, period 1, period 2, period 3), con los parámetros de período predeterminados de (9, 3, 3) devuelve las matrices bidimensionales, que son(K, D, J) respectively.

function main(){
    var records = exchange.GetRecords(PERIOD_M15)
    var kdj = TA.KDJ(records, 9, 3, 3)
    Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2])
}
def main():
    r = exchange.GetRecords(PERIOD_M15)
    kdj = TA.KDJ(r, 9, 3, 3)
    Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2])
void main() {
    auto r = exchange.GetRecords();
    auto kdj = TA.KDJ(r, 9, 3, 3);
    Log("k:", kdj[0], "d:", kdj[1], "j:", kdj[2]);
}

Indicador de fuerza relativa

TA.RSI(data, period), con el parámetro de período predeterminado de 14, devuelve una matriz unidimensional.

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var rsi = TA.RSI(records, 14)
    Log(rsi)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    rsi = TA.RSI(r, 14)
    Log(rsi)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto rsi = TA.RSI(r, 14);
    Log(rsi); 
}

ATR - Volatilidad verdadera media

TA.ATR(data, period); ATR(datos, período), con el parámetro de período predeterminado de 14, devuelve una matriz unidimensional.

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var atr = TA.ATR(records, 14)
    Log(atr)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    atr = TA.ATR(r, 14)
    Log(atr)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto atr = TA.ATR(r, 14);
    Log(atr);
}

OBV - En el volumen del saldo

TA.OBV(data)devuelve una matriz unidimensional.

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var obv = TA.OBV(records)
    Log(obv)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    obv = TA.OBV(r)
    Log(obv)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto obv = TA.OBV(r);
    Log(obv);
}

La media móvil

TA.MA(data, period); MA ((data, period), con el parámetro de período predeterminado de 9, devuelve una matriz unidimensional.

function main(){
    var records = exchange.GetRecords(PERIOD_M30)
    var ma = TA.MA(records, 14)
    Log(ma)
}
def main():
    r = exchange.GetRecords(PERIOD_M30)
    ma = TA.MA(r, 14)
    Log(ma)
void main() {
    auto r = exchange.GetRecords(PERIOD_M30);
    auto ma = TA.MA(r, 14);
    Log(ma);
}

EMA - Promedio móvil exponencial

TA.EMA(data, period)es un indicador promedio exponencial, con el parámetro de período predeterminado de 9, devuelve una matriz unidimensional.

function main(){
    var records = exchange.GetRecords()
    // Determine if the number of K-line bars meets the requirement of the indicator calculation period 
    if (records && records.length > 9) {
        var ema = TA.EMA(records, 9)          
        Log(ema)
    }
}
def main():
    r = exchange.GetRecords()
    if r and len(r) > 9:
        ema = TA.EMA(r, 9)
        Log(ema)
void main() {
    auto r = exchange.GetRecords();
    if(r.Valid && r.size() > 9) {
        auto ema = TA.EMA(r, 9);
        Log(ema);
    }
}

Se aplicarán las siguientes condiciones:

TA.BOLL(data, period, multiplier); BOLL ((datos, período, multiplicador) es un indicador de banda de Bollinger, con los parámetros predeterminados de (20, 2), y devuelve una matriz bidimensional, a saber:[Upline, Midline, Downline].

function main() {
    var records = exchange.GetRecords()
    if(records && records.length > 20) {
        var boll = TA.BOLL(records, 20, 2)
        var upLine = boll[0]
        var midLine = boll[1]
        var downLine = boll[2]
        Log(upLine)
        Log(midLine)
        Log(downLine)
    }
}
def main():
    r = exchange.GetRecords()
    if r and len(r) > 20:
        boll = TA.BOLL(r, 20, 2)
        upLine = boll[0]
        midLine = boll[1]
        downLine = boll[2]
        Log(upLine)
        Log(midLine)
        Log(downLine)
void main() {
    auto r = exchange.GetRecords();
    if(r.Valid && r.size() > 20) {
        auto boll = TA.BOLL(r, 20, 2);
        auto upLine = boll[0];
        auto midLine = boll[1];
        auto downLine = boll[2];
        Log(upLine);
        Log(midLine);
        Log(downLine);
    }
}

Indicador de cocodrilo

TA.Alligator(data, mandible period, tooth period, upper lip period); Alligator ((datos, período mandibular, período dental, período del labio superior) es el indicador de Alligator, con los parámetros predeterminados de (13,8,5), y devuelve una matriz bidimensional, a saber[Mandible, Teeth, Upper Lip].

CMF - Flujo de caja de Chaikin

TA.CMF(data, period); CMF ((datos, período) es el indicador de flujo de efectivo de Chaikin, con el parámetro de período predeterminado de 20, devuelve una matriz unidimensional.

Precio más alto del período

TA.Highest(data, period, attribute), devuelve el valor máximo en el período más reciente (excluyendo la barra actual), comoTA.Highest(records, 30, 'High'). Si elperiodes 0, significa que todas las barras.attributeno se especifica, los datos se consideran una matriz ordinaria y devuelve un precio (tipo de valor).

Precio más bajo - período Precio más bajo

TA.Lowest(data, period, attribute), devuelve el valor mínimo del período más reciente (excluyendo el Bar actual), comoTA.Highest(records, 30, 'Low'). Si elperiodSi el atributo no se especifica, los datos se consideran una matriz ordinaria y se devuelve un precio (tipo de valor).

El uso deTA.Highest(...)yTA.Lowest(...)En elC++La estrategia debe tenerse en cuentaHighestyLowestlas funciones sólo tienen 2 parámetros respectivamente, y el primer parámetro no es el valor de retorno deauto r = exchange.GetRecords()función, por lo que usted necesita llamar el método derpara transmitir datos de atributos específicos, por ejemplo:r.Close()Los datos de cierre de precios.Close, High, Low, Open, Volumees comor.Close().

C++ejemplos:

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

    for(int j = 0; j < r.size(); j++){
        Log(r[j]);
    }

    // Note: if the first parameter passed in is not r, you need to call "r.Close()"
    auto highest = TA.Highest(r.Close(), 8);   
    Log(highest);                     
}

Biblioteca de terceros adjunta

JavaScript también

C++

Ejemplos

  • JavaScriptbibliotecahttp://mathjs.org/

    function main() {
        Log(math.round(math.e, 3))                // 2.718
        Log(math.atan2(3, -3) / math.pi)          // 0.75
        Log(math.log(10000, 10))                  // 4
        Log(math.sqrt(-4))                        // {"mathjs":"Complex","re":0,"im":2}   
    }
    

    http://mikemcl.github.io/decimal.js/

    function main() {
        var x = -1.2
        var a = Decimal.abs(x)
        var b = new Decimal(x).abs()
        Log(a.equals(b))                           // true  
    
        var y = 2.2
        var sum = Decimal.add(x, y)
        Log(sum.equals(new Decimal(x).plus(y)))

Más.