FMZ戦略の初期設計では,非同期同時操作が必要な場合,exchange.Go()
この機能は,FMZエンカプスルされたインターフェースの同時実行を達成するためにのみ使用することができ,一部のカスタム操作 (関数) を同時実行することは不可能です.このデザインは戦略プログラムの効率を大幅に向上させるが,ネイティブプログラミング言語で同時設計の経験を持つ学生はしばしば非常に不快を感じます.
FMZを導入的な量的な取引のために使用する新しい学生でさえ,exchange.Go()
機能exchange.Go()
この記事では,FMZプラットフォームに新たに追加された並行スレッド機能の利用について調べます.__Thread()
戦略プログラムの非同期設計などです.
戦略のメインスレッドが,私たちが書いたカスタム関数を実行するサブスレッドと同時実行されることを望む場合は,次のコードに似たデザインを使用できます. 戦略コードでは,カスタム関数を定義します.GetTickerAsync()
この関数は無限ループを実行し,継続的に FMZ API インターフェースを呼び出しますGetTicker()
市場データを取得するために
その場合は,この文を使用します__threadSetData(0, "ticker", t)
データをメインスレッドに書き込みます. データ名はticker
データ値はt
, が返される値である.GetTicker()
.
__threadSetData(0, "ticker", t)
プログラムにコードを書くことができます. プログラムにコードを書いたときに,main()
機能.main()
この関数は,
__Thread(GetTickerAsync, 0) // GetTickerAsync is a custom function that needs to be executed concurrently, and 0 is the parameter that is passed to the GetTickerAsync function.
実行を開始する同時スレッドを作成するGetTickerAsync()
機能.次に,main()
この関数は,自分の実行を開始します.while
更新されたデータを受信するループです.GetTickerAsync()
機能し,それをプリントします:
var t = __threadGetData(0, "ticker")
Log(t)
完全なコード例:
function GetTickerAsync(index) {
while (true) {
var t = exchanges[index].GetTicker()
__threadSetData(0, "ticker", t)
Sleep(500)
}
}
function main() {
__Thread(GetTickerAsync, 0)
while(true) {
var t = __threadGetData(0, "ticker")
Log(t)
Sleep(1000)
}
}
ライブ取引テスト:
これは最もシンプルなアプリケーションデザインの"つです. では,他の要件デザインを見てみましょう.
10つのスレッドを同時に作成する関数を設計できます. それぞれのスレッドは注文の配置関数を実行します.main()
設計することができます.while
戦略の相互作用コマンドを検出するループです.placeMultipleOrders
,我々は同時注文配置関数と呼ぶtestPlaceMultipleOrders()
.
if (cmd == "placeMultipleOrders") {
// ...
}
戦略編集ページに 戦略インタラクションデザインを追加する コマンド: placeMultipleOrders を追加する ボタン
完全なコード例:
function placeOrder(exIndex, type, price, amount) {
var id = null
if (type == "Buy") {
id = exchanges[exIndex].Buy(price, amount)
} else if (type == "Sell") {
id = exchanges[exIndex].Sell(price, amount)
} else {
throw "type error! type:" + type
}
}
function testPlaceMultipleOrders(index, beginPrice, endPrice, step, type, amount) {
Log("beginPrice:", beginPrice, ", endPrice:", endPrice, ", step:", step, ", type:", type, ", amount:", amount)
var tids = []
for (var p = beginPrice; p <= endPrice; p += step) {
var tid = __Thread(placeOrder, index, type, p, amount)
tids.push(tid)
Sleep(10)
}
Sleep(1000)
for (var i = 0; i < tids.length; i++) {
__threadTerminate(tids[i])
}
}
function main() {
while(true) {
LogStatus(_D())
var cmd = GetCommand()
if (cmd) {
if (cmd == "placeMultipleOrders") {
var t = _C(exchange.GetTicker)
var beginPrice = t.Last * 0.8
var endPrice = t.Last * 0.9
var step = t.Last * 0.01
testPlaceMultipleOrders(0, beginPrice, endPrice, step, "Buy", 0.01)
var orders = exchange.GetOrders()
for (var i = 0; i < orders.length; i++) {
Log(orders[i])
}
}
}
Sleep(1000)
}
}
placeMultipleOrdersのボタンをクリックすると,次のメッセージが表示されます. placeMultipleOrdersコマンドが成功して送信されました.ライブ取引からの応答をお待ちください.
この要求は FMZ ユーザによって提起され,Webソケットネットワークにデータを送信する方法main()
主要な糸で機能する.
前の例の並行スレッドを作るには非常にシンプルで,同じです.唯一の違いは,__threadPeekMessage()
そして__threadPostMessage()
スレッド間の通信のための機能です.例として,Binance 取引所の WebSocket API 呼び出しを取ると,WebSocket 接続の閉じる操作も処理する必要があります.次の例では,同時スレッドを停止するように通知する方法を示します.
完全なコード例:
var tid = null
function createWS() {
// wss://stream.binance.com:9443/ws/<streamName> , <symbol>@ticker
var stream = "wss://stream.binance.com:9443/ws/btcusdt@ticker"
var ws = Dial(stream)
Log("Create a WS connection:", stream)
while (true) {
var data = ws.read()
if (data) {
__threadPostMessage(0, data)
}
Log("receiving data pushed by the WS link, data:", data)
// __threadPeekMessage timeout parameter set to -1, no blocking
var msg = __threadPeekMessage(-1)
if (msg) {
if (msg == "stop") {
Log("Concurrent Thread Id:", __threadId(), "Received stop command")
break
}
}
}
Log("Concurrent threads finish execution, close ws connection")
ws.close()
}
function main() {
tid = __Thread(createWS)
Log("Create concurrent threads, thread Id:", tid)
while(true) {
// __threadPeekMessage's timeout parameter is set to 0, blocking for data
var data = __threadPeekMessage(0)
Log("Received from concurrent thread", ", Id:", tid, ", the data sent, data:", data, "#FF0000")
var tbl = {
type : "table",
title : "<symbol>@ticker channel push message",
cols : ["Event Type", "Event Time", "Trading Pairs", "24 Hour Price Change", "24 Hour Price Change %", "Average Price", "Last Traded Price", "Volume in 24 Hours", "Turnover in 24 Hours"],
rows : []
}
try {
data = JSON.parse(data)
tbl.rows.push([data.e, _D(data.E), data.s, data.p, data.P, data.w, data.c, data.v, data.q])
} catch (e) {
Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
}
LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`")
}
}
function onexit() {
Log("Finalize function, send a stop command to the concurrent thread with ID ", tid,"")
__threadPostMessage(tid, "stop")
Log("Wait for the concurrent thread with ID ", tid, " to stop")
__threadJoin(tid)
Log("Finalize function execution completed")
}
リアルタイムの取引のテストではmain()
この機能は,同時スレッドで作成された WebSocket 接続から市場データを継続的に受信します.
ライブ・トレード・戦略を停止すると,ファイナライズ機能が動作します.