alamat IP sted ialah 10.0.3.15 { C: $ 00FFFF }
#### 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)
}
}
exchange.GetTicker()
mengembalikan objek, apabila panggilan berjaya. Jika panggilan gagal, objek yang dikembalikan masih objek, yang dibezakan dari objek yang dikembalikan biasa oleh atributValid
. 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);
}
}
Perbezaan antaramain()
fungsi dalamC++
strategi bertulis danmain()
fungsi dalam standard C11:
Nilai pulanganC++
fungsi kemasukan programmain()
dalam C11 ialahint
jenis.C++
menulis strategi di platform FMZ, fungsi permulaan strategi juga fungsimain()
, tetapi kedua-dua fungsi ini tidak sama, hanya dengan nama yang sama.main()
fungsi dalamC++
strategi adalahvoid
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));
}
Untuk alasan bahasa JavaScript (JavaScript bahasa terbina dalam sokongan rentetanascii
danutf-16
hanya pengekodan, supaya tidak kehilangan data), apabila ia menemui rentetan yang tidak boleh dikodkan, ia akan mengembalikanArrayBuffer
Semua antara muka API yang boleh lulus parameter rentetan juga menyokong lulusArrayBuffer
type.
Ia benar-benar menyokong fungsi pelbagai benangJavaScript
strategi bahasa dari bahagian bawah sistem, termasuk: pelaksanaan serentak fungsi pelaksanaan tersuai; sokongan untuk komunikasi antara utas serentak, sokongan untuk komunikasi antara utas serentak dan utas utama; penyimpanan, perkongsian pembolehubah dalam persekitaran utas dan fungsi lain. Ia hanya menyokong penggunaan dalam persekitaran perdagangan langsung setakat ini, sila rujuk:https://www.fmz.com/bbs-topic/9974.
Peraturan__Thread(function, arguments...)
function mencipta thread yang berjalan serentak. Ia tidak menyokong rujukan langsung kepada pembolehubah selain daripada fungsi pelaksanaan thread (berjalan sebagai persekitaran yang terpencil). Rujukan kepada pembolehubah luaran akan gagal disusun. Rujukan kepada fungsi penutupan lain juga tidak disokong. Semua API platform boleh dipanggil di dalam thread, tetapi fungsi lain yang ditakrifkan pengguna tidak boleh dipanggil. Parameterfunction
boleh menjadi rujukan fungsi atau fungsi tanpa nama.arguments
ialah parameterfunction
fungsi (parameter sebenar yang dihantar), danarguments...
bermaksud bahawa beberapa parameter boleh diteruskan. Nilai balik: ID benang.
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
}
Ia menyokong kaedah panggilan__Thread([function, arguments...], [function, arguments...], ...)
, iaitu, pelbagai fungsi pelaksanaan benang dijalankan secara berurutan dalam benang yang dicipta.
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)
}
Fungsi pelaksanaan serentak diteruskan kepada__Thread
contoh di atas akan menggunakanLog
fungsi untuk mencetak1 ~ 5
pemboleh ubah bersama antara fungsi pelaksanaan benang yang berbeza disokong.this.d
pembolehubah dalam contoh di atas boleh diberikan dalamthreadTestFuncB
fungsi dan digunakan dalamthreadTestFuncA
Ia menyokong lulus dalam rentetan fungsi, seperti"function threadTestFuncC(c) {Log(c)}"
dalam contoh di atas, yang membolehkan utas untuk menjalankan panggilan fungsi kepada fungsi luaran dan perpustakaan
Untuk mengimport perpustakaan luaran, contoh penggunaan khusus adalah seperti berikut:
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")])))
}
Peraturan__threadPeekMessage(threadId, timeout)
fungsi membaca data dari saluran komunikasi benang, parameterthreadId
adalah ID yang dikembalikan oleh__Thread()
fungsi, menetapkan parameterthreadId
bermaksud untuk menerima data yang dihantar oleh thread yang diwakili oleh threadId. Apabila ditetapkan kepada 0, ia bermaksud untuk menerima data yang dihantar oleh thread utama, iaitu fungsi utama semasa (parameter threadId ditetapkan kepada 0, yang hanya disokong dalam fungsi pelaksanaan thread serentak). Parametertimeout
adalah tetapan waktu, yang akan menyekat dan menunggu mengikut bilangan milidetik yang ditetapkan oleh parameter ini. Jikatimeout
ditetapkan kepada-1
, ia bermaksud untuk menyekat dan menunggu sehingga data dalam saluran diterima. Apabila utas penghantar saluran selesai pelaksanaan dan tidak ada data,__threadPeekMessage
Nilai pulangan: data yang diterima.
Apabila menulis program, anda perlu memberi perhatian kepada masalah thread deadlock. contoh berikut adalah komunikasi antara fungsi pelaksanaantestFunc
daripada benang serentak yang dicipta danmain
fungsi benang utama, dan fungsi pelaksanaan benangtestFunc
akan dieksekusi terlebih dahulu.
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)
}
}
Peraturan__threadPostMessage(threadId, data)
fungsi menulis data kepada saluran komunikasi benang, parameterthreadId
adalah ID yang dikembalikan oleh__Thread()
fungsi, menetapkan parameterthreadId
bermaksud untuk menghantar data ke thread yang diwakili oleh threadId, dan apabila ditetapkan kepada 0, ia bermaksud untuk menghantar data ke thread utama, iaitu fungsi utama semasa (parameter threadId ditetapkan kepada 0, yang hanya disokong dalam fungsi pelaksanaan thread serentak). Parameterdata
boleh lulus nilai, rentetan, nilai Boolean, objek, array dan jenis data lain. Fungsi ini tidak mempunyai nilai balik.
Apabila__threadPostMessage
fungsi dipanggil dalam fungsi pelaksanaan benang untuk menghantar isyarat dan data, peristiwa mesej juga akan dihasilkan.EventLoop()
fungsi untuk menerima pemberitahuan mesej.
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)
}
Peraturan__threadJoin(threadId, timeout)
fungsi digunakan untuk menunggu untuk utas dengan Id yang ditentukan untuk keluar dan mendapatkan semula sumber sistem.threadId
adalah ID yang dikembalikan oleh__Thread()
fungsi, dan parametertimeout
adalah tetapan masa untuk menunggu akhir thread, dalam mili saat. Jika timeout tidak ditetapkan, ia bermakna menunggu sehingga akhir pelaksanaan thread. Nilai balik: Jenis adalah objek, yang menunjukkan hasil pelaksanaan. Jika ia masa keluar, kembaliundefined
.
Struktur nilai pulangan, contohnya:
{
"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
}
Peraturan__threadTerminate
fungsi digunakan untuk menamatkan thread secara paksa dan melepaskan sumber perkakasan yang digunakan oleh thread yang dicipta (the __threadJoin tidak boleh lagi digunakan untuk menunggu akhir). ParameterthreadId
adalah ID yang dikembalikan oleh__Thread()
Nilai pulangan: Nilai Boolean, yang menunjukkan hasil pelaksanaan.
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)
}
```threadId``` is 0 to indicate the main thread (i.e. the thread where ```main``` function is located), you can use ```__threadId()``` function to get the Id of the current thread, set the parameter ```threadId``` to the current thread Id, and use it to read the variables stored in the current thread in the thread execution function. You can also read the variables in the thread environment of the specified Id.
```js
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"))
}
```threadId``` is 0 to indicate the main thread (i.e. the thread where ```main``` function is located), and you can use the ```__threadId()``` function to get the Id of the current thread. ```value``` not specified means to delete ```key```. It supports mutual access to shared variables between threads. The data is valid when the thread has not executed the ```__threadJoin``` function (waiting for successful exit) and has not executed the ```__threadTerminate``` function (terminate the thread forcibly). The value of the parameter ```value``` must be a serializable variable.
```js
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"))
}
```js
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())
}
DalamJavaScript
Strategi bahasa, kod hex fail wasm boleh dimuatkan, dicontohkan, dan kod di dalamnya dijalankan.JavaScript
Kod, ia mempunyai kelebihan kelajuan tertentu.
For example, the following c++ function code can be compiled into wasm code, and then converted into a hex string, which can be used as the ```data``` parameter of the ```wasm.parseModule(data)``` function.
```cpp
// Recursive Algorithm for Fibonacci Numbers
int fib(int f) {
if (f < 2) return f;
return fib(f - 1) + fib(f - 2);
}
```opt``` parameter setting example:
{ stack_size: 65*1024*1024, { C: $ 00FFFF }
#### callFunction
```callFunction(funcName, param1, ...)```, which is a method of the wasm model instance, used to execute the function in the wasm model instance. The ```funcName``` parameter is the name of the function to be executed, and the ```param1``` parameter is the parameter passed in when executing the function (specified by the parameter ```funcName```).
## Blockchain
The FMZ Quant Trading platform is officially accessible to support the interactive call of the ```web3``` contract on the chain, which can access the ```defi``` exchange easily.
### Ethereum
#### Configuration
On the FMZ Quant Trading platform, write strategy code to implement the method call of smart contract on the Ethereum chain through the ```exchange.IO``` function. First, configure the access node on the FMZ Quant Trading platform. The access nodes can be self-built nodes or use third-party services, such as ```infura```.
On the page of ["Exchange"](https://www.fmz.com/m/platforms) FMZ Quant Trading platform, select the protocol: cryptocurrency, and then selects the exchange ```Web3```. Configure ```Rpc Address``` (service address of access node) and ```Private Key``` (private key). It supports localized deployment of private keys, see [Key Security](https://www.fmz.com/api#key-security)].
#### Register ABI
Calling a contract that is a standard ```ERC20``` method does not require registration and it can be called directly. Calling methods other than the standard contract requires registering the ABI content: ```exchange.IO("abi", tokenAddress, abiContent)```. To get the ABI content of a contract, you can use the following URL to get it, taking the result field only.
#### Method of calling Ethereum RPC
When the second parameter of the ```exchange.IO``` function is ```"eth"```, you can call the RPC methods available to the node server directly, for example:
- Query the balance of ETH in the wallet
```js
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()))
}
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)
}
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)
}
Fungsiexchange.IO
merangkumiencode
kaedah, yang boleh mengembalikan fungsi panggilan pengekodan untukhex
anda boleh merujuk kepada platformunwrapWETH9
kaedah digunakan di sini sebagai contoh:
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)
}
Apabila memanggilexchange.IO("encode",...)
fungsi, jika parameter kedua (jenis rentetan) bermula dengan0x
, ia bermaksud panggilan kaedah pada kod (encode
) kontrak pintar.0x
, ia digunakan untuk mengkod perintah jenis yang ditentukan.abi.encode
dalamsolidity
. merujuk kepada contoh berikut.
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
*/
}
Sokong pengekodan berurutan tuples atau jenis yang mengandungi 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)
}
Perintah jenis ini terdiri daripada:tuple
danbytes
, jadi dua parameter perlu dihantar dalam apabila memanggilexchange.IO
kepadaencode
:
tuple
: {
a: 30,
b: 20,
c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
}
Parameter yang dihantar juga harus konsisten dengan struktur dan jenistuple
, seperti yang ditakrifkan dalamtypes
Parameter:tuple(a uint256, b uint8, c address)
.
bytes
: "0011"
Sokongan untuk pengekodan berurutan array atau jenis yang mengandungi array:
function main() {
var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"] // ETH address, USDT address
var ret = exchange.IO("encode", "address[]", path)
Log("encode: ", ret)
}
Sebagai contoh, apabila memanggil kaedah DEXUniswap V3
, anda perlu lulus dalam parameter, seperti laluan pertukaran, jadi anda perlu menggunakanencodePackaged
operasi:
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)
}
Pemprosesan data bukan sahaja menyokong pengekodan (encode
), tetapi juga mendekod (decode
) Gunakanexchange.IO("decode", types, rawData)
fungsi untuk melaksanakandecode
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)
}
Contoh ini melakukanencodePacked
operasi pertama semasapath
pemprosesan parameter, keranaexactOutput
panggilan kaedah yang perlu dikodkan kemudian memerlukanpath
sebagai parameter. Kemudian,encode
kaedahexactOutput
kontrak laluan hanya mempunyai satu parameter, dan jenis parameter adalahtuple
. KaedahexactOutput
nama dikodkan sebagai0x09b81346
, yang telah didekodkan hasildecodeRaw
olehexchange.IO ("decode",...)
kaedah, dan ia adalah konsisten dengan pembolehubahdataTuple
.
Ia menyokong menukar kunci peribadi untuk mengendalikan pelbagai alamat dompet, contohnya:
function main() {
exchange.IO("key", "Private Key") // "Private Key" represents the private key string, which needs to be filled in specifically
}
Parameter pertamaexchange.IO
Fungsi adalah:"api"
menunjukkan bahawa panggilan ini adalah panggilan lanjutan.exchange.IO
fungsi adalah alamat kontrak pintar yang akan dipanggil.
Jika kaedah dipanggil mempunyaipayable
Atribut, anda perlu menambah nilai ETH pemindahan selepas nama kaedah (parameter keempatexchange.IO
fungsi), yang boleh berjenis nombor atau lulus nilai dalam bentuk rentetan, contohnyamulticall
kaedahUniswap V3
. Kandungan berikut adalah contoh beberapa panggilan kaedah kontrak pintar:
Peraturandecimals
kaedah adalahconstant
kaedahERC20
yang tidak menghasilkangas
penggunaan, dan ia boleh menyoal data ketepatantoken
.decimals
Nilai pulangan: data ketepatantoken
.
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
}
Peraturanallowance
kaedah adalahconstant
kaedahERC20
yang tidak menghasilkangas
Penggunaan, dan ia boleh menyoal jumlah yang dibenarkantoken
untuk alamat kontrak tertentu.allowance
kaedah perlu lulus dalam 2 parameter, yang pertama adalah alamat dompet, dan yang kedua adalah alamat yang dibenarkan.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"))
}
```spender```: The authorized contract address is replaced by the string "spender" in the example. In actual use, you need to fill in the address specifically, for example, the address can be ```Uniswap V3 router v1```.
- approve
The ```approve``` method is a non-```constant``` method of ```ERC20``` that generates ```gas``` consumption, which is used to authorize a ```token``` operation amount to a certain contract address. The ```approve``` method need to pass in 2 parameters, the first one is the address to be authorized and the second one is the authorized amount. Return value: ```txid```.
```js
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"))
}
```0xde0b6b3a7640000```: The number of authorizations, represented here using a hexadecimal string, corresponds to a decimal value of ```1e18```, divided by the ```token``` precision unit in the example (i.e., 1e18), yielding 1 ```token``` authorized.
The third parameter of the ```exchange.IO``` function is passed the method name ```approve```, which can also be written in the form of ```methodId```, for example: "0x571ac8b0". It is also possible to write the full standard method name, such as ''approve(address,uint256)''.
- multicall
The ```multicall``` method is a non-constant method of ```Uniswap V3```, which will generate ```gas``` consumption and be used to exchange tokens in multiple ways. The ```multicall``` method may have multiple methods of passing in parameters. You can query the ABI containing the method for details. You need to register the ABI before calling the method. Return value: ```txid```.
For specific examples of ```multicall``` method calls, please refer to the public ["Uniswap V3 Trading Class Library" template](https://www.fmz.com/strategy/397260) of our platform.
Pseudocode is used here to describe some details:
```js
exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)
```value```: The amount of ETH transferred, set it to 0 if the ```tokenIn``` token for the exchange operation is not ETH.
```deadline```: It can be set to ```(new Date().getTime() / 1000) + 3600```, which means it is valid for one hour.
```data```: The data of the packing operation to be performed.
It is also possible to specify the ```gasLimit/gasPrice/nonce``` setting for method calls, we use pseudocode to describe again:
```js
exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})
Anda boleh menetapkan parameter{gasPrice: 11, gasLimit: 111, nonce: 111}
mengikut keperluan khusus anda, parameter ditetapkan kepada parameter terakhirexchange.IO
Anda boleh mengabaikannonce
dan menggunakan sistem lalai, atau tidak menetapkangasLimit/gasPrice/nonce
dan gunakan semua nilai lalai sistem.
Perlu diperhatikan bahawa dalam contoh, atributstateMutability
dalammulticall(uint256,bytes[])
kaedah adalahpayable
, danvalue
parameter perlu dihantar dalam.stateMutability":"payable"
boleh dilihat dariABI
.exchange.IO
fungsi akan menentukan parameter yang diperlukan mengikutstateMutability
atribut dalamABI
yang telah didaftarkan.stateMutability
atribut adalahnonpayable
, parametervalue
tidak perlu diserahkan.
function main() {
Log(exchange.IO("address")) // Print the wallet address of the private key configured on the exchange object.
}
function main() {
var chainRpc = "https://bsc-dataseed.binance.org"
e.IO("base", chainRpc) // Switch to BSC chain
}
Apabila memanggil fungsi penunjuk, anda perlu menambahTA.
atautalib.
sebagai awalan
Contoh panggilan fungsi penunjuk dalamtalib
perpustakaan danTA
perpustakaan:
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));
}
Data dalam parameter berikut adalah semua data yang diperoleh oleh fungsiexchange.GetRecords(Period)
.
Berhati-hati dengan panjangrecords
, apabila panjang tidak memenuhi keperluan pengiraan parameter fungsi penunjuk, nilai yang tidak sah akan dikembalikan.
PeraturanTA
perpustakaan penunjuk platform FMZ Quant Trading telah mengoptimumkan algoritma penunjuk yang biasa digunakan untuk menyokong panggilan strategi yang ditulis dalamJavaScript
, Python
dancpp
Kod perpustakaan TA sumber terbuka.
```js
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]);
}
```js
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]);
}
```js
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);
}
```js
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);
}
```js
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);
}
```js
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);
}
```js
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);
}
}
```js
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);
}
}
### CMF - Chaikin Money Flow
```TA.CMF(data, period)```; CMF(data, period) is Chaikin Money Flow indicator, with the default period parameter of 20, returns a one-dimensional array.
### Highest - Period Highest Price
```TA.Highest(data, period, attribute)```, returns the maximum value in the most recent period (excluding the current Bar), such as ```TA.Highest(records, 30, 'High')```. If the ```period``` is 0, it means all Bars. If the ```attribute``` is not specified, the data is regarded as an ordinary array, and returns a price (value type).
### Lowest - Period Lowest Price
```TA.Lowest(data, period, attribute)```, returns the minimum value in the most recent period (excluding the current Bar), such as ```TA.Highest(records, 30, 'Low')```. If the ```period``` is 0, it means all bars. If the attribute is not specified, the data is regarded as an ordinary array, and a price (value type) is returned.
The use of ```TA.Highest(...)``` and ```TA.Lowest(...)``` in the ```C++``` strategy should be noted that ```Highest``` and ```Lowest``` functions only have 2 parameters respectively, and the first parameter is not the return value of ```auto r = exchange.GetRecords()```function, so you need to call the method of ```r``` to pass specific attribute data, for example: pass ```r.Close()``` close price data. The call method of ```Close```, ```High```, ```Low```, ```Open```, ```Volume``` is just like ```r.Close()```.
```C++``` examples:
```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
perpustakaanhttp://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/
var y = 2.2
var sum = Decimal.add(x, y)
Log(sum.equals(new Decimal(x).plus(y)))