मात्रात्मक व्यापार और स्वचालित रणनीति विकास में, http सेवाओं का कभी-कभी उपयोग किया जाता है।_Serve()
हाल ही में, जो उपयोगकर्ताओं को लचीली HTTP, HTTPS और TCP सेवा निर्माण क्षमताएं प्रदान करता है। इस फ़ंक्शन के साथ डेवलपर्स सेवा कॉन्फ़िगरेशन प्रक्रिया को सरल बना सकते हैं और मात्रात्मक वातावरण में अधिक अनुकूलित सेवाओं को लागू कर सकते हैं, जिससे रणनीति डिजाइन चिकनी और अधिक सुविधाजनक हो जाता है। यह लेख फ़ंक्शन के उपयोग परिदृश्यों और बुनियादी संचालन का परिचय देगा।_Serve()
FMZ क्वांट के इस नए फ़ंक्शन के साथ जल्दी से आरंभ करने में आपकी सहायता करने के लिए।
प्लेटफ़ॉर्म एपीआई प्रलेखन_Serve()
अद्यतन किया गया हैः
मंच ने कार्य को उन्नत किया है_Serve()
(जैसा कि जावास्क्रिप्ट भाषा में पहले सेवाओं को बनाने का कार्य नहीं था, यह फ़ंक्शन केवल जावास्क्रिप्ट भाषा में रणनीतियों का समर्थन करता है) । सरल शब्दों में, यह रणनीतियों को नेटवर्क सेवाओं को बनाने की क्षमता रखने में सक्षम बनाता है। इस फ़ंक्शन के आधार पर, हम कई फ़ंक्शन विकसित कर सकते हैं और कई समस्याओं को हल कर सकते हैं। उदाहरण के लिए, रणनीतियों में बाहरी इंटरफेस, डेटा अग्रेषण हो सकते हैं, और प्लेटफॉर्म के कस्टम प्रोटोकॉल फ़ंक्शन के साथ सहयोग कर सकते हैं ताकि एफएमजेड प्लेटफॉर्म द्वारा समर्थित नहीं होने वाले एक्सचेंजों को निर्बाध रूप से कैप्सूल किया जा सके।
इस लेख में, हम एक उदाहरण के रूप में FMZ प्लेटफॉर्म द्वारा समर्थित नहीं एक्सचेंजों को निर्बाध रूप से कैप्सूल करने के लिए मंच के कस्टम प्रोटोकॉल फ़ंक्शन के साथ सहयोग करने की मांग का उपयोग करेंगे। पिछले लेख मेंकस्टम प्रोटोकॉल गाइड, हमने पायथन भाषा का उपयोग ओकेएक्स एक्सचेंज के एपीआई को स्पॉट मोड में कैप्सूल करने के लिए किया (क्योंकि एफएमजेड स्वयं ओकेएक्स का समर्थन करता है, ओकेएक्स का उपयोग यहां केवल एक उदाहरण के रूप में किया जाता है, और यह अन्य एक्सचेंजों पर लागू होता है जो एफएमजेड प्लेटफॉर्म से जुड़े नहीं हैं) । इस लेख में पायथन का कस्टम प्रोटोकॉल प्रोग्राम अलग से चलाने की आवश्यकता है। जब जावास्क्रिप्ट भाषा फ़ंक्शन का समर्थन करती है_Serve()
, यह जावास्क्रिप्ट भाषा रणनीति के लिए कस्टम प्रोटोकॉल तक पहुँचने के लिए आसान है।
हम एक्सचेंज इंटरफेस के कस्टम प्रोटोकॉल को एक
एक टेम्पलेट डिजाइन करते समय, हम उपयोग कर सकते हैं/OKX
यह पहचानने के लिए कि कॉन्फ़िगर किया गया कस्टम प्रोटोकॉल एक्सचेंज ऑब्जेक्ट किस एक्सचेंज का है।
सबसे पहले, एफएमजेड क्वांट ट्रेडिंग प्लेटफॉर्म में एक नई रणनीति बनाएं, रणनीति प्रकार को टेम्पलेट लाइब्रेरी में सेट करें, और रणनीति भाषा को जावास्क्रिप्ट में सेट करें।
बनाए गए रणनीति टेम्पलेट में 3 पैरामीटर जोड़ें:
फिर हम कस्टम प्रोटोकॉल टेम्पलेट के लिए डिजाइन और कोड लिखना शुरू कर सकते हैं।
कोड 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")
}
}
सीमित स्थान के कारण, सभी इंटरफेस यहां लागू नहीं हैं। केवलबाज़ार पूछताछ , संपत्ति क्वेरी, औरआईओ कॉलजो लोग रुचि रखते हैं वे सभी इंटरफेस को लागू कर सकते हैं। डिजाइन पूरा होने के बाद, टेम्पलेट कोड सहेजें और टेम्पलेट नाम को सहेजेंः
ओकेएक्स एक्सचेंज के एपीकेई, सीक्रेटकी, पासफ्रेज आदि को कॉन्फ़िगर करने के बाद, हम परीक्षण करने के लिए एक परीक्षण रणनीति लिख सकते हैं।
रणनीति हमारी डिज़ाइन की गई टेम्पलेट लाइब्रेरी की जाँच करती हैः
परीक्षण रणनीति कोडः
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())
}
जैसा कि हम देख सकते हैं, रणनीति को केवल एक टेम्पलेट की जांच करने की आवश्यकता है ताकि ओकेएक्स एक्सचेंज तक निर्बाध पहुंच प्राप्त हो सके (हालांकि ओकेएक्स एक्सचेंज पहले से ही इसका समर्थन करता है, उदाहरण के लिए, ओकेएक्स को यहां एक एक्सचेंज से बदल दिया गया है जिसे एफएमजेड ने अभी तक कनेक्ट नहीं किया है) ।