avatar of 发明者量化-小小梦 发明者量化-小小梦
پر توجہ دیں نجی پیغام
4
پر توجہ دیں
1271
پیروکار

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

میں تخلیق کیا: 2024-12-17 11:44:07, تازہ کاری: 2024-12-17 16:08:11
comments   0
hits   663

[TOC]

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

دیباچہ

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

حکمت عملی پر عمل درآمد

ٹریڈنگ ویو سگنلز تک رسائی کے لیے FMZ ایکسٹینشن API استعمال کرنے کی سابقہ ​​حکمت عملی کے بعد، ہم سابقہ ​​میسج فارمیٹ، میسج پروسیسنگ کا طریقہ، وغیرہ استعمال کرتے ہیں اور حکمت عملی میں سادہ ترمیم کرتے ہیں۔

چونکہ پالیسی میں شامل خدمات Http یا HTTPS استعمال کر سکتی ہیں، سادہ نمائش کے لیے، ہم Http پروٹوکول استعمال کرتے ہیں، IP وائٹ لسٹ کی تصدیق شامل کرتے ہیں، اور پاس ورڈ کی تصدیق شامل کرتے ہیں۔ اگر سیکورٹی کو مزید بڑھانے کی ضرورت ہے تو، پالیسی بلٹ ان سروس کو Https سروس کے طور پر ڈیزائن کیا جا سکتا ہے۔

//信号结构
var Template = {
    Flag: "45M103Buy",     // 标识,可随意指定
    Exchange: 1,           // 指定交易所交易对
    Currency: "BTC_USDT",  // 交易对
    ContractType: "spot",  // 合约类型,swap,quarter,next_quarter,现货填写spot
    Price: "{{close}}",    // 开仓或者平仓价格,-1为市价
    Action: "buy",         // 交易类型[ buy:现货买入 , sell:现货卖出 , long:期货做多 , short:期货做空 , closesell:期货买入平空 , closebuy:期货卖出平多]
    Amount: "1",           // 交易量
}

var Success = "#5cb85c"    // 成功颜色
var Danger = "#ff0000"     // 危险颜色
var Warning = "#f0ad4e"    // 警告颜色
var buffSignal = []

// Http服务
function serverFunc(ctx, ipWhiteList, passPhrase) {
    var path = ctx.path()
    if (path == "/CommandRobot") {
        // 校验IP地址
        var fromIP = ctx.remoteAddr().split(":")[0]        
        if (ipWhiteList && ipWhiteList.length > 0) {
            var ipList = ipWhiteList.split(",")
            if (!ipList.includes(fromIP)) {
                ctx.setStatus(500)
                ctx.write("IP address not in white list")
                Log("500 Error: IP address not in white list", "#FF0000")
                return 
            }
        }

        // 校验口令
        var pass = ctx.rawQuery().length > 0 ? ctx.query("passPhrase") : ""
        if (passPhrase && passPhrase.length > 0) {
            if (pass != passPhrase) {
                ctx.setStatus(500)
                ctx.write("Authentication failed")
                Log("500 Error: Authentication failed", "#FF0000")
                return 
            }
        }

        var body = JSON.parse(ctx.body())
        threading.mainThread().postMessage(JSON.stringify(body))
        ctx.write("OK")
        // 200
    } else {
        ctx.setStatus(404)
    }
}

// 校验信号消息格式
function DiffObject(object1, object2) {
    const keys1 = Object.keys(object1)
    const keys2 = Object.keys(object2)
    if (keys1.length !== keys2.length) {
        return false
    }
    for (let i = 0; i < keys1.length; i++) {
        if (keys1[i] !== keys2[i]) {
            return false
        }
    }
    return true
}

