এফএমজেড ডাইজেস্টের আগের নিবন্ধে, আমরা বেশ কয়েকটি অর্ডার এবং পজিশন সিঙ্ক্রোনস কৌশল ডিজাইন করেছি।
এই ডিজাইনগুলি অর্ডার এবং অবস্থানগুলির সিঙ্ক্রোনাইজেশন উপলব্ধি করতে পরিচালিত হতে একই কৌশলটিতে রেফারেন্স অ্যাকাউন্ট এবং সিঙ্ক্রোনস অ্যাকাউন্ট গ্রহণ করে। আজ, আমরা একটি ভিন্ন নকশা চেষ্টা করতে পারি; এফএমজেডের শক্তিশালী বর্ধিত এপিআই ইন্টারফেসের উপর ভিত্তি করে, এখানে আমরা একটি অর্ডার সিঙ্ক্রোনস ম্যানেজমেন্ট সিস্টেম ডিজাইন করি।
প্রথমত, আমাদের কিছু ভাল পরামর্শ এবং প্রয়োজনীয়তা দরকার। উপরের দুটি পূর্ববর্তী আদেশ এবং অবস্থান সিঙ্ক্রোনাইজেশন কৌশলগুলির বেশ কয়েকটি সুস্পষ্ট অসুবিধা রয়েছে। আসুন তাদের একসাথে আলোচনা করিঃ
1.যে ব্যবহারকারীরা কৌশল বট সিঙ্ক্রোনাইজেশন বাস্তবায়ন করেন তাদের অবশ্যই রেফারেন্স অ্যাকাউন্ট প্ল্যাটফর্মের এপিআই কী এবং সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের এপিআই কী থাকতে হবে। ব্যবহারের দৃশ্যের জন্য, সমস্যাটি হ'লঃ আপনার অন্যান্য প্ল্যাটফর্ম অ্যাকাউন্টগুলি আপনার নিজের অ্যাকাউন্টগুলির মধ্যে একটি অনুসরণ করতে পারে। তবে রেফারেন্স অ্যাকাউন্ট এবং সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের একই মালিক না থাকলে এটি পরিস্থিতির জন্য সমস্যা হতে পারে। সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের মালিক কখনও কখনও সুরক্ষার কারণে তার প্ল্যাটফর্ম অ্যাকাউন্টের এপিআই কী সরবরাহ করতে ইচ্ছুক নয়। তবে এপিআই কী সরবরাহ না করে কীভাবে সিঙ্ক্রোনাইজডভাবে ট্রেডিংয়ের জন্য অর্ডার দেওয়া যায়?
সমাধানঃ
এফএমজেড এক্সটেন্ডেড এপিআই ব্যবহার করুন, সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের মালিক (অর্ডার সুপারভাইজার) কেবল এফএমজেড কোয়ান্ট ট্রেডিং প্ল্যাটফর্মটি নিবন্ধন করতে হবে এবং তারপরে একটি কৌশল চালাতে হবে (এই নিবন্ধে ডিজাইন করা সিস্টেমেঃOrder Synchronous Management System (Synchronous Server)
তারপর, FMZ এর বর্ধিত API কী (দ্রষ্টব্য যে এটি প্ল্যাটফর্ম অ্যাকাউন্টের API কী নয়) এবং অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেমের বট আইডি (সিঙ্ক্রোনস সার্ভার) রেফারেন্স অ্যাকাউন্টের মালিককে (অর্ডার মালিক) সরবরাহ করা হবে।
যখন রেফারেন্স অ্যাকাউন্টের মালিকের (অর্ডারের মালিক) বট (Order Synchronous Management System Library (Single Server)
এই নিবন্ধে ডিজাইন করা সিস্টেমে) একটি সংকেত পাঠায়, সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের মালিকের বট ট্রেডিং সংকেতটি গ্রহণ করবে। অর্ডারটি স্বয়ংক্রিয়ভাবে পরে স্থাপন করা হবে।
2. অনেক ডেভেলপার ভাল কৌশল আছে এবং উপরে বর্ণিত পূর্ববর্তী আদেশ এবং অবস্থান সিঙ্ক্রোনাইজেশন কৌশল দুটি ব্যবহার করতে পারবেন না। কারণ যে এই সিঙ্ক্রোনাইজেশন কৌশল সঙ্গে তাদের নিজস্ব কৌশল একত্রিত করতে হবে, এবং তাদের কৌশল ব্যাপকভাবে সংশোধন করা প্রয়োজন হতে পারে, যা সময় ব্যয়বহুল এবং শ্রম-নিবিড় হয়। আপনার পরিপক্ক কৌশল কিছু সরাসরি আদেশ সিঙ্ক্রোনাইজেশন ফাংশন সঙ্গে তাদের আপগ্রেড করার একটি ভাল উপায় আছে?
সমাধানঃ
আপনি একটি অর্ডার সিঙ্ক্রোনাস টেমপ্লেট লাইব্রেরি ডিজাইন করতে পারেনOrder Synchronous Management System Library (Single Server)
নিবন্ধে ডিজাইন করা সিস্টেমে কৌশল), যাতে রেফারেন্স অ্যাকাউন্টের মালিক (অর্ডারের মালিক) সরাসরি এই টেমপ্লেট লাইব্রেরিটি তার নিজস্ব কৌশলতে সন্নিবেশ করতে পারেন যাতে আদেশ এবং অবস্থান সিঙ্ক্রোনাইজেশন অর্জন করতে পারে।
৩.একটি অতিরিক্ত বট হ্রাস করুন শেষ অসুবিধা হল যে আপনি যদি উপরে বর্ণিত পূর্ববর্তী দুটি আদেশ এবং অবস্থান সিঙ্ক্রোনাইজেশন কৌশল ব্যবহার করেন তবে বট পর্যবেক্ষণের জন্য রেফারেন্স অ্যাকাউন্টের একটি অতিরিক্ত অবস্থান (অর্ডার সহ অ্যাকাউন্ট) খুলতে হবে। সমাধানঃ ফাংশনটি রেফারেন্স অ্যাকাউন্ট কৌশলতে এম্বেড করতে টেমপ্লেট লাইব্রেরি ব্যবহার করুন।
অতএব, এই সিস্টেম দুটি অংশ নিয়ে গঠিতঃ 1.অর্ডার সিঙ্ক্রোন ম্যানেজমেন্ট সিস্টেম লাইব্রেরি (একক সার্ভার) 2.অর্ডার সিঙ্ক্রোন ম্যানেজমেন্ট সিস্টেম (সিঙ্ক্রোন সার্ভার)
একবার আমরা আমাদের দাবিগুলো নিশ্চিত হয়ে গেলে, আসুন আমরা ডিজাইন শুরু করি!
মনোযোগ দিন যে এখানে এটি একটি কৌশল নয়, কিন্তু একটি FMZ টেমপ্লেট লাইব্রেরি, যা FMZ API ডকুমেন্টেশনে অনুসন্ধান করা যেতে পারে এবং আমরা এখানে আলোচনা করব না।
টেমপ্লেট কোডঃ
// Global variable
var keyName_label = "label"
var keyName_robotId = "robotId"
var keyName_extendAccessKey = "extendAccessKey"
var keyName_extendSecretKey = "extendSecretKey"
var fmzExtendApis = parseConfigs([config1, config2, config3, config4, config5])
var mapInitRefPosAmount = {}
function parseConfigs(configs) {
var arr = []
_.each(configs, function(config) {
if (config == "") {
return
}
var strArr = config.split(",")
if (strArr.length != 4) {
throw "configs error!"
}
var obj = {}
obj[keyName_label] = strArr[0]
obj[keyName_robotId] = strArr[1]
obj[keyName_extendAccessKey] = strArr[2]
obj[keyName_extendSecretKey] = strArr[3]
arr.push(obj)
})
return arr
}
function getPosAmount(pos, ct) {
var longPosAmount = 0
var shortPosAmount = 0
_.each(pos, function(ele) {
if (ele.ContractType == ct && ele.Type == PD_LONG) {
longPosAmount = ele.Amount
} else if (ele.ContractType == ct && ele.Type == PD_SHORT) {
shortPosAmount = ele.Amount
}
})
var timestamp = new Date().getTime()
return {ts: timestamp, long: longPosAmount, short: shortPosAmount}
}
function sendCommandRobotMsg (robotId, accessKey, secretKey, msg) {
// https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
var url = "https://www.fmz.com/api/v1?access_key=" + accessKey + "&secret_key=" + secretKey + "&method=CommandRobot&args=[" + robotId + ',"' + msg + '"]'
Log(url)
var ret = HttpQuery(url)
return ret
}
function follow(nowPosAmount, symbol, ct, type, delta) {
var msg = ""
var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short
if (delta > 0) {
// Open position
var tradeDirection = type == PD_LONG ? "buy" : "sell"
// Send signal
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else if (delta < 0) {
// Open position
var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
if (nowAmount <= 0) {
Log("No position detected")
return
}
// Send signal
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else {
throw "error"
}
if (msg) {
_.each(fmzExtendApis, function(extendApiConfig) {
var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
Log("Call CommandRobot interface,", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret)
Sleep(1000)
})
}
}
$.PosMonitor = function(exIndex, symbol, ct) {
var ts = new Date().getTime()
var ex = exchanges[exIndex]
// Judge the type of ex
var exName = ex.GetName()
var isFutures = exName.includes("Futures_")
var exType = isFutures ? "futures" : "spot"
if (!isFutures) {
throw "Only support futures order supervising"
}
if (exType == "futures") {
// Cache symbol ct
var buffSymbol = ex.GetCurrency()
var buffCt = ex.GetContractType()
// Switch to the corresponding trading pair and contract code
ex.SetCurrency(symbol)
if (!ex.SetContractType(ct)) {
throw "SetContractType failed"
}
// Monitor position
var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct // refPos-exIndex-symbol-contractType
var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
if (!initRefPosAmount) {
// The data is not initialized; initialize it
mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
}
// Monitor
var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
// Calculate position changes
var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short
// Detect changes
if (!(longPosDelta == 0 && shortPosDelta == 0)) {
// Execute long position action
if (longPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Execute long position order supervision, change volume:", longPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
}
// Execute short position action
if (shortPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Execute short position order supervision, change volume:", shortPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
}
// After executing the order supervision operation, update
mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
}
// Recover symbol ct
ex.SetCurrency(buffSymbol)
ex.SetContractType(buffCt)
} else if (exType == "spot") {
// Spot
}
}
$.getTbl = function() {
var tbl = {
"type" : "table",
"title" : "Synchrodata",
"cols" : [],
"rows" : []
}
// Construct the table title
tbl.cols.push("Monitoring account:refPos-exIndex-symbol-contractType")
tbl.cols.push(`Mintoring position:{"timestamp":xxx,"long position volume":xxx,"short position volume":xxx}`)
_.each(fmzExtendApis, function(extendApiData, index) {
tbl.cols.push(keyName_robotId + "-" + index)
})
// Write in the data
_.each(mapInitRefPosAmount, function(initRefPosAmount, key) {
var arr = [key, JSON.stringify(initRefPosAmount)]
_.each(fmzExtendApis, function(extendApiData) {
arr.push(extendApiData[keyName_robotId])
})
tbl.rows.push(arr)
})
return tbl
}
// Invocation example of the strategy in the template
function main() {
// Clear all logs
LogReset(1)
//Switch to OKEX simulated bot test
exchanges[0].IO("simulate", true)
// Set contract
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// Timed trading time interval
var tradeInterval = 1000 * 60 * 3 // trade every three minutes, to observe the order supervising signal
var lastTradeTS = new Date().getTime()
while (true) {
// Other logic of the strategy...
// Used to test the simulated trade trigger
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("Simulated strategy with orders has trades, and positions changed", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// Call the interface function in the template
$.PosMonitor(0, "ETH_USDT", "swap") // You can set multiple monitors, to minitor different exchange objects in the strategy with orders
var tbl = $.getTbl()
// Display the status bar
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
নকশা খুব সহজ, লাইব্রেরি 2 ফাংশন আছে. যখন FMZ প্ল্যাটফর্মে একটি প্রোগ্রাম ট্রেডিং কৌশল কলOrder Synchronous Management System Library (Single Server)
টেমপ্লেট ক্লাস লাইব্রেরি। এই কৌশলটি নিম্নলিখিত ফাংশনগুলি ব্যবহার করতে পারে।
ব্যবহারের উদাহরণ হলmain
অর্ডার সিঙ্ক্রোনস ম্যানেজমেন্ট সিস্টেম লাইব্রেরিতে ফাংশন (একক সার্ভার):
// Invocation example of the strategy in the template
function main() {
// Clear all logs
LogReset(1)
// Switch to OKEX simulated bot test
exchanges[0].IO("simulate", true)
// Set contract
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// Timed trading time interval
var tradeInterval = 1000 * 60 * 3 // trade every three minutes, to observe the order supervising signal
var lastTradeTS = new Date().getTime()
while (true) {
// Other logic of the strateg...
// Used to test the simulated trade trigger
var ts = new Date().getTime()
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("Simulated strategy with orders has trades, and positions changed", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// Use the interface function of the template
$.PosMonitor(0, "ETH_USDT", "swap") // You can set multiple monitors to monitor different exchange objects on an strategy with orders
var tbl = $.getTbl()
// Display the status bar
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
একটি টেমপ্লেট লাইব্রেরি নিজেই একটি কৌশল বট তৈরি করতে পারে, যা সাধারণত টেমপ্লেট লাইব্রেরি পরীক্ষা করতে ব্যবহৃত হয়। উদাহরণস্বরূপ এই টেমপ্লেট জন্য একটি পরীক্ষা। আপনি বুঝতে পারেন যেmain
টেমপ্লেটে ফাংশন হলmain
আপনার নিজস্ব কৌশলগুলির একটির ফাংশন।
পরীক্ষার কোডটি পরীক্ষার জন্য ওকেএক্স সিমুলেটেড বট ব্যবহার করার জন্য লেখা হয়েছে, এবং ওকেএক্স সিমুলেটেড বটের এপিআই কীটি একটি রেফারেন্স অ্যাকাউন্ট (অর্ডার সহ) হিসাবে এফএমজেডে কনফিগার করা দরকার, এবং মূল ফাংশনটি সিমুলেটেড বটে স্যুইচ করতে শুরু করে। তারপরে ট্রেডিং জোড়াটি ETH_USDT এ সেট করুন, এবং চুক্তিটি স্যুইচ করতে সেট করুন। তারপরে একটি while লুপ প্রবেশ করুন। লুপে, কৌশল ব্যবসায়ের ট্রিগার সিমুলেট করার জন্য প্রতি 3 মিনিটে একটি অর্ডার স্থাপন করা হয়।$.PosMonitor(0, "ETH_USDT", "swap")
while loop এ কল করা হয়, এবং কল করা ফাংশনের প্রথম প্যারামিটার হল 0, যার অর্থ এক্সচেঞ্জ অবজেক্ট এক্সচেঞ্জ[0], ট্রেডিং জোড়া ETH_USDT এবং swap contract এর পর্যবেক্ষণ করা। তারপর কল করুন$.getTbl()
চার্ট তথ্য পেতে, এবং ব্যবহারLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
স্ট্যাটাস বারে প্রদর্শিত চার্ট ডেটা তৈরি করতে।
সুতরাং আপনি দেখতে পারেন, যতক্ষণ না$.PosMonitor(0, "ETH_USDT", "swap")
টেমপ্লেটটি কল করে এমন একটি কৌশলতে ব্যবহৃত হয়, কৌশলটি একটি নির্দিষ্ট প্রতীক অবস্থান পর্যবেক্ষণ এবং অবস্থান পরিবর্তন বার্তাটি চাপানোর ফাংশন থাকতে পারে।
পরীক্ষার আগে, পরামিতি নকশা ব্যাখ্যা করুনOrder Synchronous Management System Library (Single Server)
কৌশলঃ
আমি শুধু টেমপ্লেটের ইন্টারফেস ফাংশন ব্যবহার করে অর্ডার বহন করার ফাংশন দিয়ে একটি কৌশল আপগ্রেড করতে কিভাবে কথা বলেছি. তাই অবস্থান পরিবর্তন যখন সংকেত পাঠানো হয়?
কার কাছে পাঠাতে হবে তা প্রশ্নটি প্যারামিটার দ্বারা কনফিগার করা হয়order synchronous management system library (Single Server)
.
আপনি পাঁচটি পরামিতি দেখতে পারেন, যা সর্বোচ্চ পাঁচটি ধাক্কা সমর্থন করতে পারে (আপনি যদি ধাক্কা সংখ্যা বাড়াতে চান তবে আপনি এটি নিজেরাই প্রসারিত করতে পারেন); পরামিতিগুলির ডিফল্টটি একটি খালি স্ট্রিং, যথা প্রক্রিয়াজাত নয়। কনফিগার করা স্ট্রিং ফর্ম্যাটেঃ লেবেল, robotId, accessKey, secretKey
লেবেল সিঙ্ক্রোনিক অ্যাকাউন্টের লেবেল, একটি অ্যাকাউন্ট লেবেল করতে ব্যবহৃত হয়; লেবেল নামটি এলোমেলোভাবে সেট করা যেতে পারে।
robotId
বট আইডি;order synchronous management system (Synchronous Server)
সিঙ্ক্রোনস অ্যাকাউন্টের মালিকের দ্বারা তৈরি।
অ্যাক্সেস কী এফএমজেডের এক্সটেন্ডেড এপিআই এর অ্যাক্সেসকি।
সিক্রেটকি এফএমজেডের সিক্রেট কী এপিআই প্রসারিত করেছে।
তারপর, আমরা একটি সহজ পরীক্ষা পরিচালনা করতে পারেন।
অর্ডার সিঙ্ক্রোন ম্যানেজমেন্ট সিস্টেম লাইব্রেরি (একক সার্ভার) বট অপারেশনঃ
অর্ডার সিঙ্ক্রোন ম্যানেজমেন্ট সিস্টেম (সিঙ্ক্রোন সার্ভার) বট সিগন্যালটি পেয়েছেঃ অর্ডার সিঙ্ক্রোনাস ম্যানেজমেন্ট সিস্টেম (সিঙ্ক্রোনাস সার্ভার) এখন সম্পূর্ণরূপে আমাদের দ্বারা ডিজাইন করা হয় নি, এবং আমরা একটি সহজ কোড ব্যবহার করতে পারেন এটি উপলব্ধি করতে, ট্রেডিং ছাড়া, শুধুমাত্র প্রিন্ট সংকেতঃ
অর্ডার সিঙ্ক্রোন ম্যানেজমেন্ট সিস্টেম (সিঙ্ক্রোন সার্ভার) অস্থায়ী কোডঃ
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
আপনি দেখতে পাচ্ছেন, সিঙ্ক্রোনাইজড অ্যাকাউন্টের মালিকের বট এই বার্তাটি পেয়েছেঃETH_USDT,swap,buy,1
.
সুতরাং, পরবর্তী ধাপে, আমরা ট্রেডিং জোড়া, চুক্তি কোড, ট্রেডিং দিক এবং ভলিউম অনুযায়ী, স্বয়ংক্রিয়ভাবে অর্ডার তত্ত্বাবধান করতে পারি।
বর্তমানে,order synchronous management system (Synchronous Server)
এটি কেবলমাত্র অস্থায়ী কোড, এবং আমরা পরবর্তী নিবন্ধে এর নকশা সম্পর্কে আরও আলোচনা করতে পারি।