Type/to search
Built-in Functions
Global
Log
Market
Trade
Account
Futures
Exchange
IO
Network
Storage
Threads
exchange.Go
EventLoop
ctx.subscribe
ctx.poll
ctx.order
ctx.cancel
ctx.orderAsync
ctx.cancelAsync
Subscription
threading
Thread
ThreadLock
ThreadEvent
ThreadCondition
ThreadDict
Server
TA
Talib
OS
Structures
Built-in Variables and Constants
Conventions
Exchanges

Multi-threaded asynchronous support function that can convert the operations of all supported functions into asynchronous concurrent execution.

exchange.Go(method)
exchange.Go(method, ...args)

Examples

  • exchange.Go() function usage example. When checking for undefined, you must use typeof(xx) === "undefined", because null == undefined holds true in JavaScript.

    javascript
    function main(){ // The following four operations execute concurrently in asynchronous multi-threaded mode; they take no time and return immediately var a = exchange.Go("GetTicker") var b = exchange.Go("GetDepth") var c = exchange.Go("Buy", 1000, 0.1) var d = exchange.Go("GetRecords", PERIOD_H1) // Call the wait method to wait for the result of the asynchronous ticker retrieval var ticker = a.wait() // Returns the depth data; it may also return null if the retrieval fails var depth = b.wait() // Returns the order ID with a 1-second timeout; returns undefined on timeout. If the previous wait timed out, this object can continue calling wait var orderId = c.wait(1000) if(typeof(orderId) == "undefined") { // Timed out, retrieve again orderId = c.wait() } var records = d.wait() }
    python
    def main(): a = exchange.Go("GetTicker") b = exchange.Go("GetDepth") c = exchange.Go("Buy", 1000, 0.1) d = exchange.Go("GetRecords", PERIOD_H1) ticker, ok = a.wait() depth, ok = b.wait() orderId, ok = c.wait(1000) if ok == False: orderId, ok = c.wait() records, ok = d.wait()
    rust
    fn main() { // In Rust, exchange.Go uses a typed form: use the Go:: method token to specify the concurrent function; pass () for no arguments and a tuple for arguments // The following four operations execute concurrently in asynchronous multi-threaded mode; they take no time and return immediately let a = exchange.Go(Go::GetTicker, ()); let b = exchange.Go(Go::GetDepth, ()); // There is no Buy token in Rust; it is equivalent to CreateOrder, where the first argument "" indicates the current trading pair let c = exchange.Go(Go::CreateOrder, ("", "buy", 1000, 0.1)); let d = exchange.Go(Go::GetRecords, ("", PERIOD_H1)); // arguments: trading pair ("" = current pair), K-line period // Call the wait method to wait for the result of the asynchronous ticker retrieval; wait(0) blocks until the concurrent thread finishes running (corresponding to the parameterless wait() in JS) let ticker = a.wait(0); // Returns the depth data; it may also return Err if the retrieval fails let depth = b.wait(0); // Returns the order ID with a 1-second timeout; returns Err on timeout. If the previous wait timed out, this object can continue calling wait // Note: Err may also mean the order placement itself failed (a timeout error reads routine N not finished); if the order failed, the result has been taken and calling wait again returns Err (routine N already finished) let mut orderId = c.wait(1000); if orderId.is_err() { // Timed out, retrieve again orderId = c.wait(0); } let records = d.wait(0); }
  • Calling the wait() method on a released concurrent object will raise an error.

    javascript
    function main() { var d = exchange.Go("GetRecords", PERIOD_H1) // Wait for the K-line data results to return var records = d.wait() // Calling wait again here on an asynchronous operation that has already been waited on and finished throws an exception: routine N already finished var ret = d.wait() }
    python
    def main(): d = exchange.Go("GetRecords", PERIOD_H1) records, ok = d.wait() ret, ok = d.wait()
    rust
    fn main() { // In Rust, exchange.Go uses a typed syntax: specify the concurrent function via the Go:: method token let d = exchange.Go(Go::GetRecords, ("", PERIOD_H1)); // arguments: trading pair ("" = current pair), K-line period // Wait for the K-line data results to return; wait(0) blocks until execution completes (equivalent to JS's parameterless wait()) let records = d.wait(0); // Calling wait again here on an asynchronous operation that has already been waited on and finished returns Err (routine N already finished) let ret = d.wait(0); }
  • Concurrently retrieve market data from multiple exchanges.

    javascript
    function main() { while(true) { var beginTS = new Date().getTime() var arrRoutine = [] var arrTicker = [] var arrName = [] for(var i = 0; i < exchanges.length; i++) { arrRoutine.push(exchanges[i].Go("GetTicker")) arrName.push(exchanges[i].GetName()) } for(var i = 0; i < arrRoutine.length; i++) { arrTicker.push(arrRoutine[i].wait()) } var endTS = new Date().getTime() var tbl = { type: "table", title: "Market Data", cols: ["Index", "Name", "Last Price"], rows: [] } for(var i = 0; i < arrTicker.length; i++) { tbl.rows.push([i, arrName[i], arrTicker[i].Last]) } LogStatus(_D(), "Total time for concurrent ticker retrieval:", endTS - beginTS, "ms", "\n", "`" + JSON.stringify(tbl) + "`") Sleep(500) } }
    python
    import time import json def main(): while True: beginTS = time.time() arrRoutine = [] arrTicker = [] arrName = [] for i in range(len(exchanges)): arrRoutine.append(exchanges[i].Go("GetTicker")) arrName.append(exchanges[i].GetName()) for i in range(len(exchanges)): ticker, ok = arrRoutine[i].wait() arrTicker.append(ticker) endTS = time.time() tbl = { "type": "table", "title": "Market Data", "cols": ["Index", "Name", "Last Price"], "rows": [] } for i in range(len(arrTicker)): tbl["rows"].append([i, arrName[i], arrTicker[i]["Last"]]) LogStatus(_D(), "Total time for concurrent ticker retrieval:", endTS - beginTS, "seconds", "\n", "`" + json.dumps(tbl) + "`") Sleep(500)
    rust
    fn main() { loop { let beginTS = UnixNano() / 1000000; let mut arrRoutine = Vec::new(); let mut arrTicker = Vec::new(); let mut arrName = Vec::new(); for e in exchanges.iter() { // In Rust, exchange.Go is a typed form; the token is Go::GetTicker arrRoutine.push(e.Go(Go::GetTicker, ())); arrName.push(e.GetName()); } // On failure, record None as a placeholder to stay index-aligned with arrName for r in arrRoutine.iter() { arrTicker.push(r.wait(0).ok()); } let endTS = UnixNano() / 1000000; // Rust has no built-in JSON serialization; use format! to assemble the table's JSON text let mut rows = String::new(); for i in 0..arrTicker.len() { if let Some(ticker) = &arrTicker[i] { if !rows.is_empty() { rows.push(','); } rows += &format!(r#"[{}, "{}", {}]"#, i, arrName[i], ticker.Last); } } let tbl = format!(r#"{{"type": "table", "title": "Market Data", "cols": ["Index", "Name", "Last Price"], "rows": [{}]}}"#, rows); LogStatus!(_D(None), "Total time for concurrent ticker retrieval:", endTS - beginTS, "ms", "\n", format!("`{}`", tbl)); Sleep(500); } }
  • Concurrently call the exchange.IO("api", ...) function.

    javascript
    function main() { /* Test the OKX futures order placement endpoint POST /api/v5/trade/order */ var beginTS = new Date().getTime() var param = {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"} var ret1 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", JSON.stringify(param)) var ret2 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", JSON.stringify(param)) var ret3 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", JSON.stringify(param)) var id1 = ret1.wait() var id2 = ret2.wait() var id3 = ret3.wait() var endTS = new Date().getTime() Log("id1:", id1) Log("id2:", id2) Log("id3:", id3) Log("Concurrent order time:", endTS - beginTS, "ms") }
    python
    import time import json def main(): beginTS = time.time() param = {"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"} ret1 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", json.dumps(param)) ret2 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", json.dumps(param)) ret3 = exchange.Go("IO", "api", "POST", "/api/v5/trade/order", "", json.dumps(param)) id1, ok1 = ret1.wait() id2, ok2 = ret2.wait() id3, ok3 = ret3.wait() endTS = time.time() Log("id1:", id1) Log("id2:", id2) Log("id3:", id3) Log("Concurrent order time:", endTS - beginTS, "seconds")
    rust
    fn main() { /* Test the OKX futures order placement endpoint POST /api/v5/trade/order */ let beginTS = UnixNano() / 1000000; // Rust does not support JSON serialization, so construct the parameters directly using a raw string let param = r#"{"instId":"BTC-USDT-SWAP","tdMode":"cross","side":"buy","ordType":"limit","px":"16000","sz":"1","posSide":"long"}"#; // In Rust, exchange.Go uses a typed form: the token is Go::IO, and the parameters are passed as a tuple let ret1 = exchange.Go(Go::IO, ("api", "POST", "/api/v5/trade/order", "", param)); let ret2 = exchange.Go(Go::IO, ("api", "POST", "/api/v5/trade/order", "", param)); let ret3 = exchange.Go(Go::IO, ("api", "POST", "/api/v5/trade/order", "", param)); let id1 = ret1.wait(0); let id2 = ret2.wait(0); let id3 = ret3.wait(0); let endTS = UnixNano() / 1000000; Log!("id1:", id1); Log!("id2:", id2); Log!("id3:", id3); Log!("Concurrent order time:", endTS - beginTS, "ms"); }
  • Testing the automatic release mechanism

    javascript
    function main() { var counter = 0 var arr = [] // Variables used to test persistently referencing concurrent objects var symbols = ["BTC_USDT", "ETH_USDT", "SOL_USDT", "LTC_USDT", "EOS_USDT"] while (true) { var arrRoutine = [] for (var symbol of symbols) { var r = exchange.Go("GetTicker", symbol) arrRoutine.push(r) // Record the concurrent object, used to call the r.wait() function to get the result; cleared every loop iteration // arr.push(r) // If this line is used, the runtime will persistently reference the concurrent objects, preventing them from being automatically released; once 2000 tasks are waiting to have their results taken, calling exchange.Go() again reports: too many routine wait, max is 2000 counter++ } // Iterate over arrRoutine and call r.wait() to get the results LogStatus(_D(), "routine number:", counter) Sleep(50) } }
    rust
    fn main() { let mut counter = 0; let mut arr: Vec<TypedRoutine<Go::GetTicker>> = Vec::new(); // Variables used to test persistently referencing concurrent objects let symbols = ["BTC_USDT", "ETH_USDT", "SOL_USDT", "LTC_USDT", "EOS_USDT"]; loop { let mut arrRoutine = Vec::new(); for symbol in symbols { // In Rust, exchange.Go uses a typed form, with the token being Go::GetTicker let r = exchange.Go(Go::GetTicker, (symbol,)); arrRoutine.push(r); // Record the concurrent object, used to call the r.wait(0) function to get the result; cleared every loop iteration // arr.push(r); // If this line is used, the runtime will persistently reference the concurrent objects, preventing them from being automatically released; once 2000 tasks are waiting to have their results taken, calling exchange.Go() again reports: too many routine wait, max is 2000 counter += 1; } // Iterate over arrRoutine and call r.wait(0) to get the results LogStatus!(_D(None), "routine number:", counter); Sleep(50); } }

Returns

TypeDescription

object

Returns a concurrent object at once; its wait() method returns the result of the concurrent call, see exchange.Go-return.

Arguments

NameTypeRequiredDescription

method

string

Yes

Name of the function to be executed concurrently. Please note that this parameter is a function name string, not a function reference.

arg

string / number / bool / object / array / function / any

No

The parameters of the concurrent execution function. The arg parameter can appear multiple times. The type and number of the arg parameters depend on the parameter definition of the concurrent execution function.

See Also

Remarks

This function only creates multi-threaded execution tasks when running in live trading. Backtesting does not support multi-threaded concurrent execution of tasks (it can be used in backtesting, but is still executed sequentially).

The timeout of the concurrent object's wait() method and its return values per language on completion, timeout and repeated calls are described in exchange.Go-return. In Python wait() returns two values, (result, ok).

Although the underlying system has an automatic reclamation mechanism, if the related variables are continuously referenced, the results of the concurrent tasks will not be released. Once 2000 concurrent tasks are waiting to have their results taken, submitting another one with exchange.Go() fails immediately with "too many routine wait, max is 2000" and the task is not executed.

Supported functions: GetTicker, GetDepth, GetTrades, GetRecords, GetAccount, GetOrders, GetOrder, CancelOrder, Buy, Sell, GetPositions, IO, etc. When these functions are called concurrently, they are all executed based on the current exchange object.