function CheckSignal(Signal) {
    Signal.Price = parseFloat(Signal.Price)
    Signal.Amount = parseFloat(Signal.Amount)
    if (Signal.Exchange <= 0 || !Number.isInteger(Signal.Exchange)) {
        Log("交易所最小编号为1,并且为整数", Danger)
        return
    }
    if (Signal.Amount <= 0 || typeof(Signal.Amount) != "number") {
        Log("交易量不能小于0,并且为数值类型", typeof(Signal.Amount), Danger)
        return
    }
    if (typeof(Signal.Price) != "number") {
        Log("价格必须是数值", Danger)
        return
    }
    if (Signal.ContractType == "spot" && Signal.Action != "buy" && Signal.Action != "sell") {
        Log("指令为操作现货,Action错误,Action:", Signal.Action, Danger)
        return 
    }
    if (Signal.ContractType != "spot" && Signal.Action != "long" && Signal.Action != "short" && Signal.Action != "closesell" && Signal.Action != "closebuy") {
        Log("指令为操作期货,Action错误,Action:", Signal.Action, Danger)
        return 
    }
    return true
}

// 信号处理对象
function createManager() {
    var self = {}
    self.tasks = []
    
    self.process = function() {
        var processed = 0
        if (self.tasks.length > 0) {
            _.each(self.tasks, function(task) {
                if (!task.finished) {
                    processed++
                    self.pollTask(task)
                }
            })
            if (processed == 0) {
                self.tasks = []
            }
        }
    }
    
    self.newTask = function(signal) {
        // {"Flag":"45M103Buy","Exchange":1,"Currency":"BTC_USDT","ContractType":"swap","Price":"10000","Action":"buy","Amount":"0"}
        var task = {}
        task.Flag = signal["Flag"]
        task.Exchange = signal["Exchange"]
        task.Currency = signal["Currency"]
        task.ContractType = signal["ContractType"]
        task.Price = signal["Price"]
        task.Action = signal["Action"]
        task.Amount = signal["Amount"]
        task.exchangeIdx = signal["Exchange"] - 1
        task.pricePrecision = null
        task.amountPrecision = null 
        task.error = null 
        task.exchangeLabel = exchanges[task.exchangeIdx].GetLabel()
        task.finished = false 
        
        Log("创建任务:", task)
        self.tasks.push(task)
    }
    
    self.getPrecision = function(n) {
        var precision = null 
        var arr = n.toString().split(".")
        if (arr.length == 1) {
            precision = 0
        } else if (arr.length == 2) {
            precision = arr[1].length
        } 
        return precision
    }
    
    self.pollTask = function(task) {
        var e = exchanges[task.exchangeIdx]
        var name = e.GetName()
        var isFutures = true
        e.SetCurrency(task.Currency)
        if (task.ContractType != "spot" && name.indexOf("Futures_") != -1) {
            // 非现货,则设置合约
            e.SetContractType(task.ContractType)
        } else if (task.ContractType == "spot" && name.indexOf("Futures_") == -1) {
            isFutures = false 
        } else {
            task.error = "指令中的ContractType与配置的交易所对象类型不匹配"
            return 
        }
        
        var depth = e.GetDepth()
        if (!depth || !depth.Bids || !depth.Asks) {
            task.error = "订单薄数据异常"
            return 
        }
        
        if (depth.Bids.length == 0 && depth.Asks.length == 0) {
            task.error = "盘口无订单"
            return 
        }
        
        _.each([depth.Bids, depth.Asks], function(arr) {
            _.each(arr, function(order) {
                var pricePrecision = self.getPrecision(order.Price)
                var amountPrecision = self.getPrecision(order.Amount)
                if (Number.isInteger(pricePrecision) && !Number.isInteger(self.pricePrecision)) {
                    self.pricePrecision = pricePrecision
                } else if (Number.isInteger(self.pricePrecision) && Number.isInteger(pricePrecision) && pricePrecision > self.pricePrecision) {
                    self.pricePrecision = pricePrecision
                }
                if (Number.isInteger(amountPrecision) && !Number.isInteger(self.amountPrecision)) {
                    self.amountPrecision = amountPrecision
                } else if (Number.isInteger(self.amountPrecision) && Number.isInteger(amountPrecision) && amountPrecision > self.amountPrecision) {
                    self.amountPrecision = amountPrecision
                }
            })
        })

        if (!Number.isInteger(self.pricePrecision) || !Number.isInteger(self.amountPrecision)) {
            task.err = "获取精度失败"
            return 
        }
        
        e.SetPrecision(self.pricePrecision, self.amountPrecision)
        
        // buy:现货买入 , sell:现货卖出 , long:期货做多 , short:期货做空 , closesell:期货买入平空 , closebuy:期货卖出平多
        var direction = null 
        var tradeFunc = null 
        if (isFutures) {
            switch (task.Action) {
                case "long": 
                    direction = "buy"
                    tradeFunc = e.Buy 
                    break
                case "short": 
                    direction = "sell"
                    tradeFunc = e.Sell
                    break
                case "closesell": 
                    direction = "closesell"
                    tradeFunc = e.Buy 
                    break
                case "closebuy": 
                    direction = "closebuy"
                    tradeFunc = e.Sell
                    break
            }
            if (!direction || !tradeFunc) {
                task.error = "交易方向错误:" + task.Action
                return 
            }
            e.SetDirection(direction)
        } else {
            if (task.Action == "buy") {
                tradeFunc = e.Buy 
            } else if (task.Action == "sell") {
                tradeFunc = e.Sell 
            } else {
                task.error = "交易方向错误:" + task.Action
                return 
            }
        }
        var id = tradeFunc(task.Price, task.Amount)
        if (!id) {
            task.error = "下单失败"
        }
        
        task.finished = true
    }
    
    return self
}

