JavaScript
平台支持用JavaScript编写策略。运行时基于 QuickJS 引擎,支持async/await、class、BigInt等现代语法;实盘时策略在托管者上运行,回测时在浏览器端的回测系统中运行。在代码中加入// @ts-check即可改用 TypeScript 编写,见 TypeScript。
策略结构与参数
策略入口为function main(),可选的init()、onexit()、onerror(msg)由托管者自动调用,见 策略结构。界面参数是同名的全局变量,可以直接读取,也可以在代码中修改,见 策略参数。
错误与返回值
API 函数调用失败(交易所返回错误、网络问题等)时返回null,并在日志中输出错误信息。使用返回值之前先判断,或者用 _C 重试:
javascript
function main() {
var ticker = exchange.GetTicker()
// 调用失败时返回 null
if (ticker) {
Log(ticker)
}
// 失败时自动重试,直到返回有效数据
var account = _C(exchange.GetAccount)
Log(account)
}
程序异常(例如读取undefined的属性)和接口业务报错的日志中会显示出错位置在策略代码中的行号,便于调试和排查。
字符串与ArrayBuffer
JavaScript 的字符串是 UTF-16 编码。平台 API 返回的文本如果不是合法的 UTF-8 字节序列,为了不丢失数据,会返回ArrayBuffer(原始字节)。所有可以传入字符串的 API 参数也都接受ArrayBuffer。
javascript
function stringToHex(str) {
let hex = ''
for (let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i).toString(16)
hex += charCode.length === 1 ? '0' + charCode : charCode
}
return hex
}
function main() {
// “𠮷”的 Unicode 码点超出 16 位,在 JavaScript 字符串中占两个 UTF-16 码元
const inputString = "abc𠮷123"
// Encode 按 UTF-8 编码后输出 hex
const encodedHex = Encode("raw", "string", "hex", inputString)
Log(encodedHex) // 616263f0a0aeb7313233
// charCodeAt 取的是 UTF-16 码元,“𠮷”被写成 d842、dfb7,结果不是 UTF-8 编码
const manuallyEncodedHex = stringToHex(inputString)
Log(manuallyEncodedHex) // 616263d842dfb7313233
// 合法的 UTF-8 字节可以还原为字符串
const decodedString = Encode("raw", "hex", "string", encodedHex)
Log(decodedString) // abc𠮷123
// 不是合法的 UTF-8 字节,返回 ArrayBuffer
// (如果 inputString 改为 "abcG123",两种编码结果相同,这里得到的是字符串)
const outputD = Encode("raw", "hex", "string", manuallyEncodedHex)
Log(outputD instanceof ArrayBuffer) // true
// 查看 ArrayBuffer 中的原始字节
const bufferD = new Uint8Array(outputD)
let hexBufferD = ''
for (let i = 0; i < bufferD.length; i++) {
hexBufferD += bufferD[i].toString(16).padStart(2, '0')
}
Log(hexBufferD) // 616263d842dfb7313233
}
异步与多线程
setTimeout/clearTimeout:回调在主线程调用Sleep()等待期间执行;main()返回时还没到期的定时器会先执行完,再调用onexit()。fetch(url):返回Promise,结果为响应对象(ok、status、headers属性,text()、json()直接返回内容)。托管者中的fetch在调用时就同步完成请求,返回的是已经完成的Promise,所以用Promise.all组合多个fetch并不会并发请求。- 交易所 API(例如
exchange.GetTicker())是同步阻塞调用,包装进Promise或async函数也不会并发执行。 - 需要并发时使用
exchange.Go、HttpQuery_Go,或者用Thread创建线程,见JavaScript多线程。
javascript
async function main() {
let resp = await fetch("https://www.okx.com/api/v5/market/books?instId=BTC-USDT")
if (resp.ok) {
Log(resp.json())
} else {
Log("status:", resp.status)
}
}
库与依赖
JavaScript 策略可以直接使用内置的TA指标库和talib指标库,各语言可用的内置库见 内置库。其它第三方 JavaScript 库可以在运行时下载后用eval加载,示例见同一页。