وسائل لوڈ ہو رہے ہیں... لوڈنگ...

ایف ایم زیڈ پلیٹ فارم کے لئے بیرونی سگنل وصول کرنے کا جائزہ: توسیع API بمقابلہ حکمت عملی بلٹ ان HTTP سروس

مصنف:ایجاد کاروں کی مقدار - خواب, تخلیق: 2024-12-12 18:33:26, تازہ کاری: 2024-12-16 09:15:23

img

پیش گوئی

پلیٹ فارم کی لائبریری میں ٹریڈنگ ویو ویب ہوک کو جوڑنے کے بارے میں کئی مضامین موجود ہیں ، جو اس وقت تک پلیٹ فارم کے اندرونی جاوا اسکرپٹ کی حمایت نہیں کرتے تھے۔ پلیٹ فارم کے توسیعی API انٹرفیس کا استعمال کرتے ہوئے:CommandRobotاس کا مطلب یہ ہے کہ ایک بیرونی سگنل کا http/https درخواست FMZ پلیٹ فارم کو بھیجا جاتا ہے ، جس میں پلیٹ فارم سگنل کو منتقل کرتا ہے ، جو حکمت عملی کے ساتھ بات چیت کرنے والے پیغامات کے طور پر حکمت عملی کے پروگرام کو مطلع کرتا ہے۔

پلیٹ فارم کی ترقی ، تکرار اور اپ گریڈ کے ساتھ ، بہت ساری نئی خصوصیات کو اپ ڈیٹ کیا گیا ہے۔ بیرونی سگنل وصول کرنے کے لئے بھی نئے حل موجود ہیں۔ ہر ایک کے اپنے فوائد ہیں ، اور ہم اس موضوع پر ایک ساتھ مل کر بحث کریں گے۔

ایف ایم زیڈ پلیٹ فارم کا استعمال کرتے ہوئے API میں توسیع

بیرونی نظاموں کو اس طرح سے جوڑنے کے فوائد یہ ہیں کہ یہ نسبتا آسان ، مضبوط سیکیورٹی ، اور پلیٹ فارم پر منحصر توسیع API انٹرفیس کی اعلی استحکام ہے۔

بیرونی سگنل وصول کرنے کا عمل:

بیرونی نظام ((Trading View webhook) ہک> FMZ توسیع API سروس ہک> حکمت عملی ڈسک

1، بیرونی نظام (Trading View webhook): مثال کے طور پر ٹریڈنگ ویو پر چلنے والے PINE اسکرپٹ ، الارم قائم کرسکتے ہیں ، جو ٹرگر ہونے پر سیٹ ویب ہوک یو آر ایل پر HTTP درخواست بھیجتے ہیں ، بطور سگنل۔ 2، FMZ توسیع API سروس: اس انٹرفیس تک رسائی حاصل کرنے کے بعد، پلیٹ فارم کو ایک انٹرایکٹو پیغام کے طور پر حکمت عملی کی ڈسک پر بھیجا جاتا ہے. 3، حکمت عملی کی ڈسک: حکمت عملی کی ڈسک میں، GetCommand فنکشن کو انٹرایکٹو پیغامات کی سماعت کرنے کے لئے ڈیزائن کیا جا سکتا ہے، اور پیغام کا پتہ لگانے کے بعد مقررہ کارروائی انجام دیتا ہے.

اس کے مقابلے میں بلٹ ان HTTP سروس کا استعمال کرتے ہوئے براہ راست سروس وصول کرنے کے سگنل بنانے کے لئے، اس کے درمیان ایک قدم زیادہ ہے (پلیٹ فارم کی منتقلی).

حکمت عملی بلٹ ان HTTP سروس

اس پلیٹ فارم میں جاوا اسکرپٹ زبان کی بلٹ ان ایچ ٹی ٹی پی سروس کی صلاحیت کی حمایت کے بعد ، براہ راست ایک متوازی سروس کی نگرانی کے بیرونی سگنل کو تخلیق کیا جاسکتا ہے۔ فوائد یہ ہیں: تخلیق کردہ ایچ ٹی ٹی پی سروس الگ تھلگ تھریڈ ہے ، اور اس سے مرکزی فنکشن کی منطق پر کوئی اثر نہیں پڑتا ہے ، جس میں گیٹ کمانڈ فنکشن کی طرح پیغامات کی نگرانی کی جاسکتی ہے ، براہ راست بیرونی سگنل کی نگرانی کی جاسکتی ہے ، جو ایک توسیعی API پروگرام کا استعمال کرنے کے مقابلے میں ، درمیانی موڑ کے حلقے کو ختم کرتا ہے۔

بیرونی سگنل وصول کرنے کا عمل:

بیرونی نظام ((Trading View webhook) ہک> حکمت عملی کی اصلی ڈسک

1، بیرونی نظام (Trading View webhook): مثال کے طور پر ٹریڈنگ ویو پر چلنے والے PINE اسکرپٹ کو الارم سیٹ کیا جاسکتا ہے ، جو ٹرگر ہونے پر سیٹ ویب ہوک یو آر ایل پر HTTP درخواست بھیجتا ہے ، جس کا اشارہ ہے۔ 2، حکمت عملی ڈسک: حکمت عملی ایک HTTP سروس کو براہ راست بیرونی سگنل حاصل کرنے کے لئے بیک وقت چلتی ہے۔

یہ ایک قدم بچاتا ہے ، لیکن سیکیورٹی کو بڑھانے کے ل the ، https سروس کو ترتیب دینا بہتر ہے ، جس میں فولڈنگ کی ضرورت ہوتی ہے۔

کوڈ کی جانچ

ٹیسٹنگ کے دو طریقوں میں ، مندرجہ ذیل پالیسیاں ہر دور میں 10 HTTP / HTTPS درخواستیں بھیجتی ہیں ، جو بیرونی سگنل کی تقلید کرتی ہیں۔ پھر حکمت عملی "انٹریکشن میسج" اور "HTTP سروس تھریڈ کے ذریعہ بھیجے گئے پیغامات" کی نگرانی کرتی ہے۔ پھر حکمت عملی پروگرام ایک ایک کرکے بیرونی سگنل کے پیغامات اور موصولہ سگنل کا موازنہ کرتی ہے ، سگنل کی کمی کا پتہ لگاتی ہے ، اور حساب کتاب میں وقت لگتا ہے۔

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("测试开始...", "#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("等待结束...", "#FF0000")
                
        var tbls = t.deal()
        LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
        Sleep(20000)
    }
}

اگر ٹیسٹ کیا جائے تو ، سرور کے مخصوص آئی پی ایڈریس ، ایف ایم زیڈ پلیٹ فارم کی توسیع API KEY کو پُر کرنے کی ضرورت ہے۔

var httpUrl = "http://123.123.123.123:8088/CommandRobot"
var accessKey = "xxx"
var secretKey = "xxx"

سرور فنکشن ایک متوازی HTTP سروس بناتا ہے جو بیرونی سگنلز کی نگرانی کرتا ہے۔ توسیع API انٹرفیس کے ذریعہ موصول ہونے والے بیرونی پیغامات کے لئے ، یہ گیٹ کمانڈ فنکشن کا استعمال کرتے ہوئے نگرانی کرتا ہے۔

  • ایچ ٹی ٹی پی سروس تھریڈ کے ذریعے بھیجا گیا پیغام: var msg = threading.mainThread().peekMessage(-1)آپ کی بات سن رہا ہوں۔

  • ایپلی کیشنز API کے ذریعے انٹرایکٹو پیغامات: var cmd = GetCommand()آپ کی بات سن رہا ہوں۔

2، سگنل بھیجنے اور سگنل وصول کرنے کا عمل غیر مسدود ہے، پلیٹ فارم نے بنیادی ملٹی تھریڈ وسائل کی بازیابی کے میکانزم کو بہتر بنایا ہے، جس سے یہ ممکن ہے کہ اس کے ساتھ ساتھ اس کے ساتھ مل کر کام کرنے والے صارفین کو بھی اس کے ساتھ مل کر کام کرنے میں مدد ملے.Threadیاexchange.Goہم آہنگی کے افعال ، بغیر کسی واضح طور پر انتظار کرنے کے لئے کہ ہم آہنگی کے کاموں کو مکمل کیا جائے (جیسے شامل کریں ، انتظار کریں ، وغیرہ) ، نظام کے نچلے حصے میں خود بخود وسائل کی بازیافت کا انتظام کیا جاتا ہے (جسے جدید ترین ورژن کی ضرورت ہوتی ہے) ۔

    // 摘录代码片段,发送信号
    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)                       // 并发调用,非阻塞
        }
    }

    // 摘录代码片段,接收信号
    var cmd = GetCommand()                              // 监听来自扩展API的消息,非阻塞
    var msg = threading.mainThread().peekMessage(-1)    // 监听来自自建Http服务的消息,使用了参数-1,非阻塞