function main() {
    // 重置日志信息
    if (isResetLog) {
        LogReset(1)
    }

    Log("交易类型[ buy:现货买入 , sell:现货卖出 , long:期货做多 , short:期货做空 , closesell:期货买入平空 , closebuy:期货卖出平多]", Danger)
    Log("指令模板:", JSON.stringify(Template), Danger)    
    if (!passPhrase || passPhrase.length == 0) {
        Log("webhook url:", `http://${serverIP}:${port}/CommandRobot`)
    } else {
        Log("webhook url:", `http://${serverIP}:${port}/CommandRobot?passPhrase=${passPhrase}`)
    }

    // 创建Http内置服务
    __Serve("http://0.0.0.0:" + port, serverFunc, ipWhiteList, passPhrase)

    // 初始化执行的代码
    if (initCode && initCode.length > 0) {
        try {
            Log("执行初始化代码:", initCode)
            eval(initCode)
        } catch(error) {
            Log("e.name:", error.name, "e.stack:", error.stack, "e.message:", error.message)
        }
    }    

    // 创建信号管理对象
    var manager = createManager()
    
    while (true) {
        try {
            // 检测交互控件,用于测试
            var cmd = GetCommand()
            if (cmd) {
                // 发送Http请求,模拟测试
                var arrCmd = cmd.split(":", 2)
                if (arrCmd[0] == "TestSignal") {
                    // {"Flag":"TestSignal","Exchange":1,"Currency":"BTC_USDT","ContractType":"swap","Price":"10000","Action":"long","Amount":"1"}
                    var signal = cmd.replace("TestSignal:", "")
                    if (!passPhrase || passPhrase.length == 0) {
                        var ret = HttpQuery(`http://${serverIP}:${port}/CommandRobot`, {"method": "POST", "body": signal})
                        Log("测试请求的应答:", ret)
                    } else {
                        var ret = HttpQuery(`http://${serverIP}:${port}/CommandRobot?passPhrase=${passPhrase}`, {"method": "POST", "body": signal})
                        Log("测试请求的应答:", ret)
                    }                    
                }
            }

            // 检测内置Http服务收到请求之后通知主线程的消息,写入manager对象的任务队列
            var msg = threading.mainThread().peekMessage(-1)
            if (msg) {
                Log("收到消息 msg:", msg)
                var objSignal = JSON.parse(msg)
                if (DiffObject(Template, objSignal)) {
                    Log("接收到交易信号指令:", objSignal)
                    buffSignal.push(objSignal)
                    
                    // 检查交易量、交易所编号
                    if (!CheckSignal(objSignal)) {
                        continue
                    }
                    
                    // 创建任务
                    if (objSignal["Flag"] == "TestSignal") {
                        Log("收到测试消息:", JSON.stringify(objSignal))
                    } else {
                        manager.newTask(objSignal)
                    }                    
                } else {
                    Log("指令无法识别", signal)
                }
            } else {
                Sleep(1000 * SleepInterval)
            }

            // 处理任务
            manager.process()
            
            // 状态栏显示信号
            if (buffSignal.length > maxBuffSignalRowDisplay) {
                buffSignal.shift()
            }
            var buffSignalTbl = {
                "type" : "table",
                "title" : "信号记录",
                "cols" : ["Flag", "Exchange", "Currency", "ContractType", "Price", "Action", "Amount"],
                "rows" : []
            }
            for (var i = buffSignal.length - 1 ; i >= 0 ; i--) {
                buffSignalTbl.rows.push([buffSignal[i].Flag, buffSignal[i].Exchange, buffSignal[i].Currency, buffSignal[i].ContractType, buffSignal[i].Price, buffSignal[i].Action, buffSignal[i].Amount])
            }

            LogStatus(_D(), "\n", "`" + JSON.stringify(buffSignalTbl) + "`")            
        } catch (error) {
            Log("e.name:", error.name, "e.stack:", error.stack, "e.message:", error.message)
        }        
    }
}

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

  • پورٹ پیرامیٹر: اگر آپ HTTP پروٹوکول استعمال کرتے ہیں، تو آپ ٹریڈنگ ویو پر صرف پورٹ 80 سیٹ کر سکتے ہیں۔
  • سرور آئی پی پیرامیٹر: سرور کا عوامی IP ایڈریس درج کریں۔
  • initCode پیرامیٹر: ایکسچینج ٹیسٹ ماحول میں جانچ کے لیے بیس ایڈریس کو تبدیل کرنے کے لیے استعمال کیا جا سکتا ہے۔

