onexit()
onexit()由用户实现,在策略退出时处理扫尾工作,可以不定义。最长执行 5 分钟,超时会被强制结束。各语言在哪些情况下调用onexit(),见 策略结构。
示例
-
测试
onexit()函数:javascriptfunction main(){ Log("Starting, will stop after 5 seconds and execute cleanup function!") Sleep(1000 * 5) } // 扫尾函数实现 function onexit(){ var beginTime = new Date().getTime() while(true){ var nowTime = new Date().getTime() Log("Program stop countdown..cleanup started, elapsed time:", (nowTime - beginTime) / 1000, "seconds!") Sleep(1000) } }pythonimport time def main(): Log("Starting, will stop after 5 seconds and execute cleanup function!") Sleep(1000 * 5) def onexit(): beginTime = time.time() * 1000 while True: ts = time.time() * 1000 Log("Program stop countdown..cleanup started, elapsed time:", (ts - beginTime) / 1000, "seconds!") Sleep(1000)rustfn main() { Log!("Starting, will stop after 5 seconds and execute cleanup function!"); Sleep(1000 * 5); } // 扫尾函数实现 fn onexit() { let beginTime = Unix() * 1000; loop { let nowTime = Unix() * 1000; Log!("Program stop countdown..cleanup started, elapsed time:", (nowTime - beginTime) / 1000, "seconds!"); Sleep(1000); } } -
回测系统中,策略通常写成不停轮询的死循环,回测数据结束时
main()并没有正常返回,JavaScript、Python策略因此不会执行onexit()。可以在回测中(IsVirtual()为真)捕获回测结束时抛出的异常(EOF),让main()返回,从而执行onexit()。Rust策略在回测结束时 API 调用返回Err,退出循环即可。javascriptfunction main() { if (exchange.GetName().startsWith("Futures_")) { Log("Exchange is futures") exchange.SetContractType("swap") } else { Log("Exchange is spot") } if (IsVirtual()) { try { onTick() } catch (e) { Log("error:", e) } } else { onTick() } } function onTick() { while (true) { var ticker = exchange.GetTicker() LogStatus(_D(), ticker ? ticker.Last : "--") Sleep(500) } } function onexit() { Log("Executing cleanup function") }pythondef main(): if exchange.GetName().startswith("Futures_"): Log("Exchange is futures") else: Log("Exchange is spot") if IsVirtual(): try: onTick() except Exception as e: Log(e) else: onTick() def onTick(): while True: ticker = exchange.GetTicker() LogStatus(_D(), ticker["Last"] if ticker else "--") Sleep(500) def onexit(): Log("Executing cleanup function")rustfn onTick() { loop { match exchange.GetTicker(None) { Ok(ticker) => LogStatus!(_D(None), ticker.Last), Err(e) => { // 回测结束时API调用返回Err,退出循环使main返回,从而触发onexit()扫尾函数 Log!("error:", e); break; } } Sleep(500); } } fn main() { if exchange.GetName().starts_with("Futures_") { Log!("Exchange is futures"); let _ = exchange.SetContractType("swap"); } else { Log!("Exchange is spot"); } onTick(); } fn onexit() { Log!("Executing cleanup function"); }