В процессе загрузки ресурсов... загрузка...

Инструкции по API FMZ

Автор:Нуль, Создано: 2020-04-20 10:19:00, Обновлено: 2023-04-12 14:44:56

sted 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()возвращает объект, когда вызов удается. Если вызов не удается, возвращенный объект все еще является объектом, который отличается от обычного возвращенного объекта атрибутомValid.

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

Разница междуmain()Функция вC++Письменная стратегия иmain()функция в стандарте C11: Доходное значениеC++Функция ввода программыmain()в C11 составляетintВC++Написать стратегию на платформе FMZ, запуск функции стратегии также является функциейmain()На платформе FMZ, возвращаемое значениеmain()Функция вC++Стратегияvoid 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));
}

Специальные вопросы JavaScript

По причинам языка JavaScript (Язык JavaScript поддерживает встроенные строкиasciiиutf-16кодирование только, чтобы не потерять данные), когда он столкнулся с строкой, которая не может быть закодирована, он вернетArrayBufferВсе интерфейсы API, которые могут передавать параметры строки, также поддерживают передачуArrayBuffer type.

Многопроводные JavaScript

Он действительно поддерживает многопоточную функциюJavaScriptязыковая стратегия из нижней части системы, включая: одновременное выполнение функций пользовательского выполнения; поддержка связи между одновременными потоками, поддержка связи между одновременными потоками и основной нитью; хранение, совместное использование переменных в среде потока и другие функции. До сих пор он поддерживает только использование в среде реального времени, пожалуйста, обратитесь к:https://www.fmz.com/bbs-topic/9974.

__ нить

В__Thread(function, arguments...)function создает нить, которая работает одновременно. Она не поддерживает прямую ссылку на переменные, кроме функции выполнения нитей (работающей в изолированной среде). Ссылки на внешние переменные не будут компилироваться. Ссылки на другие функции закрытия также не поддерживаются. Все API платформы могут быть вызваны внутри нитки, но другие функции, определенные пользователем, не могут быть вызваны. Параметрfunctionможет быть функция ссылка или анонимная функция.argumentsявляется параметромfunctionфункция (фактический параметр, переданный), иarguments...означает, что несколько параметров могут быть переданы.

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
}

Он поддерживает метод вызова__Thread([function, arguments...], [function, arguments...], ...), то есть несколько функций выполнения потоков выполняются последовательно в созданных потоках.

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

Функция одновременного исполнения передается__ThreadВ приведенном выше примере используетсяLogфункция для печати1 ~ 5Общие переменные между различными функциями выполнения потоков поддерживаются.this.dпеременная в приведенном выше примере может быть назначена вthreadTestFuncBФункция и используется вthreadTestFuncAОн поддерживает передачу функций, таких как"function threadTestFuncC(c) {Log(c)}"в приведенном выше примере, который позволяет потокам выполнять вызовы функций к внешним функциям и библиотекам, "импортированным" этим методом.

Для импорта внешних библиотек конкретный пример использования таков:

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 (Посвящение из Peek)

В__threadPeekMessage(threadId, timeout)функция считывает данные с канала связи нитки, параметрthreadIdявляется ИД, возвращаемый__Thread()функция, устанавливающая параметрthreadIdозначает принимать данные, отправленные потоком, представленным threadId. Когда он установлен на 0, это означает принимать данные, отправленные основным потоком, то есть текущей основной функцией (параметр threadId установлен на 0, который поддерживается только в одновременных функциях выполнения потока). Параметрtimeoutявляется настройкой временного задержки, которая будет блокировать и ждать в соответствии с количеством миллисекунд, установленных этим параметром.timeoutУстановлено на-1, это означает блокировать и ждать, пока данные в канале не будут получены.__threadPeekMessageФункция возвращает нулевое значение немедленно.

При написании программ, вы должны обратить внимание на проблему тупика потока.testFuncсоздаваемой параллельной нитью иmainфункция основной нити и функция выполнения нитиtestFuncбудет казнен первым.

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