بیرونی سگنلز تک رسائی کے لیے توسیعی API استعمال کرنے کی حکمت عملی کے مقابلے میں، حکمت عملی میں تبدیلی بڑی نہیں ہے، صرف ایک اضافہ کرناserverFuncHttp سروس پروسیسنگ فنکشن FMZ پلیٹ فارم کے ذریعہ نئے شامل کردہ ملٹی تھریڈڈ میسج پاس کرنے کا طریقہ استعمال کرتا ہے:postMessage/peekMessage، دوسرے کوڈز تقریباً تبدیل نہیں ہوئے ہیں۔

آئی پی وائٹ لسٹ

چونکہ ٹریڈنگ ویو کے ویب ہک سے درخواستیں صرف درج ذیل IP پتوں سے بھیجی جاتی ہیں:

52.89.214.238
34.212.75.30
54.218.53.128
52.32.178.7

لہذا ہم حکمت عملی میں ایک پیرامیٹر شامل کرتے ہیں۔ipWhiteListآئی پی وائٹ لسٹ سیٹ کرنے کے لیے استعمال کیا جاتا ہے وہ تمام درخواستوں کو نظر انداز کر دیا جائے گا جو اس آئی پی ایڈریس وائٹ لسٹ میں نہیں ہیں۔

        // 校验IP地址
        var fromIP = ctx.remoteAddr().split(":")[0]        
        if (ipWhiteList && ipWhiteList.length > 0) {
            var ipList = ipWhiteList.split(",")
            if (!ipList.includes(fromIP)) {
                ctx.setStatus(500)
                ctx.write("IP address not in white list")
                Log("500 Error: IP address not in white list", "#FF0000")
                return 
            }
        }

پاس ورڈ کی تصدیق کریں۔

