O recurso está a ser carregado... Carregamento...

Instruções da API FMZ

Autora:Zero., Criado: 2020-04-20 10:19:00, Atualizado: 2023-04-12 14:44:56

onde o endereço IP é10.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()retorna um objeto, quando a chamada é bem sucedida. Se a chamada falhar, o objeto retornado ainda é um objeto, que é distinguido do objeto normal retornado pelo 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);
        }
    }
    

A diferença entre omain()função naC++estratégia escrita emain()Função na norma C11: O valor de retorno doC++Função de entrada do programamain()em C11 é deintNo que respeita aoC++estratégia escrita na plataforma FMZ, a função de inicialização da estratégia é também a funçãomain(), mas estas duas não são a mesma função, apenas com o mesmo nome.main()função naC++A estratégia é 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));
}

Questões especiais do JavaScript

Por razões de linguagem JavaScript (a linguagem JavaScript suporta cadeia de caracteresasciieutf-16codificação apenas, a fim de não perder dados), quando encontrou uma cadeia que não pode ser codificada, ele retornará oArrayBufferTodas as interfaces de API que podem passar parâmetros de string também suportam passar oArrayBuffer type.

Multi-threading do JavaScript

Ele realmente suporta a função multi-threading doJavaScriptestratégia de linguagem a partir da base do sistema, incluindo: execução simultânea de funções de execução personalizadas; suporte para comunicação entre threads simultâneos, suporte para comunicação entre threads simultâneos e o thread principal; armazenamento, compartilhamento de variáveis no ambiente do thread e outras funções.https://www.fmz.com/bbs-topic/9974.

__Fio

O__Thread(function, arguments...)função cria um thread que é executado em simultâneo. Não suporta referência direta a variáveis além da função de execução do thread (funcionando como um ambiente isolado). As referências a variáveis externas não serão compiladas. As referências a outras funções de fechamento também não são suportadas. Todas as APIs da plataforma podem ser chamadas dentro do thread, mas outras funções definidas pelo usuário não podem ser chamadas.functionpode ser uma referência de função ou uma função anônima.argumentsé o parâmetro dofunctionfunção (o parâmetro efetivo transmitido), earguments...significa que podem ser transmitidos vários parâmetros. Valor de retorno: o ID do thread.

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
}

Suporta o método de chamada de__Thread([function, arguments...], [function, arguments...], ...), ou seja, múltiplas funções de execução de thread são executadas sequencialmente nos threads criados.

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

A função de execução simultânea passou para o__ThreadA função será executada em ordem inversa.Logfunção para imprimir1 ~ 5As variáveis compartilhadas entre diferentes funções de execução de thread são suportadas.this.dA variável no exemplo acima pode ser atribuída nothreadTestFuncBfunção e utilizado nathreadTestFuncAEle suporta a passagem em funções de cadeias, tais como"function threadTestFuncC(c) {Log(c)}"no exemplo acima, que permite que os threads executem chamadas de funções para funções externas e bibliotecas importadas por este método.

Para a importação de bibliotecas externas, um exemplo específico de uso é o seguinte:

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")])))
}

__threadPeekMessage

O__threadPeekMessage(threadId, timeout)função lê dados do canal de comunicação do fio, o parâmetrothreadIdé o ID devolvido pelo__Thread()função, definindo o parâmetrothreadIdsignifica receber os dados enviados pelo thread representado pelo threadId. Quando definido como 0, significa receber os dados enviados pelo thread principal, ou seja, a função principal atual (o parâmetro threadId é definido como 0, que só é suportado em funções de execução de thread simultâneas).timeouté uma definição de timeout, que bloqueia e espera de acordo com o número de milissegundos definidos por este parâmetro.timeoutestá definido em-1, significa bloquear e esperar até que os dados no canal sejam recebidos.__threadPeekMessageA função retornará um valor nulo imediatamente.

Ao escrever programas, você precisa prestar atenção ao problema do impasse de threads.testFuncdo fio concorrente criado e domainfunção do fio principal e função de execução do fiotestFuncserá executado primeiro.

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

__threadPostMessage