__threadПослание

В__threadPostMessage(threadId, data)функция записывает данные на канал связи потока, параметрthreadIdявляется ИД, возвращаемый__Thread()функция, установить параметрthreadIdозначает отправку данных в нить, представленную threadId, и когда он установлен на 0, это означает отправку данных в главную нить, то есть текущую основную функцию (параметр threadId установлен на 0, который поддерживается только в одновременных функциях выполнения нитей). Параметрdataможет передавать значения, строки, булевые значения, объекты, массивы и другие типы данных.

Когда__threadPostMessagefunction называется в функции исполнения потока для отправки сигналов и данных, событие сообщения также будет генерироваться.EventLoop()функция получения уведомлений о сообщениях.

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

Присоединяйтесь

В__threadJoin(threadId, timeout)функция используется для ожидания потока с указанным ID для выхода и восстановления системных ресурсов.threadIdявляется ИД, возвращаемый__Thread()функция, и параметрtimeoutявляется настройкой задержки для ожидания окончания потока, в миллисекундах. Если задержка не установлена, это означает ожидание до конца выполнения потока. Возвратное значение: Тип является объектом, указывающим результат выполнения. Если он задерживается, возвратитеundefined.

Структура стоимости возврата, например:

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

__threadОкончить

В__threadTerminateфункция используется для принудительного прекращения потока и освобождения аппаратных ресурсов, используемых созданным потоком ( __threadJoin больше не может быть использован для ожидания конца). ПараметрthreadIdявляется ИД, возвращаемый__Thread()Функция. Возвращаемое значение: Булевое значение, указывающее результат выполнения.

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), функция используется для доступа к переменным, разделяемым между потоками.__threadJoinФункция (в ожидании успешного выхода) и не выполнила__threadTerminateпараметрthreadIdявляется ID потока, и параметрkeyявляется ключевым именем хранимогоkey-valueвозвращает значение: возвращает значение ключа, соответствующееkeyвkey-value pair.

threadId0 для обозначения основной нитки (т.е. нитки, гдеmainфункция находится), вы можете использовать__threadId()Функция для получения идентификатора текущей нитью, установить параметрthreadIdВы также можете читать переменные в среде потока указанного ID.

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

__threadSetData (установка данных)

__threadSetData(threadId, key, value), который используется для хранения переменных в среде потока.threadIdявляется идентификатором потока, параметромkeyявляется ключевым именем хранимогоkey-valueпара, и параметрvalueФункция не возвращает значения.

threadId0 для обозначения основной нитки (т.е. нитки, гдеmainВы можете воспользоваться__threadId()Функция для получения идентификатора текущей нитки.valueНеопределенное средство удаленияkey. Он поддерживает взаимный доступ к общим переменным между потоками.__threadJoinФункция (в ожидании успешного выхода) и не выполнила__threadTerminateзначение параметраvalueдолжна быть сериализируемой переменной.

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(), который используется для получения ID текущей нитки без параметров.threadIdтекущей нити.

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

Поддержка кодирования

ВJavaScriptпо стратегии языка, шестерковый код файла wasm может быть загружен, инстанцирован, и код в нем выполнен.JavaScriptКод, у него есть определенное преимущество скорости.

wasm.parseModule

wasm.parseModule(data), который анализирует модель шестерковой строки.dataпараметр - это кодировка wasm, которая была преобразована в шестичленную строку.Пример стратегии.

Например, следующий код функции C++ может быть компилирован в wasm код, а затем преобразован в шестеренковую строку, которая может быть использована в качествеdataпараметрwasm.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), который создает модель WASM.moduleПараметр - это модель wasm, а параметрoptпараметр - это конфигурационная информация, которая используется для настройки пространства стека, выделенного программе-инстанции wasm.

optПример настройки параметров:

{
    stack_size: 65*1024*1024,
}

callFunction