اس کے بعد ہم اس ٹیسٹنگ کے عمل کو دیکھیں گے جس میں یہ معلومات براہ راست کوڈ میں بیان کی گئی ہیں:

function main() {
    __Serve("http://0.0.0.0:8088", serverFunc)      // 在当前策略实例中,创建一个并发的http服务

    var t = createMsgTester(accessKey, secretKey, httpUrl)   // 创建一个用于测试管理的对象
    while (true) {                                           // 策略主循环开始
        Log("测试开始...", "#FF0000")
        t.run()                                              // 每次循环开始,调用测试管理对象的run函数,使用两种方式(1、通过扩展API发送信号,2、直接向当前策略创建的Http服务发送信号),每种方式并发发送10个请求

        var beginTS = new Date().getTime()
        while (new Date().getTime() - beginTS < 60 * 1000) {   // 循环检测来自扩展API的交互消息,循环检测来自自建Http服务的消息
            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()        // 检测到自建的Http服务收到的消息,更新时间为收到时间
                    t.getEcho(obj)                          // ...
                } catch (e) {
                    Log(e)
                }
            }
        }
        Log("等待结束...", "#FF0000")
                
        var tbls = t.deal()                                  // 根据记录的消息,配对,检查是否有未配对的消息,如果有说明有信号丢失
        LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
        Sleep(20000)
    }
}

ٹیسٹ کے نتائج

img

img

کچھ عرصے کے ٹیسٹ کے بعد ، یہ دیکھا گیا ہے کہ ایچ ٹی ٹی پی کا طریقہ اوسطا API کے مقابلے میں تھوڑا سا کم وقت لگتا ہے۔

حکمت عملی بلٹ ان ایچ ٹی ٹی پی سروس سگنل وصول کرتی ہے ، یہ ٹیسٹ کا طریقہ بہت سخت نہیں ہے ، درخواستیں بیرونی سے آئیں گی۔ آسانی سے سمجھنے کے ل this ، اس عنصر کو نظرانداز کیا جاسکتا ہے۔ دونوں طریقوں سے سگنل حاصل کرنے کے ل the ، حکمت عملی بلٹ ان ایچ ٹی پی سروس نے ایک لنک کم کیا ، اور جواب کی رفتار تھوڑی تیز ہونی چاہئے۔ سگنل کی استحکام کے ل the ، سگنل کی کمی یا کمی نہیں ہے۔ ٹیسٹ کے نتائج میں دیکھا جاسکتا ہے کہ ایف ایم زیڈ پلیٹ فارم کی توسیع API بھی اسی طرح مستحکم ہے ، ٹیسٹ میں سگنل کی کمی نہیں دیکھی گئی ، لیکن نیٹ ورک جیسے تمام پہلوؤں کو خارج نہیں کیا جاسکتا جس کی وجہ سے سگنل کا مسئلہ پیدا ہوتا ہے ، بلٹ ان ایچ ٹی پی سروس کا استعمال کرتے ہوئے براہ راست بیرونی سگنل وصول کرنا بھی ایک بہتر حل ہے۔

اس مضمون میں ، متن میں موجود کوڈ میں بلٹ ان HTTP سروس کی توثیق نہیں کی گئی ہے ، اور یہ صرف پیغام کے اعداد و شمار کو وصول کرنے کے لئے ہے ، اگلے مضمون میں ہم نے مل کر ایک قابل استعمال بلٹ ان HTTP سروس کو مکمل کیا ہے جو بیرونی ٹریڈنگ ویو سگنل وصول کرنے کے لئے استعمال کیا جاتا ہے۔


مزید