O__threadPostMessage(threadId, data)função escreve dados para o canal de comunicação thread, o parâmetrothreadIdé o ID devolvido pelo__Thread()Função, definir o parâmetrothreadIdsignifica enviar dados para o thread representado pelo threadId, e quando definido como 0, significa enviar dados para o thread principal, ou seja, a função principal atual (o parâmetro threadId é definido como 0, que só é suportado em funções de execução de thread simultâneas).dataPode passar valores, strings, valores booleanos, objetos, matrizes e outros tipos de dados.

Quando o__threadPostMessagefunção é chamada na função de execução de um thread para enviar sinais e dados, um evento de mensagem também será gerado.EventLoop()Função para receber notificações de mensagens.

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

Junta-te.

O__threadJoin(threadId, timeout)A função é usada para esperar que o thread com a ID especificada para sair e recuperar os recursos do sistema.threadIdé o ID devolvido pelo__Thread()função, e o parâmetrotimeouté a definição de tempo de espera para o final do thread, em milissegundos. Se o tempo de espera não for definido, significa esperar até o final da execução do thread. Valor de retorno: O tipo é um objeto, indicando o resultado da execução. Se expirar, retorneundefined.

Estrutura de valor de retorno, por exemplo:

{
    "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
}

__threadTerminar

O__threadTerminatefunção é usada para encerrar o thread forçosamente e liberar os recursos de hardware utilizados pelo thread criado (o __threadJoin não pode mais ser usado para esperar o fim).threadIdé o ID devolvido pelo__Thread()Função. Valor de retorno: valor booleano, indicando o resultado da execução.

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

__threadGetData(threadId, key), a função é usada para acessar as variáveis compartilhadas entre os tópicos. Os dados são válidos quando o tópico não executou o__threadJoinFunção (em espera de uma saída bem sucedida) e não executou o__threadTerminateFunção (terminou o fio forçadamente).threadIdé o ID do thread e o parâmetrokeyé o nome de chave do ficheiro armazenadokey-valueValor de retorno: Retorna o valor da chave correspondente akeyemkey-value pair.

threadIdé 0 para indicar o fio principal (ou seja, o fio ondemainfunção está localizado), você pode usar__threadId()função para obter o ID do tópico atual, definir o parâmetrothreadIdVocê também pode ler as variáveis no ambiente do thread do 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"))
}

__threadSetDados

__threadSetData(threadId, key, value), que é usado para armazenar variáveis no ambiente do thread.threadIdé o ID do thread, o parâmetrokeyé o nome de chave do ficheiro armazenadokey-valuepar, e o parâmetrovalueé o valor chave. A função não tem valor de retorno.

threadIdé 0 para indicar o fio principal (ou seja, o fio ondemainfunção está localizada), e você pode usar o__threadId()função para obter a ID do thread atual.valuemeios não especificados para eliminarkey. Suporta o acesso mútuo a variáveis compartilhadas entre threads. Os dados são válidos quando o thread não executou o__threadJoinfunção (em espera de saída bem sucedida) e não executou o__threadTerminateO valor do parâmetrovaluedeve ser uma variável serializável.

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

_threadId

__threadId(), que é utilizado para obter o ID do thread atual, sem parâmetros.threadIddo fio corrente.

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

Apoio à codificação

EmJavaScriptA estratégia de linguagem, o código hexadecimal do arquivo wasm pode ser carregado, instanciado e o código nele executado.JavaScriptCódigo, tem uma certa vantagem de velocidade.

wasm.parseModule

wasm.parseModule(data), que analisa um modelo de cadeia hexadecimal.dataParâmetro é a codificação wasm que foi convertida em uma cadeia hexadecimal.Exemplo de estratégia.

Por exemplo, o seguinte código de função c ++ pode ser compilado em código wasm, e, em seguida, convertido em uma cadeia hexadecimal, que pode ser usado como odataParâmetro dowasm.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 cria uma instância de modelo wasm.moduleO parâmetro é o modelo wasm, e ooptO parâmetro é a informação de configuração, que é usada para definir o espaço de pilha alocado ao programa de instância wasm.

optExemplo de definição de parâmetros:

{
    stack_size: 65*1024*1024,
}

callFunction