callFunction(funcName, param1, ...), который является методом инстанции модели wasm, используемой для выполнения функции в инстанции модели wasm.funcNameпараметр - это название функции, которая должна быть выполнена, иparam1параметр - это параметр, переданный при выполнении функции (указанный параметромfuncName).

Блокчейн

Платформа FMZ Quant Trading официально доступна для поддержки интерактивного звонкаweb3Контракт на цепочку, которая может получить доступ кdefiлегко обмениваться.

Эфириум

Конфигурация

На платформе FMZ Quant Trading, напишите код стратегии для реализации метода вызова смарт-контракта на цепочке Ethereum черезexchange.IOВ первую очередь, настроить узел доступа на платформе FMZ Quant Trading.infura.

На страницеобменFMZ Quant Trading платформа, выберите протокол: криптовалюта, а затем выберите обменWeb3. НастроитьRpc Address(адрес обслуживания узла доступа) иPrivate KeyОн поддерживает локальное развертывание частных ключей, см.Ключевая безопасность].

Регистрировать ABI

Название контракта, который является стандартомERC20Для вызова методов, отличных от стандартного контракта, необходимо зарегистрировать содержание ABI:exchange.IO("abi", tokenAddress, abiContent). Чтобы получить содержание ABI контракта, вы можете использовать следующий URL, чтобы получить его, принимая только поле результатов.

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

Способ вызова Ethereum RPC

Когда второй параметрexchange.IOфункция -"eth", вы можете вызвать методы RPC, доступные серверу узлов напрямую, например:

  • Запрос баланса ETH в кошельке

    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()))
    }
    
  • Перевод 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)
    }
    
  • Запрос газа

    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)
    }
    
  • Запрос eth_estimateГаз

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

Поддержка кодирования

Функцияexchange.IOвключает в себяencodeметод, который может вернуть код вызова функцииhexВы можете обратиться к публично доступным платформам.Uniswap V3 Trading Class Library шаблонДля конкретного использования.unwrapWETH9Метод используется здесь в качестве примера:

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

Когда вы звонитеexchange.IO("encode",...)функция, если второй параметр (тип строки) начинается с0x, это означает вызов метода на закодированный (encodeЕсли он не начинается с0x, он используется для кодирования указанного порядка типа.abi.encodeвsolidity- Обратитесь к следующему примеру.

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

Поддержка последовательного кодирования тупелей или типов, содержащих тупели:

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

Этот тип порядка состоит из:tupleиbytes, так что два параметра должны быть переданы при вызовеexchange.IOдоencode:

    1. Переменные, соответствующие типуtuple:
    {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }
    

    Переданные параметры также должны соответствовать структуре и типуtuple, как определено вtypesпараметр:tuple(a uint256, b uint8, c address).

    1. Переменные, соответствующие типуbytes:
    "0011"
    

Поддержка последовательного кодирования массивов или типов, содержащих массивы:

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

Поддержка encodePacked

Например, при вызове метода DEXUniswap V3, вы должны передать в параметрах, таких как путь обмена, так что вы должны использоватьencodePackagedОперация:

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

Поддержка декодирования

Обработка данных не только поддерживает кодирование (encode), а также декодирования (decode) Используйтеexchange.IO("decode", types, rawData)Функция выполненияdecode 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)
}

Пример выполняетencodePackedпервой операции в течениеpathобработки параметров, посколькуexactOutputПозволение метода, который должен быть закодирован позже, требуетpathКак параметр.encodeМетодexactOutputдоговор маршрутизации имеет только один параметр, и тип параметра:tuple. МетодexactOutputИмя кодируется как0x09b81346, который расшифровывает результатdecodeRawотexchange.IO ("decode",...)метод, и это соответствует переменнойdataTuple.

Поддержка переключения частных ключей

Он поддерживает переключение частных ключей для работы с несколькими адресами кошельков, например:

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

Способ вызова умного контракта

Первый параметрexchange.IOФункция:"api"Это означает, что это вызов является вызовом расширения.exchange.IOфункция - это адрес смарт-контракта, который будет вызван.

