प्लेटफ़ॉर्म CommandRobot
, सरल शब्दों में, बाहरी सिग्नल का http/https अनुरोध FMZ प्लेटफॉर्म को भेजा जाता है, और प्लेटफॉर्म सिग्नल को एक रणनीति बातचीत संदेश के रूप में रणनीति कार्यक्रम को अग्रेषित करता है।
जैसा कि मंच विकसित होता है और पुनरावृत्त होता है, कई नई सुविधाओं को अपडेट और अपग्रेड किया गया है। बाहरी संकेत प्राप्त करने के लिए नए समाधान भी हैं। प्रत्येक समाधान के अपने फायदे हैं। इस लेख में, हम इस विषय पर एक साथ चर्चा करेंगे।
बाहरी प्रणालियों से कनेक्ट करने के लिए इस विधि का उपयोग करने के फायदे यह हैं कि यह अपेक्षाकृत सरल, अत्यधिक सुरक्षित है, और प्लेटफ़ॉर्म के विस्तारित एपीआई इंटरफ़ेस की स्थिरता पर निर्भर करता है।
बाहरी संकेत प्राप्त करने की प्रक्रियाः
बाहरी प्रणाली (ट्रेडिंग व्यू वेबहुक)
> FMZ विस्तारित एपीआई सेवा > रणनीति लाइव ट्रेडिंग
सिग्नल को सीधे प्राप्त करने के लिए एक सेवा बनाने के लिए अंतर्निहित एचटीपी सेवा का उपयोग करने की तुलना में, बीच में एक अतिरिक्त कदम है (प्लेटफ़ॉर्म स्थानांतरण) ।
एक बार जब प्लेटफ़ॉर्म जावास्क्रिप्ट भाषा के अंतर्निहित एचटीपी सेवा फ़ंक्शन का समर्थन करता है, तो आप बाहरी संकेतों को सीधे सुनने के लिए एक समवर्ती सेवा बना सकते हैं। फायदे हैंः बनाई गई एचटीपी सेवा एक अलग धागा है और मुख्य फ़ंक्शन तर्क को प्रभावित नहीं करती है। यह गेटकमांड फ़ंक्शन जैसे संदेशों को सुन सकता है और सीधे बाहरी संकेतों को सुन सकता है। विस्तारित एपीआई समाधान के उपयोग की तुलना में, यह पारगमन की आवश्यकता को समाप्त करता है।
बाहरी संकेत प्राप्त करने की प्रक्रियाः
बाहरी प्रणाली (ट्रेडिंग व्यू वेबहुक)
> रणनीति लाइव ट्रेडिंग
यह समाधान एक कदम बचाता है, लेकिन सुरक्षा में सुधार करने के लिए, https सेवा को कॉन्फ़िगर करना बेहतर है, जिसके लिए कुछ प्रयास की आवश्यकता होती है। यह विस्तारित एपीआई समाधान का उपयोग करने की तुलना में थोड़ा अधिक कष्टप्रद है।
दो समाधानों का परीक्षण करें। निम्नलिखित रणनीति बाहरी संकेतों का अनुकरण करने के लिए प्रत्येक चक्र में समानांतर में 10 Http/Https अनुरोध भेजेगी। फिर रणनीति
var httpUrl = "http://123.123.123.123:8088/CommandRobot"
var accessKey = ""
var secretKey = ""
function serverFunc(ctx) {
var path = ctx.path()
if (path == "/CommandRobot") {
var body = ctx.body()
threading.mainThread().postMessage(body)
ctx.write("OK")
// 200
} else {
ctx.setStatus(404)
}
}
function createMsgTester(accessKey, secretKey, httpUrl) {
var tester = {}
tester.currentRobotId = _G()
tester.arrSendMsgByAPI = []
tester.arrSendMsgByHttp = []
tester.arrEchoMsgByAPI = []
tester.arrEchoMsgByHttp = []
tester.idByAPI = 0
tester.idByHttp = 0
var sendMsgByAPI = function(msgByAPI, robotId, accessKey, secretKey) {
var headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Content-Type": "application/json"
}
HttpQuery(`https://www.fmz.com/api/v1?access_key=${accessKey}&secret_key=${secretKey}&method=CommandRobot&args=[${robotId},+""]`, {"method": "POST", "body": JSON.stringify(msgByAPI), "headers": headers})
}
var sendMsgByHttp = function(msgByHttp, httpUrl) {
HttpQuery(httpUrl, {"method": "POST", "body": JSON.stringify(msgByHttp)})
}
tester.run = function() {
var robotId = tester.currentRobotId
for (var i = 0; i < 10; i++) {
var msgByAPI = {"ts": new Date().getTime(), "id": tester.idByAPI, "way": "ByAPI"}
tester.arrSendMsgByAPI.push(msgByAPI)
tester.idByAPI++
threading.Thread(sendMsgByAPI, msgByAPI, robotId, accessKey, secretKey)
var msgByHttp = {"ts": new Date().getTime(), "id": tester.idByHttp, "way": "ByHttp"}
tester.arrSendMsgByHttp.push(msgByHttp)
tester.idByHttp++
threading.Thread(sendMsgByHttp, msgByHttp, httpUrl)
}
}
tester.getEcho =function(msg) {
if (msg["way"] == "ByAPI") {
tester.arrEchoMsgByAPI.push(msg)
} else {
tester.arrEchoMsgByHttp.push(msg)
}
}
tester.deal = function() {
var tbls = []
for (var pair of [[tester.arrEchoMsgByHttp, tester.arrSendMsgByHttp, "ByHttp"], [tester.arrEchoMsgByAPI, tester.arrSendMsgByAPI, "ByAPI"]]) {
var receivedMessages = pair[0]
var sentMessages = pair[1]
var testType = pair[2]
var receivedMap = new Map()
receivedMessages.forEach(message => {
receivedMap.set(message["id"], message)
})
var matchedPairs = []
var timeDifferences = []
for (var sentMessage of sentMessages) {
var receivedMessage = receivedMap.get(sentMessage["id"])
if (receivedMessage) {
matchedPairs.push([JSON.stringify(sentMessage), JSON.stringify(receivedMessage), receivedMessage["ts"] - sentMessage["ts"]])
timeDifferences.push(receivedMessage["ts"] - sentMessage["ts"])
} else {
Log("no matched sentMessage:", sentMessage, "#FF0000")
}
}
var averageTimeDifference = timeDifferences.reduce((sum, diff) => sum + diff, 0) / timeDifferences.length
var tbl = {
"type": "table",
"title": testType + " / averageTimeDifference:" + averageTimeDifference,
"cols": ["send", "received", "ts diff"],
"rows": []
}
for (var pair of matchedPairs) {
tbl["rows"].push(pair)
}
tbls.push(tbl)
Log(testType, ", averageTimeDifference:", averageTimeDifference, "ms")
}
tester.arrSendMsgByAPI = []
tester.arrSendMsgByHttp = []
tester.arrEchoMsgByAPI = []
tester.arrEchoMsgByHttp = []
return tbls
}
return tester
}
function main() {
__Serve("http://0.0.0.0:8088", serverFunc)
var t = createMsgTester(accessKey, secretKey, httpUrl)
while (true) {
Log("Test start...", "#FF0000")
t.run()
var beginTS = new Date().getTime()
while (new Date().getTime() - beginTS < 60 * 1000) {
var cmd = GetCommand()
if (cmd) {
try {
var obj = JSON.parse(cmd)
obj["ts"] = new Date().getTime()
t.getEcho(obj)
} catch (e) {
Log(e)
}
}
var msg = threading.mainThread().peekMessage(-1)
if (msg) {
try {
var obj = JSON.parse(msg)
obj["ts"] = new Date().getTime()
t.getEcho(obj)
} catch (e) {
Log(e)
}
}
}
Log("Waiting is over...", "#FF0000")
var tbls = t.deal()
LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
Sleep(20000)
}
}
यदि परीक्षण, आप विशिष्ट सर्वर आईपी पते और FMZ मंच के विस्तारित एपीआई कुंजी भरने की जरूरत है.
var httpUrl = "http://123.123.123.123:8088/CommandRobot"
var accessKey = "xxx"
var secretKey = "xxx"
Http सेवा थ्रेड द्वारा पुश किए गए संदेशः
द्वारा निगरानी कीvar msg = threading.mainThread().peekMessage(-1)
.
विस्तारित एपीआई इंटरफ़ेस द्वारा अग्रेषित बातचीत संदेशः
द्वारा निगरानी कीvar cmd = GetCommand()
.
Thread
याexchange.Go
, समवर्ती कार्यों के पूरा होने के लिए स्पष्ट रूप से प्रतीक्षा करने की कोई आवश्यकता नहीं है (जैसे कि फ़ंक्शन जोड़ना, प्रतीक्षा फ़ंक्शन, आदि) । अंतर्निहित प्रणाली संसाधन पुनर्प्राप्ति को स्वचालित रूप से संभाल लेगी (इसका समर्थन करने के लिए डॉकर के नवीनतम संस्करण की आवश्यकता होती है) । // Extract code snippet, send signal
tester.run = function() {
var robotId = tester.currentRobotId
for (var i = 0; i < 10; i++) {
var msgByAPI = {"ts": new Date().getTime(), "id": tester.idByAPI, "way": "ByAPI"}
tester.arrSendMsgByAPI.push(msgByAPI)
tester.idByAPI++
threading.Thread(sendMsgByAPI, msgByAPI, robotId, accessKey, secretKey) // Concurrent calls, non-blocking
var msgByHttp = {"ts": new Date().getTime(), "id": tester.idByHttp, "way": "ByHttp"}
tester.arrSendMsgByHttp.push(msgByHttp)
tester.idByHttp++
threading.Thread(sendMsgByHttp, msgByHttp, httpUrl) // Concurrent calls, non-blocking
}
}
// Extract code snippet, receiving signal
var cmd = GetCommand() // Listen for messages from the extension API, non-blocking
var msg = threading.mainThread().peekMessage(-1) // Listen for messages from self-built Http service, using parameter -1, non-blocking
इसके बाद, आइए परीक्षण प्रक्रिया को देखें, जहां जानकारी सीधे कोड में एनोटेट की जाती हैः
function main() {
__Serve("http://0.0.0.0:8088", serverFunc) // Create a concurrent http service in the current strategy instance
var t = createMsgTester(accessKey, secretKey, httpUrl) // Create an object for test management
while (true) { // The strategy main loop starts
Log("Test start...", "#FF0000")
t.run() // At the beginning of each loop, the run function of the test management object is called in two ways (1. Sending signals through the extended API, 2. Sending signals directly to the Http service created by the current strategy), each way sends 10 requests concurrently
var beginTS = new Date().getTime()
while (new Date().getTime() - beginTS < 60 * 1000) { // Loop detection of interactive messages from extended APIs and messages from self-built Http services
var cmd = GetCommand()
if (cmd) {
try {
var obj = JSON.parse(cmd)
obj["ts"] = new Date().getTime() // Detect interactive messages, record messages, and update time to the time received
t.getEcho(obj) // Record to the corresponding array
} catch (e) {
Log(e)
}
}
var msg = threading.mainThread().peekMessage(-1)
if (msg) {
try {
var obj = JSON.parse(msg)
obj["ts"] = new Date().getTime() // Detects the message received by the self-built Http service, and the update time is the receiving time
t.getEcho(obj) // ...
} catch (e) {
Log(e)
}
}
}
Log("Waiting is over...", "#FF0000")
var tbls = t.deal() // Pair according to the recorded messages and check if there is any unpaired message. If there is, it means the signal is lost.
LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
Sleep(20000)
}
}
परीक्षण की अवधि के बाद, यह देखा जा सकता है कि एचटीटीपी विधि को एपीआई विधि की तुलना में औसतन थोड़ा कम समय लगता है।
रणनीति में संकेत प्राप्त करने के लिए एक अंतर्निहित एचटीपी सेवा है। यह परीक्षण विधि बहुत कठोर नहीं है, और अनुरोध बाहर से आना चाहिए। सरल समझ के लिए, इस कारक को नजरअंदाज किया जा सकता है। संकेत अधिग्रहण के दो तरीकों के लिए, रणनीति
यह लेख सिर्फ एक प्रारंभिक बिंदु है, चर्चा करने के लिए आपका स्वागत है, पढ़ने के लिए धन्यवाद।