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

ایف ایم زیڈ کوانٹ کی نئی خصوصیت: آسانی سے ایچ ٹی ٹی پی سروسز بنانے کے لئے _Serve فنکشن کا استعمال کریں

مصنف:FMZ~Lydia, تخلیق: 2024-11-13 11:59:30, تازہ کاری: 2024-11-15 09:57:05

img

مقداری تجارت اور خودکار حکمت عملی کی ترقی میں ، http خدمات کا کبھی کبھی استعمال کیا جاتا ہے۔ ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم نے ایک فنکشن شامل کیا ہے_Serve()حال ہی میں ، جو صارفین کو لچکدار HTTP ، HTTPS اور TCP سروس تخلیق کی صلاحیتوں کے ساتھ فراہم کرتا ہے۔ اس فنکشن کے ذریعہ ڈویلپرز سروس کی تشکیل کے عمل کو آسان بنا سکتے ہیں اور مقداری ماحول میں زیادہ اپنی مرضی کے مطابق خدمات کو نافذ کرسکتے ہیں ، جس سے حکمت عملی کا ڈیزائن ہموار اور زیادہ آسان ہوجاتا ہے۔ یہ مضمون فنکشن کے استعمال کے منظرنامے اور بنیادی آپریشن متعارف کرائے گا۔_Serve()FMZ Quant کے اس نئے فنکشن کے ساتھ جلدی شروع کرنے میں آپ کی مدد کرنے کے لئے.

کے لئے پلیٹ فارم API دستاویزات_Serve()کو اپ ڈیٹ کیا گیا ہے:

https://www.fmz.com/syntax-guide/fun/global/__serve

طلب

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