Если вызванный метод имеетpayableатрибут, вы должны добавить значение ETH передачи после названия метода (четвертый параметрexchange.IOфункция), которая может быть числового типа или передавать значение в виде строки, например,multicallМетодUniswap V3Ниже приведены примеры вызовов методов умных контрактов:

  • десятичные числа

    ВdecimalsМетод являетсяconstantМетодERC20что не генерируетgasС другой стороны, в этом случае можно использоватьtoken.decimalsВ обратном порядке значение: данные точностиtoken.

    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
    }
    
  • пособие

    ВallowanceМетод являетсяconstantМетодERC20что не генерируетgasПотребление, и он может запросить разрешенное количество определенногоtokenдля определенного контрактного адреса.allowanceМетод должен пройти в 2 параметра, первый - это адрес кошелька, а второй - авторизованный адрес.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: Адрес кошелька заменяется строкой owner в примере.spender: Авторизованный адрес контракта заменяется строкой spender в примере.Uniswap V3 router v1.

  • одобряю

    ВapproveМетод не является...constantМетодERC20что генерируетgasПотребление, которое используется для разрешенияtokenВ этом случае, если вы хотите, чтобы вы получилиapproveМетод должен пройти в 2 параметра, первый - это адрес, который должен быть разрешен, а второй - разрешенная сумма.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: адрес уполномоченного контракта, пример заменяется строкой spender, фактическое использование необходимо заполнить конкретный адрес, например, это может бытьUniswap V3 router v1 address. 0xde0b6b3a7640000: Количество разрешений, представленное здесь с помощью шестой десятичной строки, соответствует десятичному значению1e18, разделенный наtokenточная единица в примере (т.е. 1e18), дающая 1token authorized.

    Третий параметрexchange.IOФункция передается название методаapprove, который также может быть записан в видеmethodId, например: 0x571ac8b0. Также можно написать полное стандартное название метода, например approve(address,uint256) .

  • многократный звонок

    Вmulticallметод является неконстантным методомUniswap V3, что приведет кgasС другой стороны, это не означает, что они могут быть использованы для обмена токенами.multicallУ этого метода может быть несколько способов передачи параметров. Вы можете запросить ABI, содержащий метод, для получения деталей. Вам нужно зарегистрировать ABI перед вызовом метода. Возвращение значения:txid.

    Для конкретных примеровmulticallметоды вызовов, пожалуйста, обратитесь к общественностиUniswap V3 Trading Class Library шаблоннашей платформы.

    Псевдокод используется здесь для описания некоторых деталей:

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

    ContractV3SwapRouterV2: адрес маршрутизатора v2 Uniswap V3.value: сумма ETH, перечисленная, установлена на 0, еслиtokenInТокен для обменной операции не является ETH.deadline: Он может быть настроен на(new Date().getTime() / 1000) + 3600Это означает, что она действительна в течение часа.data: Данные о предстоящей упаковке.

    Также можно указатьgasLimit/gasPrice/nonceУстановка для вызовов методов, мы используем псевдокод, чтобы описать снова:

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

    Вы можете установить параметр{gasPrice: 11, gasLimit: 111, nonce: 111}в соответствии с вашими конкретными потребностями, параметр устанавливается на последний параметрexchange.IOВы можете пропуститьnonceи использовать системные настройки по умолчанию, или не устанавливатьgasLimit/gasPrice/nonceи использовать все значения системы по умолчанию.

    Следует отметить, что в примере атрибутstateMutabilityвmulticall(uint256,bytes[])метод:payable, иvalueпараметр должен быть передан.stateMutability":"payable"может быть просмотрен сABI.exchange.IOфункция будет определять необходимые параметры в соответствии сstateMutabilityатрибут вABIЕсли жеstateMutabilityатрибут - этоnonpayable, параметрvalueне нужно передавать.

Общие вызовы функций

  1. Получает адрес кошелька, настроенного обменным объектом.
function main() {
    Log(exchange.IO("address"))         // Print the wallet address of the private key configured on the exchange object.
}
  1. Переключите блокчейн RPC узлов.