callFunction(funcName, param1, ...), que é um método da instância do modelo wasm, usado para executar a função na instância do modelo wasm.funcNameParâmetro é o nome da função a executar, e oparam1Parâmetro é o parâmetro transmitido ao executar a função (especificado pelo parâmetrofuncName).

Blockchain

A plataforma FMZ Quant Trading é oficialmente acessível para apoiar a chamada interativa doweb3O contrato sobre a cadeia, que pode aceder aodefitroca facilmente.

Ethereum

Configuração

Na plataforma FMZ Quant Trading, escrever código de estratégia para implementar a chamada de método de contrato inteligente na cadeia Ethereum através doexchange.IOPrimeiro, configure o nó de acesso na plataforma FMZ Quant Trading. Os nós de acesso podem ser nós auto-construídos ou usar serviços de terceiros, comoinfura.

Na página de Troca FMZ Quant plataforma de negociação, selecione o protocolo: criptomoeda, e depois seleciona a trocaWeb3ConfigurarRpc Address(endereço de serviço do nó de acesso) ePrivate Key(chave privada). Ele suporta a implantação localizada de chaves privadas, verSegurança fundamental].

Registro ABI

O que é um contrato padrão?ERC20O método não requer registro e pode ser chamado diretamente.exchange.IO("abi", tokenAddress, abiContent). Para obter o conteúdo ABI de um contrato, você pode usar o seguinte URL para obtê-lo, tomando o campo de resultado apenas.

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

Método de chamada do Ethereum RPC

Quando o segundo parâmetro doexchange.IOfunção é"eth", você pode chamar os métodos RPC disponíveis para o servidor de nó diretamente, por exemplo:

  • Consultar o saldo de ETH na carteira

    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()))
    }
    
  • Transferência 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)
    }
    
  • Query gasPrice

    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)
    }
    
  • Query eth_estimateGás

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

Suporte para codificação

A funçãoexchange.IOEncapsula oencodemétodo, que pode retornar a codificação de chamada de função parahexPode consultar as plataformas disponíveis publicamente Uniswap V3 Trading Class Library modeloA chamada da codificaçãounwrapWETH9método é usado aqui como exemplo:

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

Ao ligar para oexchange.IO("encode",...)função, se o segundo parâmetro (tipo de string) começar com0x, significa a chamada do método no código (encode) contrato inteligente.0x, é utilizado para codificar a ordem de tipo especificada.abi.encodeemsolidity. Consulte o seguinte exemplo.

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
    */
}

Suporte à codificação sequencial de tuplas ou tipos contendo tuplas:

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

Esta ordem de tipo é composta por:tupleebytes, então dois parâmetros precisam ser passados quando chamadosexchange.IOparaencode:

    1. Variaveis correspondentes ao tipotuple:
    {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }
    

    Os parâmetros transmitidos devem igualmente ser coerentes com a estrutura e o tipo detuple, tal como definido notypesParâmetro:tuple(a uint256, b uint8, c address).

    1. Variaveis correspondentes ao tipobytes:
    "0011"
    

Suporte para codificação sequencial de matrizes ou tipos que contenham matrizes:

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

Suporte para encodePacked

Por exemplo, ao chamar o método DEX deUniswap V3, você precisa passar em parâmetros, tais como o caminho de troca, então você precisa usar oencodePackagedOperação:

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

Suporte para decodificação

O processamento de dados não só suporta a codificação (encode), mas também a decodificação (decode) Utilize oexchange.IO("decode", types, rawData)função para executar odecode 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)
}

O exemplo executa oencodePackedA primeira operação durante opathProcessamento de parâmetros, porque oexactOutputchamada de método que precisa ser codificada mais tarde precisa dopathA partir daí, oencodeMétodo deexactOutputcontrato de roteamento tem apenas um parâmetro, e o tipo de parâmetro étupleO métodoexactOutputnome é codificado como0x09b81346, que é decodificado o resultadodecodeRawporexchange.IO ("decode",...)método, e é consistente com a variáveldataTuple.

Suporte para trocar chaves privadas

Ele suporta a troca de chaves privadas para operar vários endereços de carteira, por exemplo:

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