حکمت عملی میں ایک پیرامیٹر شامل کریں۔passPhrase, تصدیقی پاس ورڈ سیٹ کرنے کے لیے استعمال کیا جاتا ہے یہ پاس ورڈ ٹریڈنگ ویو پر ویب ہُک یو آر ایل سیٹنگز میں کنفیگر کیا جاتا ہے جو کہ تصدیقی پاس ورڈ سے مماثل نہیں ہوتے۔

مثال کے طور پر، ہم نے سیٹ کیا:test123456

        // 校验口令
        var pass = ctx.rawQuery().length > 0 ? ctx.query("passPhrase") : ""
        if (passPhrase && passPhrase.length > 0) {
            if (pass != passPhrase) {
                ctx.setStatus(500)
                ctx.write("Authentication failed")
                Log("500 Error: Authentication failed", "#FF0000")
                return 
            }
        }

بیرونی سگنل

ٹریڈنگ ویو پلیٹ فارم کی PINE اسکرپٹ کو بیرونی سگنل ٹرگر سورس کے طور پر استعمال کریں، اور ٹریڈنگ ویو کے ذریعہ باضابطہ طور پر جاری کردہ PINE اسکرپٹ میں سے ایک کو تصادفی طور پر منتخب کریں:

//@version=6
strategy("MovingAvg Cross", overlay=true)
length = input(9)
confirmBars = input(1)
price = close
ma = ta.sma(price, length)
bcond = price > ma
bcount = 0
bcount := bcond ? nz(bcount[1]) + 1 : 0
if (bcount == confirmBars)
	strategy.entry("MACrossLE", strategy.long, comment="long")
scond = price < ma
scount = 0
scount := scond ? nz(scount[1]) + 1 : 0
if (scount == confirmBars)
	strategy.entry("MACrossSE", strategy.short, comment="short")

بلاشبہ، آپ حقیقی لین دین کو انجام دینے کے لیے براہ راست FMZ پلیٹ فارم پر PINE اسکرپٹس بھی چلا سکتے ہیں، لیکن اگر آپ ٹریڈنگ ویو پلیٹ فارم سے سگنل بھیجنے کے لیے PINE اسکرپٹس چلانا چاہتے ہیں، تو آپ صرف وہی حل استعمال کر سکتے ہیں جن پر ہم نے بات کی ہے۔

ہمیں اس اسکرپٹ کے آرڈر فنکشن پر توجہ مرکوز کرنے کی ضرورت ہے۔commentاس کا ذکر ہم بعد میں مضمون میں کریں گے۔

WebhookUrl اور جسم کی ترتیبات کی درخواست کریں۔

WebhookUrl اور درخواست کے جسم کی ترتیبات بنیادی طور پر بیرونی سگنلز تک رسائی کے لیے پچھلے توسیع شدہ API کے طریقے کی طرح ہیں جو آپ اس مضمون میں نہیں دہرائے جائیں گے۔

Webhook Url

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

جب ہم اس PINE اسکرپٹ کو ٹریڈنگ ویو پر مارکیٹ کے چارٹ میں شامل کرتے ہیں (ہم نے اپنے ٹیسٹ کے لیے Binance کی ETH_USDT دائمی کنٹریکٹ مارکیٹ کا انتخاب کیا)، ہم دیکھ سکتے ہیں کہ اسکرپٹ نے کام کرنا شروع کر دیا ہے۔ پھر ہم اسکرپٹ میں الارم شامل کرتے ہیں جیسا کہ اسکرین شاٹ میں دکھایا گیا ہے۔

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

ویب ہک یو آر ایل کی ترتیبات: پالیسی کوڈ کو خودکار طور پر ویب ہُک یو آر ایل تیار کرنے کے لیے ڈیزائن کیا گیا ہے، ہمیں اسے صرف پالیسی چلانے کے آغاز میں لاگ سے کاپی کرنے کی ضرورت ہے۔

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

http://xxx.xxx.xxx.xxx:80/CommandRobot?passPhrase=test123456