اس مضمون میں ، ہم ایک مثال کے طور پر ایف ایم زیڈ پلیٹ فارم کے ذریعہ معاونت نہیں کیے جانے والے تبادلے کو بغیر کسی رکاوٹ کے احاطہ کرنے کے لئے پلیٹ فارم کے کسٹم پروٹوکول فنکشن کے ساتھ تعاون کرنے کی مانگ کا استعمال کریں گے۔ پچھلے مضمون میںکسٹم پروٹوکول گائیڈ، ہم نے اسپاٹ موڈ میں او کے ایکس ایکسچینج کے اے پی آئی کو انکیپسول کرنے کے لئے پائیتھون زبان کا استعمال کیا (کیونکہ ایف ایم زیڈ خود او کے ایکس کی حمایت کرتا ہے ، یہاں او کے ایکس کو صرف ایک مثال کے طور پر استعمال کیا جاتا ہے ، اور یہ دوسرے تبادلے پر لاگو ہوتا ہے جو ایف ایم زیڈ پلیٹ فارم سے منسلک نہیں ہیں۔ اس مضمون میں پائیتھون کا کسٹم پروٹوکول پروگرام الگ سے چلانے کی ضرورت ہے۔ جب جاوا اسکرپٹ زبان فنکشن کی حمایت کرتی ہے_Serve()، یہ اپنی مرضی کے مطابق پروٹوکول تک رسائی کے لئے جاوا اسکرپٹ زبان کی حکمت عملی کے لئے آسان ہے.

ہم تبادلہ انٹرفیس کے کسٹم پروٹوکول کو ٹیمپلیٹ لائبریری کے طور پر احاطہ کرتے ہیں اور اسے براہ راست حکمت عملی میں ضم کرتے ہیں ، تاکہ حکمت عملی FMZ پر تعاون یافتہ نہیں ہونے والے تبادلے تک آسانی سے رسائی حاصل کرسکے۔ میں یہاں کسٹم پروٹوکول تبادلہ آبجیکٹ کی تشکیل کے بارے میں تفصیلات میں نہیں جاؤں گا ، آپ مضمون کا حوالہ دے سکتے ہیں:

https://www.fmz.com/bbs-topic/10527

  • پلیٹ فارم پر اپنی مرضی کے مطابق پروٹوکول تبادلہ ترتیب مندرجہ ذیل ہے:

img

ایک ٹیمپلیٹ ڈیزائن کرتے وقت، ہم استعمال کر سکتے ہیں/OKXشناخت کرنے کے لئے کہ کون سا تبادلہ تشکیل شدہ کسٹم پروٹوکول ایکسچینج آبجیکٹ سے تعلق رکھتا ہے۔

کسٹم پروٹوکول ٹیمپلیٹ کا نفاذ

سب سے پہلے، ایف ایم زیڈ کوانٹ ٹریڈنگ پلیٹ فارم میں ایک نئی حکمت عملی بنائیں، حکمت عملی کی قسم کو ٹیمپلیٹ لائبریری اور حکمت عملی کی زبان کو جاوا اسکرپٹ میں مقرر کریں.

ٹیمپلیٹ پیرامیٹر ڈیزائن

تخلیق کردہ حکمت عملی ٹیمپلیٹ میں 3 پیرامیٹرز شامل کریں:

img

پھر ہم اپنی مرضی کے مطابق پروٹوکول ٹیمپلیٹ کے لئے ڈیزائن اور کوڈ لکھنا شروع کر سکتے ہیں.

کوڈ کا نفاذ

کوڈ TS انداز میں لکھا گیا ہے.$.startService()فنکشن ایک ٹیمپلیٹ انٹرفیس فنکشن ہے جو اپنی مرضی کے مطابق پروٹوکول سروس شروع کرنے کے لئے استعمال ہوتا ہے۔

// @ts-check

$.startService = function (address, port, proxyConfig) {
    __Serve(`http://${address}:${port}`, function (ctx, proxyConfig) {
        // interface
        interface IData {
            data: object
            raw: object
        }
        
        interface IError {
            error: any
        }
        
        // custom protocol for OKX
        class CustomProtocolOKX {
            apiBase: string = "https://www.okx.com"
            accessKey: string
            secretKey: string
            passphrase: string
            proxyConfig: string = ""
            simulate: boolean = false
            
            constructor(accessKey: string, secretKey: string, passphrase: string, simulate?: boolean, proxyConfig?: string) {
                this.accessKey = accessKey
                this.secretKey = secretKey
                this.passphrase = passphrase
                if (typeof(simulate) == "boolean") {
                    this.simulate = simulate
                }
                this.proxyConfig = proxyConfig
            }
            
            httpReq(method: string, path: string, query: string = "", params: {[key: string]: any} = {}, headers: {key: string, value: string | ArrayBuffer}[] = []): {[key: string]: any} {
                let ret = null
                let options = {
                    method: method,                    
                    headers: {
                        'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6', 
                        'Content-Type': 'application/json; charset=UTF-8',
                        'x-simulated-trading': this.simulate ? "1" : "0"
                    },
                }
                
                // headers
                if (Array.isArray(headers) && headers.length > 0) {
                    for (var pair of headers) {
                        options.headers[pair.key] = pair.value
                    }
                }
                
                let url = ""
                if (method == "GET") {
                    if (typeof(query) == "string" && query.length > 0) {
                        url = `${this.apiBase}${path}?${query}`
                    } else {
                        url = `${this.apiBase}${path}`
                    }
                } else {
                    url = `${this.apiBase}${path}`
                    options.body = JSON.stringify(params)
                }

                // request
                try {
                    if (this.proxyConfig != "") {
                        url = `${this.proxyConfig}${url}`
                    }
                    ret = JSON.parse(HttpQuery(url, options))
                } catch(e) {
                    return null
                }
    
                return ret
            }

            callSignedAPI(method: string, path: string, query: string = "", params: {[key: string]: any} = {}): {[key: string]: any} {
                const strTime = new Date().toISOString().slice(0, -5) + 'Z'
                let jsonStr = ""
                if (method == "GET") {
                    jsonStr = Object.keys(params).length > 0 ? JSON.stringify(params) : ""
                } else {
                    jsonStr = Object.keys(params).length > 0 ? JSON.stringify(params) : "{}"
                }                
                let message = `${strTime}${method}${path}${jsonStr}`
                if (method === "GET" && query !== "") {
                    message = `${strTime}${method}${path}?${query}${jsonStr}`
                }

                const signature = Encode("sha256", "string", "base64", message, "string", this.secretKey)
                let headers = []
                headers.push({key: "OK-ACCESS-KEY", value: this.accessKey})
                headers.push({key: "OK-ACCESS-PASSPHRASE", value: this.passphrase})
                headers.push({key: "OK-ACCESS-TIMESTAMP", value: strTime})
                headers.push({key: "OK-ACCESS-SIGN", value: signature})                

                return this.httpReq(method, path, query, params, headers)
            }
            
            urlEncode(params: {[key: string]: string | number}): string {
                let encodeParams: string[] = []
                for (const [key, value] of Object.entries(params)) {
                    encodeParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
                }

                return encodeParams.join("&")
            }

            symbol2Inst(symbol: string): string {
                let arr = symbol.split("_")
                if (arr.length >= 2) {
                    return `${arr[0]}-${arr[1]}`.toUpperCase()
                } else {
                    return `${arr[0]}-USDT`.toUpperCase()
                }
            }

            getSymbol(inst: string): string {
                let arr = inst.split("-")
                if (arr.length >= 2) {
                    return `${arr[0]}_${arr[1]}`.toUpperCase()
                } else {
                    return `${arr[0]}-USDT`.toUpperCase()
                }
            }
            
            // The following code encapsulates OKX's interface
            GetTicker(symbol: string): IData | IError {
                // GET /api/v5/market/ticker , param: instId 

                let inst = this.symbol2Inst(symbol)
                let ret = this.httpReq("GET", "/api/v5/market/ticker", `instId=${inst}`)

                let retData = {}
                for (var ele of ret["data"]) {
                    retData["symbol"] = this.getSymbol(ele["instId"])
                    retData["buy"] = ele["bidPx"]
                    retData["sell"] = ele["askPx"]
                    retData["high"] = ele["high24h"]
                    retData["low"] = ele["low24h"]
                    retData["open"] = ele["open24h"]
                    retData["last"] = ele["last"]
                    retData["vol"] = ele["vol24h"]
                    retData["time"] = ele["ts"]
                }

                return {data: retData, raw: ret}
            }
            
            GetAccount(): IData | IError {
                // GET /api/v5/account/balance
                
                let ret = this.callSignedAPI("GET", "/api/v5/account/balance")

                let retData = []
                for (var ele of ret["data"]) {
                    for (var detail of ele["details"]) {
                        let asset = {"currency": detail["ccy"], "free": detail["availEq"], "frozen": detail["ordFrozen"]}
                        if (detail["availEq"] == "") {
                            asset["free"] = detail["availBal"]
                        }
                        retData.push(asset)
                    }
                }
                
                return {data: retData, raw: ret}
            }

            IO(method: string, path: string, params: {[key: string]: any}): {[key: string]: any} {
                let ret = null 
                if (method == "GET") {
                    ret = this.callSignedAPI(method, path, this.urlEncode(params))
                } else {
                    ret = this.callSignedAPI(method, path, "", params)
                }

                return {data: ret}
            }
        }
        
        // protocol factory
        class ProtocolFactory {
            static createExWrapper(accessKey: string, secretKey: string, exName: string): any {
                let protocol = null
                if (exName == "/OKX") {
                    try {
                        let passphrase = ""
                        let simulate = false
                        let arrSecretKey = secretKey.split(",")

                        if (arrSecretKey.length == 2) {
                            secretKey = arrSecretKey[0]
                            passphrase = arrSecretKey[1]
                        } else if (arrSecretKey.length == 3) {
                            secretKey = arrSecretKey[0]
                            passphrase = arrSecretKey[1]
                            simulate = arrSecretKey[2] == "simulate" ? true : false 
                        } else {
                            return null
                        }
                        protocol = new CustomProtocolOKX(accessKey, secretKey, passphrase, simulate, proxyConfig)
                    } catch(e) {
                        Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
                        return null
                    }
                }
                return protocol
            }
        }
        
        // http service
        let resp = {}
        let reqMethod = ctx.method()
        let reqPath = ctx.path()
        let httpMethod = ctx.header("Http-Method")
        let reqBody = null

        try {
            reqBody = JSON.parse(ctx.body())
        } catch(e) {
            resp = {error: {name: e.name, stack: e.stack, message: e.message, errDesc: "JSON parse error."}}
        }

        // onPost
        if (reqMethod == "POST") {
            if (!["access_key", "secret_key", "method", "params"].every(key=> key in reqBody)) {
                resp = {error: {reqBody: reqBody, errDesc: "reqBody error."}}
            }

            if ("error" in resp) {
                ctx.write(JSON.stringify(resp))
                return 
            }

            let accessKey = reqBody["access_key"]
            let secretKey = reqBody["secret_key"]
            let method = reqBody["method"]
            let params = reqBody["params"]

            let protocol = ProtocolFactory.createExWrapper(accessKey, secretKey, reqPath)
            if (!protocol) {
                ctx.write(JSON.stringify({error: {errDesc: "createExWrapper error."}}))
                return 
            }

            // process GetTicker / GetAccount ...
            if (method == "ticker") {
                if (!["symbol"].every(key=> key in params)) {
                    resp = {error: {params: params, errDesc: "params error."}}
                } else {
                    let symbol = params["symbol"]
                    resp = protocol.GetTicker(symbol)
                }
            } else if (method == "accounts") {
                resp = protocol.GetAccount()
            } else if (method.slice(0, 6) == "__api_") {
                resp = protocol.IO(httpMethod, method.slice(6), params)
            } else {
                ctx.write(JSON.stringify({error: {method: method, errDesc: "method not support."}}))
                return 
            }

            ctx.write(JSON.stringify(resp))
        }
    }, proxyConfig)
}

function init() {
    $.startService(address, port, proxyConfig)
    Log("Start the custom protocol service, address:", address, ",port:", port, "#FF0000")
    if (proxyConfig != "") {
        Log("Setting up the proxy:", proxyConfig, "#FF0000")
    }
}

محدود جگہ کی وجہ سے، تمام انٹرفیس یہاں لاگو نہیں ہیں.مارکیٹ کی تلاش , اثاثہ استفسار، اورآئی او کالانٹرفیسز پر عملدرآمد کیا جاتا ہے۔ دلچسپی رکھنے والے صارفین تمام انٹرفیسز پر عمل درآمد کرسکتے ہیں۔ ڈیزائن مکمل ہونے کے بعد ، ٹیمپلیٹ کوڈ کو محفوظ کریں اور ٹیمپلیٹ کا نام بطور محفوظ کریں: TypeScript ورژن کسٹم پروٹوکول مثال

جانچ کی حکمت عملی

OKX تبادلہs apikey، خفیہ کلید، پاس ورڈ جملہ، وغیرہ کی تشکیل کے بعد، ہم ٹیسٹ کرنے کے لئے ایک ٹیسٹ کی حکمت عملی لکھ سکتے ہیں.

حکمت عملی ہماری ڈیزائن ٹیمپلیٹ لائبریری کی جانچ پڑتال کرتا ہے:

img

ٹیسٹ کی حکمت عملی کا کوڈ:

function main() {
    // Test GetTicker
    Log(`exchange.GetTicker():`, exchange.GetTicker())

    // Test GetAccount
    Log(`exchange.GetAccount():`, exchange.GetAccount())

    // Test exchange.IO
    Log(`exchange.IO("api", "POST", "/api/v5/trade/cancel-all-after", "timeOut=0"):`, exchange.IO("api", "POST", "/api/v5/trade/cancel-all-after", "timeOut=0"))

    // Output the exchange name added by the custom protocol
    Log(`exchange.GetName():`, exchange.GetName())

    // Output exchange tags added by the custom protocol
    Log(`exchange.GetLabel():`, exchange.GetLabel())
}

چلانے کے ٹیسٹ

img

جیسا کہ ہم دیکھ سکتے ہیں ، حکمت عملی کو صرف ایک ٹیمپلیٹ کی جانچ پڑتال کرنے کی ضرورت ہے تاکہ او کے ایکس ایکس ایکسچینج تک ہموار رسائی حاصل کی جاسکے (اگرچہ او کے ایکس ایکس ایکسچینج پہلے ہی اس کی حمایت کرتا ہے ، مثال کے طور پر ، او کے ایکس کو یہاں ایک تبادلے سے تبدیل کیا گیا ہے جس سے ایف ایم زیڈ نے ابھی تک رابطہ نہیں کیا ہے) ۔


مزید