Método de chamada do contrato inteligente

O primeiro parâmetro doexchange.IOfunção é:"api"O segundo parâmetro doexchange.IOFunção é o endereço do contrato inteligente a ser chamado.

Se o método chamado tiver opayableAtributo, você precisa adicionar um transferir ETH valor após o nome do método (o quarto parâmetro doexchange.IOfunção), que pode ser de tipo numérico ou passar um valor em forma de cadeia, por exemplo, omulticallmétodo deUniswap V3Os seguintes conteúdos são exemplos de algumas chamadas de métodos de contrato inteligente:

  • números decimais

    OdecimalsO método éconstantmétodo deERC20que não geramgasA utilização de dados de precisão de um determinadotoken. OdecimalsValor de retorno: os dados de precisão 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
    }
    
  • subsídio

    OallowanceO método éconstantmétodo deERC20que não geramgasA Comissão considera que a Comissão não pode, por conseguinte,tokenO contrato de trabalho é um contrato de trabalho.allowanceRetorno de valor: o valor de autorização de uma carteira é o valor de uma carteira.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: O endereço da carteira é substituído pela cadeia owner no exemplo.spenderNo exemplo, o endereço do contrato autorizado é substituído pela cadeia spender.Uniswap V3 router v1.

  • Aprovar

    OapproveO método é um não-constantmétodo deERC20que geragasConsumo, que é utilizado para autorizar umatokenO montante da operação é fixado num determinado endereço do contrato.approveO método precisa passar em 2 parâmetros, o primeiro é o endereço a ser autorizado e o segundo é o montante autorizado.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: O endereço do contrato autorizado, o exemplo é substituído pela cadeia spender, o uso real precisa preencher o endereço específico, por exemplo, pode serUniswap V3 router v1 address. 0xde0b6b3a7640000: O número de autorizações, representado aqui por uma cadeia hexadecimal, corresponde a um valor decimal de1e18, dividido pelotokenunidade de precisão no exemplo (ou seja, 1e18), dando 1token authorized.

    O terceiro parâmetro doexchange.IOfunção é passada o nome do métodoapprove, que também pode ser escrito na forma demethodId, por exemplo: 0x571ac8b0. Também é possível escrever o nome completo do método padrão, como approve(address,uint256) .

  • Multicall

    Omulticallmétodo é um método não constante deUniswap V3, que irá gerargasO consumo e ser usado para trocar tokens de várias maneiras.multicallO método pode ter vários métodos de passagem de parâmetros. Você pode consultar o ABI contendo o método para obter detalhes. Você precisa registrar o ABI antes de chamar o método. Retorno de valor:txid.

    Para exemplos específicos demulticallAplicação do método de chamadas. Uniswap V3 Trading Class Library modeloda nossa plataforma.

    Pseudocódigo é usado aqui para descrever alguns detalhes:

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

    ContractV3SwapRouterV2: endereço do roteador v2 do Uniswap V3.value: O montante de ETH transferido, definido em 0 se otokenIntoken para a operação de troca não é ETH.deadline: Pode ser definido como(new Date().getTime() / 1000) + 3600, o que significa que é válido por uma hora.data: Os dados da operação de embalagem a efectuar.

    É também possível especificar ogasLimit/gasPrice/nonceconfiguração para chamadas de método, usamos pseudocode para descrever novamente:

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

    Você pode definir parâmetro{gasPrice: 11, gasLimit: 111, nonce: 111}De acordo com as suas necessidades específicas, o parâmetro é definido para o último parâmetro doexchange.IOPode omitir a funçãononcee usar os padrões do sistema, ou não definirgasLimit/gasPrice/noncee usar todos os valores padrão do sistema.

    Deve notar-se que no exemplo, o atributo destateMutabilityemmulticall(uint256,bytes[])método épayable, e ovalueO atributo destateMutability":"payable"A partir daí, oABI. Oexchange.IOA função irá determinar os parâmetros necessários de acordo com ostateMutabilityatributo noABISe ostateMutabilityatributo énonpayable, o parâmetrovaluenão precisa de ser transmitido.

Chamadas de funções comuns

  1. Obtém o endereço da carteira configurada pelo objeto de troca.