ٹریڈنگ ویو میں یہ شرط رکھی گئی ہے کہ ویب ہُک یو آر ایل HTTP درخواستوں کے لیے صرف پورٹ 80 کا استعمال کر سکتا ہے، اس لیے ہم نے حکمت عملی میں پورٹ پیرامیٹر کو 80 پر بھی سیٹ کیا، تاکہ آپ دیکھ سکیں کہ حکمت عملی کے ذریعے تیار کردہ ویب ہُک یو آر ایل کا لنک پورٹ بھی 80 ہے۔

جسمانی پیغام

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

پھر “ترتیبات” ٹیب میں درخواست کے باڈی میسج کو سیٹ کریں جیسا کہ اسکرین شاٹ میں دکھایا گیا ہے۔

{
    "Flag":"{{strategy.order.id}}",
    "Exchange":1,
    "Currency":"ETH_USDT",
    "ContractType":"swap",
    "Price":"-1",
    "Action":"{{strategy.order.comment}}",
    "Amount":"{{strategy.order.contracts}}"
}

کیا آپ کو ابھی ذکر کردہ PINE اسکرپٹ میں آرڈر کوڈ یاد ہے؟ آئیے مثال کے طور پر کوڈ میں لمبی پوزیشن کے آغاز کو لیتے ہیں:

strategy.entry("MACrossLE", strategy.long, comment="long")

“MACrossLE” وہ مواد ہے جو “{{strategy.order.id}}” کے لیے بھرا جاتا ہے جب مستقبل میں الارم شروع ہوتا ہے۔

“long” وہ مواد ہے جو “{{strategy.order.comment}}” میں بھرا ہوا ہے جب مستقبل میں الارم شروع ہوتا ہے۔ حکمت عملی میں جن سگنلز کی نشاندہی کی گئی ہے وہ ہیں (ذیل میں اسکرین شاٹ):

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

اس لیے سیٹنگز ایک جیسی ہونی چاہئیں۔ یہاں ہم نے آرڈر فنکشن کے لیے “لمبا” اور “مختصر” سیٹ کیا ہے، جو لمبی یا مختصر پوزیشن کھولنے کے سگنلز کی نشاندہی کرتا ہے۔

PINE اسکرپٹ ہر آرڈر کے لیے آرڈر کی مقدار کا تعین نہیں کرتا، اس لیے جب Trading View ایک الرٹ پیغام بھیجتا ہے، تو یہ “{{strategy.order.contracts}}” حصے کو بھرنے کے لیے پہلے سے طے شدہ آرڈر کی مقدار کا استعمال کرتا ہے۔

حقیقی امتحان

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

جب ٹریڈنگ ویو پر چلنے والی PINE اسکرپٹ ٹریڈنگ فنکشن کو انجام دیتی ہے، کیونکہ ہم نے ایک ویب ہُک یو آر ایل الارم ترتیب دیا ہے، ٹریڈنگ ویو پلیٹ فارم ہماری حکمت عملی میں شامل HTTP سروس کو ایک POST کی درخواست بھیجے گا جس میں تصدیق کے لیے پاس ورڈ کے پیرامیٹرز شامل ہیں۔passPhrase. موصول ہونے والی اصل درخواست اس سے ملتی جلتی ہے:

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: حکمت عملی میں بلٹ ان Http سروس کے ساتھ سگنل وصول کرنے کا ایک مکمل حل

پھر ہماری حکمت عملی اس باڈی میں موجود پیغام کی بنیاد پر متعلقہ لین دین کی کارروائیوں کو انجام دیتی ہے۔

یہ دیکھا جا سکتا ہے کہ حکمت عملی ٹریڈنگ ویو پر PINE اسکرپٹ کے مطابق OKX سمولیشن ماحول میں سنکرونائز سگنل ٹریڈنگ کرتی ہے۔

پالیسی کا پتہ

https://www.fmz.com/strategy/475235

FMZ Quantitative پر آپ کی توجہ کا شکریہ، اور پڑھنے کے لیے آپ کا شکریہ۔