[TOC]
مقداری تجارت اور خودکار حکمت عملی کی ترقی میں، بعض اوقات HTTP خدمات استعمال کی جاتی ہیں۔ موجد مقداری پلیٹ فارم نے حال ہی میں شامل کیا ہے۔_Serve()
فنکشن، صارفین کو لچکدار HTTP، HTTPS اور TCP سروس تخلیق کرنے کی صلاحیتیں فراہم کرتا ہے۔ اس خصوصیت کے ساتھ، ڈویلپرز سروس کنفیگریشن کے عمل کو آسان بنا سکتے ہیں اور مقداری ماحول میں مزید حسب ضرورت خدمات کو لاگو کر سکتے ہیں، جس سے حکمت عملی کے ڈیزائن کو ہموار اور زیادہ آسان بنایا جا سکتا ہے۔ یہ مضمون متعارف کرائے گا۔_Serve()
فنکشن کے استعمال کے منظرنامے اور بنیادی آپریشنز آپ کو Inventor Quant کے اس نئے فنکشن کے ساتھ جلدی شروع کرنے میں مدد کرتے ہیں۔
کے بارے میں_Serve()
پلیٹ فارم API دستاویزات میں اپ ڈیٹ کیا گیا:
پلیٹ فارم کو اپ گریڈ کر دیا گیا ہے۔_Serve()
فنکشن (چونکہ جاوا اسکرپٹ لینگویج میں پہلے سروسز بنانے کا فنکشن نہیں تھا، اس لیے یہ فنکشن صرف جاوا اسکرپٹ کی لینگویج پالیسیوں کو سپورٹ کرتا ہے)۔ اس فنکشن کی بنیاد پر، ہم بہت سے افعال تیار کر سکتے ہیں اور بہت سی ضروریات کو حل کر سکتے ہیں۔ مثال کے طور پر، حکمت عملی میں بیرونی انٹرفیس، ڈیٹا فارورڈنگ، اور پلیٹ فارم کے جنرل پروٹوکول کے افعال کے ساتھ تعاون کر سکتے ہیں تاکہ بغیر کسی رکاوٹ کے ان تبادلے کو سمیٹ سکیں جو FMZ پلیٹ فارم کے ذریعے تعاون یافتہ نہیں ہیں۔
اس آرٹیکل میں، ہم مثال کے طور پر “پلیٹ فارم کے جنرل پروٹوکول فنکشن کے ساتھ تعاون کرنے کی ضرورت کو بغیر کسی رکاوٹ کے ان ایکسچینجز کو سمیٹنے کے لیے لیں گے جو FMZ پلیٹ فارم سے تعاون یافتہ نہیں ہیں۔” پچھلے مضامین میں“جنرل پروٹوکول گائیڈ”اس آرٹیکل میں، ہم اسپاٹ موڈ میں OKX ایکسچینج کے API کو سمیٹنے کے لیے ازگر کی زبان کا استعمال کرتے ہیں (کیونکہ FMZ خود OKX کو سپورٹ کرتا ہے، OKX کو یہاں صرف ایک مثال کے طور پر استعمال کیا گیا ہے، اور یہ دیگر ایکسچینجز پر لاگو ہوتا ہے جن سے FMZ پلیٹ فارم منسلک نہیں ہے)۔ جب جاوا اسکرپٹ لینگویج سپورٹ کرتی ہے تو اس آرٹیکل میں Python جنرل پروٹوکول پروگرام کو الگ سے چلانے کی ضرورت ہے۔_Serve()
فنکشن کے بعد، جاوا اسکرپٹ لینگویج اسٹریٹجی کے عام پروٹوکول تک رسائی آسان ہے۔
ہم ایکسچینج انٹرفیس کے عمومی پروٹوکول کو ایک “ٹیمپلیٹ لائبریری” میں سمیٹتے ہیں اور اسے براہ راست حکمت عملی میں ضم کرتے ہیں، تاکہ حکمت عملی بغیر کسی رکاوٹ کے ان ایکسچینجز تک رسائی حاصل کر سکے جو FMZ پر تعاون یافتہ نہیں ہیں۔ میں یہاں “جنرل پروٹوکول” ایکسچینج آبجیکٹ کو ترتیب دینے کے بارے میں تفصیلات میں نہیں جاؤں گا، آپ مضمون کا حوالہ دے سکتے ہیں:
ٹیمپلیٹ کو ڈیزائن کرتے وقت، آپ کر سکتے ہیں۔/OKX
شناخت کرتا ہے کہ کنفیگرڈ جنرک پروٹوکول ایکسچینج آبجیکٹ کس ایکسچینج سے تعلق رکھتا ہے۔
سب سے پہلے، موجد مقداری تجارتی پلیٹ فارم میں ایک نئی حکمت عملی بنائیں، حکمت عملی کی قسم کو ٹیمپلیٹ لائبریری، اور حکمت عملی کی زبان کو JavaScript پر سیٹ کریں۔
بنائے گئے پالیسی ٹیمپلیٹ میں تین پیرامیٹرز شامل کریں:
پھر آپ جنرل پروٹوکول ٹیمپلیٹ کے لیے کوڈ ڈیزائن اور لکھنا شروع کر سکتے ہیں۔
کوڈ 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("启动通用协议服务,address:", address, ",port:", port, "#FF0000")
if (proxyConfig != "") {
Log("设置代理:", proxyConfig, "#FF0000")
}
}
محدود جگہ کی وجہ سے، یہاں صرف تمام انٹرفیس لاگو نہیں ہوتے ہیں۔مارکیٹ کا سوال、اثاثہ استفسار、*IO کال کرتا ہے۔*دلچسپی رکھنے والے طلباء تمام انٹرفیس کو نافذ کر سکتے ہیں؛ ڈیزائن مکمل ہونے کے بعد، ٹیمپلیٹ کوڈ کو محفوظ کریں اور ٹیمپلیٹ کا نام اس طرح محفوظ کریں: “TypeScript ورژن جنرل پروٹوکول مثال”۔
OKX ایکسچینج کی apikey، secretkey، پاسفریز وغیرہ کو ترتیب دینے کے بعد، ہم جانچنے کے لیے ایک ٹیسٹ حکمت عملی لکھ سکتے ہیں۔
حکمت عملی ہماری ڈیزائن کردہ ٹیمپلیٹ لائبریری کو چیک کریں:
ٹیسٹ حکمت عملی کوڈ:
function main() {
// 测试GetTicker
Log(`exchange.GetTicker():`, exchange.GetTicker())
// 测试GetAccount
Log(`exchange.GetAccount():`, exchange.GetAccount())
// 测试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"))
// 输出通用协议添加的交易所名称
Log(`exchange.GetName():`, exchange.GetName())
// 输出通用协议添加的交易所标签
Log(`exchange.GetLabel():`, exchange.GetLabel())
}
جیسا کہ آپ دیکھ سکتے ہیں، حکمت عملی کو OKX ایکسچینج تک بغیر کسی رکاوٹ کے رسائی حاصل کرنے کے لیے صرف ایک ٹیمپلیٹ کو چیک کرنے کی ضرورت ہے (حالانکہ OKX ایکسچینج پہلے ہی اس کی حمایت کرتا ہے، مثال کے طور پر، OKX کو یہاں ایک ایکسچینج سے تبدیل کیا گیا ہے جس سے FMZ ابھی تک منسلک نہیں ہوا ہے)۔