function main() {
    Log(exchange.IO("address"))         // Print the wallet address of the private key configured on the exchange object.
}
  1. Troque os nós RPC do blockchain.
function main() {
    var chainRpc = "https://bsc-dataseed.binance.org"
    e.IO("base", chainRpc)    // Switch to BSC chain
}

Funções do indicador

Ao chamar as funções do indicador, você precisa adicionarTA.outalib.como prefixo

Exemplos de chamada das funções de indicador emtalibBiblioteca eTABiblioteca:

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

Os dados dos seguintes parâmetros são todos os dados obtidos por funçãoexchange.GetRecords(Period)- Não. Preste atenção ao comprimento dorecords, quando o comprimento não satisfazer os requisitos de cálculo dos parâmetros da função indicador, será devolvido um valor inválido.

TA - Biblioteca de indicadores comumente utilizados

OTAbiblioteca de indicadores da plataforma FMZ Quant Trading optimizou os algoritmos de indicadores comumente usados para suportar a chamada de estratégias escritas emJavaScript, Pythonecpp código de biblioteca TA de código aberto.

MACD - Média móvel de convergência e divergência

TA.MACD(data, fast period, slow period, signal period), com os parâmetros de período padrão de (12, 26, 9) retorna as matrizes bidimensionais, que são[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), com os parâmetros de período padrão de (9, 3, 3) retorna as matrizes bidimensionais, que são(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]);
}

RSI - Índice de força relativa

TA.RSI(data, period), com o parâmetro de período padrão de 14, retorna uma 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 - Volatilidade real média

TA.ATR(data, period); ATR ((data, period), com o parâmetro de período padrão de 14, retorna uma 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 - Volume do balanço

TA.OBV(data)Retorna uma 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);
}

MA - Média móvel

TA.MA(data, period); MA ((data, período), com o parâmetro de período padrão de 9, retorna uma 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 - Média Móvel Exponencial

TA.EMA(data, period)é um indicador de média exponencial, com o parâmetro de período padrão de 9, retorna uma 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);
    }
}

BOLL - Bandas de Bollinger

TA.BOLL(data, period, multiplier); BOLL ((data, período, multiplicador) é o indicador de Bollinger Band, com os parâmetros padrão de (20, 2), e retorna uma 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);
    }
}

Alligador - Indicador de Alligador

TA.Alligator(data, mandible period, tooth period, upper lip period); Alligator ((data, período da mandíbula, período do dente, período do lábio superior) é o indicador Alligator, com os parâmetros padrão de (13,8,5), e retorna uma matriz bidimensional, a saber:[Mandible, Teeth, Upper Lip].

CMF - Fluxo de caixa de Chaikin

TA.CMF(data, period); CMF ((data, período) é o indicador Chaikin Money Flow, com o parâmetro de período padrão de 20, retorna uma matriz unidimensional.

Preço mais elevado - Período mais elevado

TA.Highest(data, period, attribute), retorna o valor máximo no período mais recente (excluindo o Bar atual), tal comoTA.Highest(records, 30, 'High')Se operiodé 0, significa todos Bars. Se oattributeNão é especificado, os dados são considerados como uma matriz ordinária, e retorna um preço (tipo de valor).

Preço mais baixo - período Preço mais baixo

TA.Lowest(data, period, attribute), retorna o valor mínimo do período mais recente (excluindo o Bar corrente), tal comoTA.Highest(records, 30, 'Low')Se operiodSe o atributo não for especificado, os dados são considerados uma matriz comum e um preço (tipo de valor) é devolvido.

A utilização deTA.Highest(...)eTA.Lowest(...)emC++A estratégia deve ser observada queHighesteLowestfunções têm apenas 2 parâmetros, respectivamente, e o primeiro parâmetro não é o valor de retorno deauto r = exchange.GetRecords()função, então você precisa chamar o método derpara passar dados de atributos específicos, por exemplo: passr.Close()O método de compra deClose, High, Low, Open, VolumeÉ como...r.Close().

C++Exemplos:

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 terceiros anexada

JavaScript

C++

Exemplos

  • 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)))

Mais.