FMZ 전략의 초기 설계에서, 동시 동시 작업이 필요한 경우,exchange.Go()
이 함수는 FMZ 캡슐화된 인터페이스의 동시 실행을 달성하기 위해만 사용될 수 있으며, 일부 사용자 지정 연산 (함수) 을 동시에 실행하는 것은 불가능합니다. 이 설계가 전략 프로그램의 효율성을 크게 향상시키기는 하지만, 네이티브 프로그래밍 언어에서 동시 설계에 경험이 있는 학생들은 종종 매우 불편함을 느낀다.
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)
}
}
이 요구 사항은 FMZ 사용자에 의해 제기되었습니다.웹소켓동시 스레드에서 연결 및main()
주선에서 기능.
사실, 그것은 매우 간단하고 이전 예제에서 동시 스레드를 만드는 것과 비슷합니다. 유일한 차이점은 우리가__threadPeekMessage()
그리고__threadPostMessage()
스레드 간의 통신을 위한 기능. 예를 들어 바이낸스 교환에 대한 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()
함수는 동시 스레드에서 생성된 웹소켓 연결에서 시장 데이터를 지속적으로 수신합니다.
라이브 트레이딩 전략을 중지하면, 최종화 함수가 작동을 시작합니다.