địa chỉ IP sted là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()
trả về một đối tượng, khi cuộc gọi thành công. Nếu cuộc gọi thất bại, đối tượng được trả về vẫn là một đối tượng, được phân biệt với đối tượng được trả về thông thường bởi thuộc tínhValid
.
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);
}
}
Sự khác biệt giữamain()
chức năng trongC++
chiến lược viết vàmain()
chức năng trong tiêu chuẩn C11:
Giá trị trả về củaC++
chức năng nhập chương trìnhmain()
trong C11 làint
loại.C++
viết chiến lược trên nền tảng FMZ, chức năng khởi động của chiến lược cũng là chức năngmain()
Trên nền tảng FMZ, giá trị trả về củamain()
chức năng trongC++
chiến lược là củavoid
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));
}
Vì lý do ngôn ngữ JavaScript ( ngôn ngữ JavaScript hỗ trợ chuỗi tích hợpascii
vàutf-16
mã hóa chỉ, để không mất dữ liệu), khi nó gặp chuỗi mà không thể được mã hóa, nó sẽ trả vềArrayBuffer
tất cả các giao diện API mà có thể vượt qua các tham số chuỗi cũng hỗ trợ vượt qua cácArrayBuffer
type.
Nó thực sự hỗ trợ các chức năng đa-threaded củaJavaScript
chiến lược ngôn ngữ từ dưới cùng của hệ thống, bao gồm: thực hiện đồng thời các chức năng thực thi tùy chỉnh; hỗ trợ giao tiếp giữa các luồng đồng thời, hỗ trợ giao tiếp giữa các luồng đồng thời và luồng chính; lưu trữ, chia sẻ các biến trong môi trường luồng và các chức năng khác. Nó chỉ hỗ trợ sử dụng trong môi trường giao dịch trực tiếp cho đến nay, vui lòng tham khảo:https://www.fmz.com/bbs-topic/9974.
Các__Thread(function, arguments...)
function tạo ra một thread chạy đồng thời. Nó không hỗ trợ tham chiếu trực tiếp đến các biến khác ngoài hàm thực thi thread (chạy như một môi trường cô lập). Các tham chiếu đến các biến bên ngoài sẽ không được biên dịch. Các tham chiếu đến các hàm đóng khác cũng không được hỗ trợ. Tất cả các API của nền tảng có thể được gọi bên trong thread, nhưng các hàm được người dùng xác định khác không thể được gọi.function
có thể là một tham chiếu hàm hoặc một hàm ẩn danh.arguments
là tham số củafunction
chức năng (các thông số thực tế được truyền vào), vàarguments...
nghĩa là nhiều tham số có thể được truyền vào. Giá trị trả về: ID chủ đề.
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
}
Nó hỗ trợ phương pháp gọi của__Thread([function, arguments...], [function, arguments...], ...)
, nghĩa là, nhiều chức năng thực thi thread được thực hiện liên tục trong các thread được tạo.
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)
}
Chức năng thực thi đồng thời được chuyển sang__Thread
hàm sẽ được thực hiện theo thứ tự ngược. ví dụ trên sẽ sử dụng cácLog
chức năng để in1 ~ 5
Các biến được chia sẻ giữa các chức năng thực thi luồng khác nhau được hỗ trợ.this.d
biến trong ví dụ trên có thể được gán trongthreadTestFuncB
chức năng và được sử dụng trongthreadTestFuncA
Nó hỗ trợ chuyển trong chuỗi hàm, chẳng hạn như"function threadTestFuncC(c) {Log(c)}"
trong ví dụ trên, cho phép các luồng thực hiện các cuộc gọi hàm đến các hàm bên ngoài và thư viện
Để nhập thư viện bên ngoài, một ví dụ sử dụng cụ thể là như sau:
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")])))
}
Các__threadPeekMessage(threadId, timeout)
chức năng đọc dữ liệu từ kênh truyền thông thread, các thông sốthreadId
là ID được trả về bởi__Thread()
chức năng, thiết lập tham sốthreadId
nghĩa là để nhận dữ liệu được gửi bởi các luồng được đại diện bởi các luồngId. Khi được thiết lập thành 0, nó có nghĩa là để nhận dữ liệu được gửi bởi các luồng chính, đó là các chức năng chính hiện tại (threadId tham số được thiết lập thành 0, chỉ được hỗ trợ trong các chức năng thực thi luồng đồng thời).timeout
là một thiết lập thời gian, mà sẽ chặn và chờ theo số milliseconds được thiết lập bởi tham số này.timeout
được thiết lập thành-1
, nó có nghĩa là chặn và chờ cho đến khi dữ liệu trong kênh được nhận.__threadPeekMessage
hàm sẽ trả về một giá trị null ngay lập tức. giá trị trả về: dữ liệu nhận được.
Khi viết chương trình, bạn cần phải chú ý đến vấn đề bế tắc luồng. ví dụ sau đây là giao tiếp giữa các chức năng thực thitestFunc
của các dây đồng thời được tạo ra vàmain
chức năng của dây chủ và chức năng thực hiện dâytestFunc
sẽ bị xử tử trước.
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)
}
}
Các__threadPostMessage(threadId, data)
chức năng ghi dữ liệu vào kênh liên lạc thread, các tham sốthreadId
là ID được trả về bởi__Thread()
chức năng, thiết lập tham sốthreadId
có nghĩa là gửi dữ liệu đến chủ đề được đại diện bởi threadId, và khi được đặt thành 0, nó có nghĩa là gửi dữ liệu đến chủ đề chính, tức là chức năng chính hiện tại (threadId được đặt thành 0, chỉ được hỗ trợ trong các chức năng thực thi chủ đề đồng thời).data
có thể truyền các giá trị, chuỗi, giá trị Boolean, đối tượng, mảng và các loại dữ liệu khác.
Khi__threadPostMessage
function được gọi trong chức năng thực thi của một thread để gửi tín hiệu và dữ liệu, một sự kiện tin nhắn cũng sẽ được tạo ra.EventLoop()
chức năng để nhận thông báo tin nhắn.
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)
}
Các__threadJoin(threadId, timeout)
chức năng được sử dụng để chờ cho các chủ đề với ID chỉ định để thoát và lấy lại tài nguyên hệ thống.threadId
là ID được trả về bởi__Thread()
chức năng, và các thông sốtimeout
là thiết lập thời gian hết để chờ kết thúc của thread, trong milliseconds. Nếu không đặt thời gian hết, có nghĩa là chờ đến khi kết thúc thực thi thread. Giá trị trả về: Loại là một đối tượng, chỉ ra kết quả thực thi. Nếu thời gian hết, trả vềundefined
.
Cấu trúc giá trị lợi nhuận, ví dụ:
{
"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
}
Các__threadTerminate
function được sử dụng để kết thúc thread một cách ép buộc và giải phóng các tài nguyên phần cứng được sử dụng bởi thread được tạo ( __threadJoin không còn có thể được sử dụng để chờ đợi kết thúc).threadId
là ID được trả về bởi__Thread()
Function. Return value: Boolean value, chỉ ra kết quả thực hiện.
function testFunc() {
for(var i = 0 ; i < 10 ; i++) {
Log("i:", i)
Sleep(500)
}
}
function main() {
var testThread = __Thread(testFunc)
var retThreadTerminate = null
for (var i = 0 ; i < 10 ; i++) {
Log("main i:", i)
if (i == 5) {
retThreadTerminate = __threadTerminate(testThread)
}
Sleep(500)
}
Log("retThreadTerminate:", retThreadTerminate)
}
__threadGetData(threadId, key)
, chức năng được sử dụng để truy cập các biến được chia sẻ giữa các luồng. Dữ liệu là hợp lệ khi luồng chưa thực hiện__threadJoin
chức năng (đang chờ một exit thành công) và đã không thực hiện các__threadTerminate
chức năng (kết thúc các đường dây bằng vũ lực).threadId
là ID thread, và tham sốkey
là tên khóa của dữ liệu được lưu trữkey-value
trả về giá trị: trả về giá trị khóa tương ứng vớikey
trongkey-value
pair.
threadId
là 0 để chỉ sợi chính (tức là sợi màmain
bạn có thể sử dụng__threadId()
chức năng để có được ID của chủ đề hiện tại, đặt tham sốthreadId
Bạn cũng có thể đọc các biến trong môi trường thread của ID được chỉ định.
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(threadId, key, value)
, được sử dụng để lưu trữ các biến trong môi trường thread.threadId
là thread Id, tham sốkey
là tên khóa của dữ liệu được lưu trữkey-value
cặp, và các tham sốvalue
là giá trị khóa. Chức năng không có giá trị trả về.
threadId
là 0 để chỉ sợi chính (tức là sợi màmain
và bạn có thể sử dụng__threadId()
chức năng để lấy ID của chủ đề hiện tại.value
không xác định phương tiện để xóakey
. Nó hỗ trợ truy cập lẫn nhau vào các biến được chia sẻ giữa các luồng. Dữ liệu là hợp lệ khi luồng chưa thực hiện các__threadJoin
chức năng (đang chờ để thoát thành công) và đã không thực hiện các__threadTerminate
Các giá trị của tham sốvalue
phải là một biến có thể được nối tiếp.
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()
, được sử dụng để lấy Id của chuỗi hiện tại, mà không có tham số.threadId
của dòng hiện tại.
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())
}
TrongJavaScript
theo chiến lược ngôn ngữ, mã hex của tệp wasm có thể được tải, thực hiện và mã trong đó được thực thi.JavaScript
Mã, nó có một lợi thế tốc độ nhất định.
wasm.parseModule(data)
, mà phân tích một mô hình chuỗi hex.data
tham số là mã hóa wasm đã được chuyển đổi thành một chuỗi hex. Return value: Return a wasm model object, you can refer toVí dụ về chiến lược.
Ví dụ, mã hàm c ++ sau đây có thể được biên dịch thành mã wasm, và sau đó chuyển đổi thành một chuỗi hex, có thể được sử dụng nhưdata
tham số củawasm.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(module, opt)
, tạo ra một mẫu mẫu wasm.module
tham số là mô hình wasm, vàopt
tham số là thông tin cấu hình, được sử dụng để thiết lập không gian ngăn xếp được phân bổ cho chương trình mẫu wasm.
opt
Ví dụ thiết lập tham số:
{
stack_size: 65*1024*1024,
}
callFunction(funcName, param1, ...)
, đó là một phương thức của mô hình wasm, được sử dụng để thực hiện hàm trong mô hình wasm.funcName
tham số là tên của chức năng được thực hiện, vàparam1
tham số là tham số được truyền vào khi thực hiện chức năng (được chỉ định bởi tham sốfuncName
).
Nền tảng FMZ Quant Trading có thể truy cập chính thức để hỗ trợ cuộc gọi tương tác củaweb3
hợp đồng trên chuỗi, mà có thể truy cậpdefi
trao đổi dễ dàng.
Trên nền tảng FMZ Quant Trading, viết mã chiến lược để thực hiện phương thức gọi hợp đồng thông minh trên chuỗi Ethereum thông quaexchange.IO
đầu tiên, cấu hình nút truy cập trên nền tảng FMZ Quant Trading. Các nút truy cập có thể là các nút tự xây dựng hoặc sử dụng các dịch vụ của bên thứ ba, chẳng hạn nhưinfura
.
Trên trang củaWeb3
. Thiết lậpRpc Address
(địa chỉ dịch vụ của nút truy cập) vàPrivate Key
Nó hỗ trợ triển khai địa phương các khóa riêng, xemChăm sóc an toàn].
Gọi một hợp đồng là một tiêu chuẩnERC20
Các phương thức gọi khác ngoài hợp đồng tiêu chuẩn đòi hỏi phải đăng ký nội dung ABI:exchange.IO("abi", tokenAddress, abiContent)
Để có được nội dung ABI của một hợp đồng, bạn có thể sử dụng URL sau đây để có được nó, chỉ lấy trường kết quả.
https://api.etherscan.io/api?module=contract&action=getabi&address=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
Khi tham số thứ hai củaexchange.IO
chức năng là"eth"
, bạn có thể gọi các phương thức RPC có sẵn cho máy chủ nút trực tiếp, ví dụ:
Tìm kiếm số dư ETH trong ví
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()))
}
Chuyển 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)
}
truy vấn eth_estimateGas
function toAmount(s, decimals) {
// The toAmount function can convert the hex-encoded value to a decimal value
return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
// Encoding the call to the approve method
var data = exchange.IO("encode", "0x111111111117dC0aa78b770fA6A738034120C302", "approve", "0xe592427a0aece92de3edee1f18e0157c05861564", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
Log("data:", data)
var gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
Log("gasPrice:", toAmount(gasPrice, 0))
var obj = {
"from" : "0x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // walletAddress
"to" : "0x111111111117dC0aa78b770fA6A738034120C302",
"gasPrice" : gasPrice,
"value" : "0x0",
"data" : "0x" + data,
}
var gasLimit = exchange.IO("api", "eth", "eth_estimateGas", obj)
Log("gasLimit:", toAmount(gasLimit, 0))
Log("gas fee", toAmount(gasLimit, 0) * toAmount(gasPrice, 0) / 1e18)
}
Chức năngexchange.IO
bao gồm cácencode
phương pháp, mà có thể trả lại các chức năng gọi mã hóa đểhex
Bạn có thể tham khảo các nền tảng unwrapWETH9
phương pháp được sử dụng ở đây như một ví dụ:
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)
}
Khi gọi choexchange.IO("encode",...)
hàm, nếu tham số thứ hai (loại chuỗi) bắt đầu với0x
, nghĩa là gọi phương thức trên mã hóa (encode
) hợp đồng thông minh.0x
, nó được sử dụng để mã hóa thứ tự loại được chỉ định.abi.encode
trongsolidity
Hãy tham khảo ví dụ sau đây.
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
*/
}
Hỗ trợ mã hóa trình tự của các tuples hoặc các loại chứa 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)
}
Lệnh kiểu này bao gồm:tuple
vàbytes
, vì vậy hai tham số cần được truyền vào khi gọiexchange.IO
đếnencode
:
tuple
:{
a: 30,
b: 20,
c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
}
Các thông số được truyền phải phù hợp với cấu trúc và loạituple
, như được định nghĩa trongtypes
tham số:tuple(a uint256, b uint8, c address)
.
bytes
:"0011"
Hỗ trợ mã hóa thứ tự của mảng hoặc các loại chứa mảng:
function main() {
var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"] // ETH address, USDT address
var ret = exchange.IO("encode", "address[]", path)
Log("encode: ", ret)
}
Ví dụ, khi gọi phương pháp DEX củaUniswap V3
, bạn cần phải truyền vào các tham số, chẳng hạn như con đường trao đổi, vì vậy bạn cần phải sử dụngencodePackaged
hoạt động:
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)
}
Xử lý dữ liệu không chỉ hỗ trợ mã hóa (encode
), nhưng cũng giải mã (decode
) Sử dụngexchange.IO("decode", types, rawData)
chức năng để thực hiệndecode
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)
}
Ví dụ thực hiệnencodePacked
hoạt động đầu tiênpath
xử lý tham số, bởi vìexactOutput
gọi phương thức mà cần được mã hóa sau đó cầnpath
Sau đó, cácencode
phương phápexactOutput
hợp đồng định tuyến chỉ có một tham số, và loại tham số làtuple
Phương phápexactOutput
tên được mã hóa là0x09b81346
, được giải mã kết quảdecodeRaw
bởiexchange.IO ("decode",...)
phương pháp, và nó phù hợp với biếndataTuple
.
Nó hỗ trợ chuyển đổi khóa riêng để vận hành nhiều địa chỉ ví, ví dụ:
function main() {
exchange.IO("key", "Private Key") // "Private Key" represents the private key string, which needs to be filled in specifically
}
Các tham số đầu tiên củaexchange.IO
chức năng là:"api"
Các tham số thứ hai củaexchange.IO
function là địa chỉ của hợp đồng thông minh được gọi.
Nếu phương thức được gọi cópayable
thuộc tính, bạn cần phải thêm một chuyển ETH giá trị sau khi tên phương thức (các tham số thứ tư củaexchange.IO
chức năng), có thể là loại số hoặc truyền một giá trị dưới dạng chuỗi, ví dụ nhưmulticall
phương phápUniswap V3
Các nội dung sau đây là ví dụ về một số cuộc gọi phương thức hợp đồng thông minh:
số thập phân
Cácdecimals
phương pháp là mộtconstant
phương phápERC20
mà không tạo ragas
tiêu thụ, và nó có thể truy vấn dữ liệu chính xác của mộttoken
.decimals
Phản hồi giá trị: dữ liệu chính xác củatoken
.
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
}
trợ cấp
Cácallowance
phương pháp là mộtconstant
phương phápERC20
mà không tạo ragas
tiêu thụ, và nó có thể truy vấn số lượng được phép của một sốtoken
cho một địa chỉ hợp đồng nhất định.allowance
Phương pháp cần phải đi qua trong 2 tham số, một là địa chỉ ví, và một thứ hai là địa chỉ được ủy quyền.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
: Địa chỉ ví được thay thế bằng chuỗi spender
: Địa chỉ hợp đồng được ủy quyền được thay thế bằng chuỗi Uniswap V3 router v1
.
chấp thuận
Cácapprove
Phương pháp này không phải là...constant
phương phápERC20
tạo ragas
tiêu thụ, được sử dụng để cho phép mộttoken
giao dịch với một địa chỉ hợp đồng nhất định.approve
phương pháp cần phải vượt qua trong 2 tham số, một là địa chỉ được ủy quyền và thứ hai là số tiền được ủy quyền.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
: Địa chỉ của hợp đồng được ủy quyền, ví dụ được thay thế bằng chuỗi Uniswap V3 router v1
address.
0xde0b6b3a7640000
: Số lượng ủy quyền, được thể hiện ở đây bằng một chuỗi hexadecimal, tương ứng với một giá trị thập phân của1e18
, chia chotoken
đơn vị chính xác trong ví dụ (tức là 1e18), tạo ra 1token
authorized.
Các tham số thứ ba củaexchange.IO
hàm được truyền tên phương thứcapprove
, cũng có thể được viết dưới dạngmethodId
, ví dụ:
nhiều cuộc gọi
Cácmulticall
phương pháp là một phương pháp không liên tục củaUniswap V3
, sẽ tạo ragas
tiêu thụ và được sử dụng để trao đổi token theo nhiều cách.multicall
method có thể có nhiều phương thức truyền tham số. Bạn có thể truy vấn ABI chứa phương thức để biết chi tiết. Bạn cần đăng ký ABI trước khi gọi phương thức. Trả về giá trị:txid
.
Đối với các ví dụ cụ thể vềmulticall
phương pháp gọi, xin vui lòng tham khảo công chúng
Mã giả được sử dụng ở đây để mô tả một số chi tiết:
exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)
ContractV3SwapRouterV2
: địa chỉ router v2 của Uniswap V3.value
: Số tiền ETH được chuyển giao, đặt nó thành 0 nếutokenIn
Token cho giao dịch trao đổi không phải là ETH.deadline
: Nó có thể được thiết lập thành(new Date().getTime() / 1000) + 3600
, có nghĩa là nó có hiệu lực trong một giờ.data
: Dữ liệu về hoạt động đóng gói cần thực hiện.
Nó cũng có thể xác địnhgasLimit/gasPrice/nonce
cài đặt cho các cuộc gọi phương thức, chúng tôi sử dụng mã giả để mô tả một lần nữa:
exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})
Bạn có thể đặt tham số{gasPrice: 11, gasLimit: 111, nonce: 111}
theo nhu cầu cụ thể của bạn, các tham số được thiết lập cho các tham số cuối cùng củaexchange.IO
Bạn có thể bỏ quanonce
và sử dụng hệ thống mặc định, hoặc không đặtgasLimit/gasPrice/nonce
và sử dụng tất cả các giá trị mặc định của hệ thống.
Cần lưu ý rằng trong ví dụ, thuộc tính củastateMutability
trongmulticall(uint256,bytes[])
phương pháp làpayable
, vàvalue
Các thuộc tính củastateMutability":"payable"
có thể được xem từABI
.exchange.IO
chức năng sẽ xác định các thông số cần thiết theostateMutability
thuộc tính trongABI
đã được đăng ký.stateMutability
thuộc tính lànonpayable
, tham sốvalue
không cần phải được chuyển vào.
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
}
Khi gọi các hàm chỉ số, bạn cần thêmTA.
hoặctalib.
như tiền tố
Ví dụ về việc gọi các hàm chỉ số trongtalib
thư viện vàTA
thư viện:
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));
}
Dữ liệu trong các thông số sau đây là tất cả dữ liệu thu được bởi hàmexchange.GetRecords(Period)
.
Hãy chú ý đến chiều dài củarecords
, khi chiều dài không đáp ứng các yêu cầu tính toán tham số của chức năng chỉ số, một giá trị không hợp lệ sẽ được trả về.
CácTA
thư viện chỉ số của nền tảng FMZ Quant Trading đã tối ưu hóa các thuật toán chỉ số thường được sử dụng để hỗ trợ các chiến lược được viết trongJavaScript
, Python
vàcpp
mã thư viện TA mã nguồn mở.
TA.MACD(data, fast period, slow period, signal period)
, với các tham số thời gian mặc định của (12, 26, 9) trả về các mảng hai chiều, đó là[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]);
}
TA.KDJ(data, period 1, period 2, period 3)
, với các tham số thời gian mặc định của (9, 3, 3) trả về các mảng hai chiều, đó là(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]);
}
TA.RSI(data, period)
, với tham số thời gian mặc định là 14, trả về một mảng một chiều.
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);
}
TA.ATR(data, period)
; ATR ((data, period), với tham số thời gian mặc định là 14, trả về một mảng một chiều.
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);
}
TA.OBV(data)
trả về một mảng một chiều.
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);
}
TA.MA(data, period)
; MA ((data, period), với tham số thời gian mặc định là 9, trả về một mảng một chiều.
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);
}
TA.EMA(data, period)
là một chỉ số trung bình hàm số, với tham số thời gian mặc định là 9, trả về một mảng một chiều.
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);
}
}
TA.BOLL(data, period, multiplier)
; BOLL ((data, period, multiplier) là chỉ số Bollinger Band, với các tham số mặc định là (20, 2), và trả về một mảng hai chiều, cụ thể là[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 ((dữ liệu, khoảng hàm dưới, khoảng răng, khoảng môi trên) là chỉ số Alligator, với các tham số mặc định là (13,8,5), và trả về một mảng hai chiều, cụ thể là[Mandible, Teeth, Upper Lip]
.
TA.CMF(data, period)
; CMF ((dữ liệu, thời gian) là chỉ số dòng tiền Chaikin, với tham số thời gian mặc định là 20, trả về một mảng một chiều.
TA.Highest(data, period, attribute)
, trả về giá trị tối đa trong thời gian gần đây nhất (không bao gồm Bar hiện tại), chẳng hạn nhưTA.Highest(records, 30, 'High')
. Nếuperiod
là 0, nó có nghĩa là tất cả các Bars.attribute
không được chỉ định, dữ liệu được coi là một mảng thông thường và trả về giá (loại giá trị).
TA.Lowest(data, period, attribute)
, trả về giá trị tối thiểu trong thời gian gần đây nhất (không bao gồm Bar hiện tại), chẳng hạn nhưTA.Highest(records, 30, 'Low')
. Nếuperiod
là 0, nghĩa là tất cả các thanh. Nếu thuộc tính không được chỉ định, dữ liệu được coi là một mảng thông thường và trả về giá (loại giá trị).
Việc sử dụngTA.Highest(...)
vàTA.Lowest(...)
trongC++
chiến lược cần lưu ý rằngHighest
vàLowest
các hàm chỉ có 2 tham số tương ứng, và tham số đầu tiên không phải là giá trị trả về củaauto r = exchange.GetRecords()
chức năng, vì vậy bạn cần phải gọi phương thức củar
để truyền dữ liệu thuộc tính cụ thể, ví dụ: passr.Close()
Các dữ liệu giá đóng.Close
, High
, Low
, Open
, Volume
là giống nhưr.Close()
.
C++
ví dụ:
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
thư việnhttp://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)))