
원래 FMZ 전략 설계에서 비동기 동시 작업을 사용해야 하는 경우에는 다음을 사용할 수 있습니다.exchange.Go()이 함수는 FMZ 캡슐화 인터페이스의 동시성을 구현하는 데 사용되며, 일부 사용자 정의 작업(함수)은 동시에 실행할 수 없습니다. 이러한 설계는 정책 프로그램 실행의 효율성을 크게 개선하지만, 네이티브 프로그래밍 언어에서 동시적 설계에 대한 경험이 있는 학생들에게는 여전히 매우 생소합니다.
FMZ를 이용한 양적거래를 처음 접하는 신입생들 중 일부는 이를 이해하지 못한다.exchange.Go()함수의 사용, 사용exchange.Go()순차적으로 실행되는 코드에서 명령문은 여전히 하나씩 실행되는 것처럼 보입니다. 이 기사에서는 FMZ 플랫폼의 새로운 동시 스레딩 기능을 살펴보겠습니다.__Thread()일련의 기능과 전략 프로그램을 비동기적으로 디자인합니다.
전략 메인 스레드가 실행되는 동안, 우리가 작성한 사용자 정의 함수를 실행하기 위해 자식 스레드를 동시에 실행하려는 경우, 다음 코드와 유사한 디자인을 사용할 수 있습니다. 전략 코드에서 기능 사용자 정의GetTickerAsync(), 이 기능의 구체적인 기능을 적어주세요. 이 함수는 무한 루프를 실행합니다.whileFMZ API 인터페이스는 루프에서 지속적으로 호출됩니다.GetTicker()시장 데이터를 얻으려면.
그런 다음 사용하세요__threadSetData(0, "ticker", t)이 문장은 메인 스레드에 데이터를 씁니다. 데이터 이름은 다음과 같습니다.ticker, 데이터 값은t지금 바로GetTicker().의 반환 값.
__threadSetData(0, "ticker", t)
스레드의 동시 실행을 위한 사용자 정의 함수를 설계한 후 다음을 작성할 수 있습니다.main()함수의 코드는 다음과 같습니다.main()함수 시작 부분에서는 다음을 사용합니다.
__Thread(GetTickerAsync, 0) // GetTickerAsync为需要并发执行的自定义函数,0为这个传入GetTickerAsync函数的参数
실행을 시작하는 동시 스레드를 만듭니다.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)
}
}



이 요구 사항은 동시 스레드에서 이를 사용하는 방법을 보여주는 간단한 예를 원했던 FMZ 사용자에 의해 제기되었습니다.WebSocket메인스레드에 데이터를 전달하는 방법을 연결하고 설계합니다.main()기능.
실제로 매우 간단하며 이전 예에서 동시 스레드를 만드는 것과 비슷합니다. 스레드 간의 통신만 사용됩니다.__threadPeekMessage()기능 및__threadPostMessage()기능. Binance Exchange의 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("创建WS连接:", stream)
while (true) {
var data = ws.read()
if (data) {
__threadPostMessage(0, data)
}
Log("接收到WS链接推送的数据,data:", data)
// __threadPeekMessage 超时参数设置-1,不阻塞
var msg = __threadPeekMessage(-1)
if (msg) {
if (msg == "stop") {
Log("并发线程Id:", __threadId(), "接收到stop指令")
break
}
}
}
Log("并发线程执行完毕,关闭ws连接")
ws.close()
}
function main() {
tid = __Thread(createWS)
Log("创建并发线程,线程Id:", tid)
while(true) {
// __threadPeekMessage 的超时参数设置为0,阻塞等待数据
var data = __threadPeekMessage(0)
Log("接收到并发线程", ", Id:", tid, ", 发送的数据,data:", data, "#FF0000")
var tbl = {
type : "table",
title : "<symbol>@ticker频道推送消息",
cols : ["事件类型", "事件时间", "交易对", "24小时价格变化", "24小时价格变化百分比", "平均价格", "最新成交价格", "24小时内成交量", "24小时内成交额"],
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("扫尾函数,向Id为", tid, "的并发线程发送stop指令")
__threadPostMessage(tid, "stop")
Log("等待Id为", tid, "的并发线程停止")
__threadJoin(tid)
Log("扫尾函数执行完毕")
}
실제 디스크 작동 테스트:

당신은 볼 수 있습니다main()이 함수는 동시 스레드가 생성한 WebSocket 연결에서 지속적으로 시장 데이터를 수신합니다.
전략이 중지되면 스윕 기능이 작동을 시작합니다.