function main() {
    var chainRpc = "https://bsc-dataseed.binance.org"
    e.IO("base", chainRpc)    // Switch to BSC chain
}

Функции индикатора

При вызове функций индикатора, вы должны добавитьTA.илиtalib.как префикс

Примеры вызова функций индикатора вtalibбиблиотека иTAбиблиотека:

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

Данные в следующих параметрах представляют собой все данные, полученные по функцииexchange.GetRecords(Period)- Да. Обратите внимание на длинуrecords, когда длина не соответствует требованиям вычисления параметров функции индикатора, возвращается недействительная величина.

TA - Библиотека часто используемых индикаторов

ВTAбиблиотека индикаторов платформы FMZ Quant Trading оптимизировала широко используемые алгоритмы индикаторов для поддержки вызова стратегий, написанных вJavaScript, Pythonиcpp открытый код библиотеки TA.

MACD - скользящая средняя конвергенции и дивергенции

TA.MACD(data, fast period, slow period, signal period), с параметрами периода по умолчанию (12, 26, 9) возвращает двумерные массивы, которые являются[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 - стохастический показатель

TA.KDJ(data, period 1, period 2, period 3), с параметрами периода по умолчанию (9, 3, 3) возвращает двумерные массивы, которые являются(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 - Индекс относительной силы

TA.RSI(data, period), с параметром периода по умолчанию 14, возвращает одномерный массив.

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 - Средняя истинная волатильность

TA.ATR(data, period); ATR ((data, period), с параметром периода по умолчанию 14, возвращает одномерный массив.

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 - По объему баланса

TA.OBV(data)возвращает одномерный массив.

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 - скользящая средняя

TA.MA(data, period); MA ((data, period), с параметром периода по умолчанию 9, возвращает одномерный массив.

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 - Экспоненциальная скользящая средняя

TA.EMA(data, period)представляет собой показатель средней экспоненциальной величины с параметром периода по умолчанию 9, возвращает одномерный массив.

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 - полосы Боллинджера

TA.BOLL(data, period, multiplier); BOLL ((data, period, multiplier) - индикатор полосы Боллинджера с параметрами по умолчанию (20, 2) и возвращает двумерный массив, а именно[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);
    }
}

Аллигатор - индикатор аллигатора

TA.Alligator(data, mandible period, tooth period, upper lip period); Alligator ((data, mandible period, tooth period, upper lip period) является индикатором Alligator с параметрами по умолчанию (13,8,5), и возвращает двумерный массив, а именно[Mandible, Teeth, Upper Lip].

CMF - денежный поток в целом

TA.CMF(data, period); CMF ((data, period) - индикатор денежного потока Чайкина, с параметром периода по умолчанию 20, возвращает одномерный массив.

Наиболее высокая цена за период

TA.Highest(data, period, attribute), возвращает максимальное значение за последний период (без учета текущего порога), например:TA.Highest(records, 30, 'High'). ЕслиperiodЭто означает, что все Бар.attributeне указана, данные рассматриваются как обычный массив и возвращает цену (тип значения).

Наименьшая - период Наименьшая цена

TA.Lowest(data, period, attribute), возвращает минимальное значение за последний период (без учета текущего порога), например:TA.Highest(records, 30, 'Low'). ЕслиperiodЕсли атрибут не указан, данные рассматриваются как обычный массив, и возвращается цена (тип значения).

ИспользованиеTA.Highest(...)иTA.Lowest(...)вC++следует отметить, чтоHighestиLowestфункции имеют только 2 параметра соответственно, и первый параметр не возвращается значениеauto r = exchange.GetRecords()функция, так что вы должны вызвать методrдля передачи данных конкретных атрибутов, например: passr.Close()Применение метода покупкиClose, High, Low, Open, Volumeэто какr.Close().

C++Примеры:

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

Приложенная библиотека третьих лиц

JavaScript

C++

Примеры

  • JavaScriptбиблиотекаhttp://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)))

Больше