এটি একটি ওয়েবসকেট টেমপ্লেট যা FMZ কর্তৃক তৈরি করা হয়েছে এবং এটি অন্য একটি টেমপ্লেট হিসাবে অনুলিপি করা হয়েছে।https://www.fmz.com/strategy/470349
বর্তমানে এফএমজেডের কৌশলটি মূলত traditionalতিহ্যবাহী REST এপিআই প্যাকেজিং, যেখানে প্রতিটি এপিআই অ্যাক্সেসের জন্য একটি নেটওয়ার্ক সংযোগ স্থাপন করা হয় এবং পরামর্শের মাধ্যমে বাজার ডেটা সংগ্রহ করা হয়। এই পদ্ধতিটি সহজ এবং ব্যবহার করা সহজ, বেশিরভাগ প্রয়োজনের জন্য এটি করা যথেষ্ট।
তবে, REST প্রোটোকলের অন্তর্নিহিত বিলম্বের সমস্যা রয়েছে, যখন একাধিক ট্রেড প্যারেন্ট, একাধিক এক্সচেঞ্জের কৌশল প্রয়োজন হয় তখন বিলম্বের সমস্যাটি বাড়ানো হয়। যদিও প্ল্যাটফর্মের Go ফাংশনটি সমান্তরালভাবে সম্পাদন করা যেতে পারে, বিলম্বের সমস্যাটি এখনও বিদ্যমান রয়েছে, যা তুলনামূলকভাবে উচ্চ ফ্রিকোয়েন্সির কৌশলগত লেনদেনের চাহিদা পূরণ করা কঠিন, এবং খুব বেশি লেনদেন, খুব দ্রুত রুটিং ফ্রিকোয়েন্সি এবং ট্রেডিং প্ল্যাটফর্মের অ্যাক্সেসের ফ্রিকোয়েন্সি সীমাবদ্ধতার মুখোমুখি হতে পারে।
বর্তমানে এক্সচেঞ্জগুলির সার্ভার লোডও ভারী, উভয়ই সম্পূর্ণ ওয়েবসকেট প্রোটোকল সরবরাহ করে এবং এপিআই ব্যবহারকারীদের জন্য সুপারিশ করা হয়। REST প্রোটোকলের তুলনায়, ওয়েবসকেট একটি স্থায়ী দ্বি-মুখী সংযোগ প্রদান করে যা এক্সচেঞ্জগুলিকে ক্লায়েন্টের কাছে ডেটা রিয়েল-টাইমে চাপিয়ে দিতে দেয়, ঘন ঘন অনুরোধ এবং প্রতিক্রিয়া এড়ায় এবং বিলম্বকে ব্যাপকভাবে হ্রাস করে। সাধারণভাবে, যদি REST API অ্যাক্সেস করার বিলম্ব 20ms এর কাছাকাছি হয় তবে ওয়েবসকেট দ্বারা চাপানো ডেটা প্রায় 2ms বিলম্বিত হয়। এবং লিঙ্কযুক্ত ওয়েবসকেট প্রোটোকলটি প্ল্যাটফর্ম অ্যাক্সেসের ফ্রিকোয়েন্সি সীমাবদ্ধতা ছাড়াই, মূলত একসাথে কয়েক ডজন লেনদেনের জন্য সাবস্ক্রাইব করতে পারে।
FMZ কোয়ালিটি ট্রেডিং প্ল্যাটফর্মটি খুব তাড়াতাড়ি ওয়েবসকেট প্রোটোকলকে সমর্থন করে এবং তুলনামূলকভাবে সহজ কলিং, তবে নতুন ব্যবহারকারীদের জন্য, একাধিক সাবস্ক্রিপশন, একাধিক এক্সচেঞ্জের জন্য সাবস্ক্রিপশন প্রক্রিয়া পরিচালনা করা এবং পুরো কৌশলগত প্রক্রিয়ায় দক্ষতার সাথে সহজেই এম্বেড করা খুব জটিল। এই উন্মুক্ত ওয়েবসকেট রিয়েল টাইম মার্কেট ডেটা এক্সিলারেটর টেমপ্লেটটি এই সমস্যাটি সমাধান করে, এটি ব্যবহার করা খুব সহজ, এটি বর্তমানে প্যাকেজ করা এপিআই কলগুলির সাথে সম্পূর্ণরূপে সামঞ্জস্যপূর্ণ, বেশিরভাগ মূল REST নীতিগুলির জন্য, আপনার নীতিগুলিকে দ্রুততর করার জন্য সরাসরি ব্যবহারের সহজ পরিবর্তন।
প্রধান বৈশিষ্ট্যঃ
মনে রাখবেন যে এই কৌশলটি টাইপস্ক্রিপ্ট ব্যবহার করে, যদি আপনি কেবল জাভাস্ক্রিপ্টের সাথে পরিচিত হন তবে এটি কিছুটা অদ্ভুত দেখাবে। টাইপস্ক্রিপ্ট জাভাস্ক্রিপ্টের উপর ভিত্তি করে টাইপ সিস্টেম এবং আরও সমৃদ্ধ ভাষার বৈশিষ্ট্যগুলি প্রবর্তন করে, যা পরিমাণগত লেনদেনের মতো জটিল লজিকগুলি পরিচালনা করার প্রয়োজন। টাইপস্ক্রিপ্ট ব্যবহার করে সম্ভাব্য ত্রুটিগুলি হ্রাস করা যায় এবং কোডের পাঠযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা উন্নত করা যায়। অতএব, এটি সহজভাবে শেখার পরামর্শ দেওয়া হয়।
এছাড়া এই কৌশলটি FMZ প্ল্যাটফর্মের একটি সিঙ্ক্রোনাইজেশন পদ্ধতি ব্যবহার করে, যেখানে একটি সাব-থ্রেড __threadPostMessage ফাংশন ব্যবহার করে মূল থ্রেডের কাছে বার্তা পাঠাতে পারে। এই পদ্ধতিটি সিঙ্ক্রোনাইজেশনহীন, এবং এটি একটি সাব-থ্রেডের মধ্যে উত্পন্ন ডেটা আপডেট করার জন্য মূল থ্রেডের জন্য প্রযোজ্য। __threadGetData এবং __threadSetData ফাংশনগুলির মাধ্যমে মূল থ্রেড এবং সাব-থ্রেডের মধ্যে ডেটা ভাগ করা যায়। এই পদ্ধতিটি থ্রেডের অ্যাক্সেস এবং শেয়ারের অবস্থা পরিবর্তন করতে দেয়। যদি আপনি পরবর্তী থ্রেডগুলি শিখতে চান তবে প্ল্যাটফর্ম ডকুমেন্টেশনের সাথে মিলিয়ে এই কৌশলটিও একটি ভাল শেখার উদাহরণ।
এই কৌশলটির মূল নীতি হ'ল মূলধারার ডিজিটাল মুদ্রা এক্সচেঞ্জগুলিকে ওয়েবসকেটের মাধ্যমে সংযুক্ত করা এবং রিয়েল-টাইম বাজারের ডেটা (যেমন গভীরতা এবং লেনদেনের তথ্য) গ্রহণ করা যা পরিমাণগত লেনদেনের সিদ্ধান্তের জন্য ডেটা সমর্থন করে।
১. ওয়েবসকেট সংযোগ সেটিং
setupWebsocket
ফাংশনটি ওয়েবসকেট সংযোগগুলি ইনস্টল করার জন্য ব্যবহৃত হয়, যা বাজারের ডেটা গ্রহণ করে। এটি একটি পরামিতি গ্রহণ করেmain_exchanges
এটি এমন একটি এক্সচেঞ্জ যা ইন্টারনেট সংযোগের প্রয়োজন।
MyDial
ফাংশন: ওয়েবসকেট সংযোগ তৈরি করুন, সংযোগের সময় রেকর্ড করুন, এবং সংযোগ বন্ধ করার সময় বন্ধের সময়টি আউটপুট করুন।updateSymbols
ফাংশন: নিয়মিতভাবে নতুন সাবস্ক্রিপশন অনুরোধের জন্য চেক করুন এবং প্রয়োজন অনুযায়ী বর্তমান লেনদেনের তালিকা আপডেট করুন।২. ডেটা প্রসেসিং
supports
অবজেক্টগুলি সমর্থিত এক্সচেঞ্জ এবং তাদের প্রসেসিং ফাংশন (যেমনBinance
) ; প্রতিটি এক্সচেঞ্জের প্রসেসিং ফাংশন প্রাপ্ত বার্তাগুলি বিশ্লেষণ এবং প্রাসঙ্গিক ডেটা বের করার জন্য দায়ী।
processMsg
ফাংশন: এক্সচেঞ্জ থেকে আসা বার্তাগুলি প্রক্রিয়া করে, বিভিন্ন ধরণের ডেটা (যেমন গভীরতা আপডেট, লেনদেন ইত্যাদি) সনাক্ত করে এবং একটি অভিন্ন ইভেন্ট অবজেক্ট হিসাবে ফর্ম্যাট করে।৩. সাবস্ক্রিপশন ডেটা
প্রতিটি সংযোগের সময়, সিস্টেমটি বর্তমান লেনদেনের উপর ভিত্তি করে সাবস্ক্রিপশনের সাথে সম্পর্কিত বাজার ডেটা চ্যানেলগুলি দেখায়।
getFunction
ফাংশন: এক্সচেঞ্জের নাম অনুসারে সংশ্লিষ্ট প্রসেসিং ফাংশন পান।this.wssPublic
ফাংশন: ওয়েবসকেট সংযোগ আরম্ভ করুন এবং ডেটা গ্রহণ শুরু করুন.৪. থ্রেড ম্যানেজমেন্ট
প্রতিটি এক্সচেঞ্জের জন্য একটি থ্রেড শুরু করুন, রিয়েল-টাইমে ডেটা গ্রহণ করুন এবং পুনরুদ্ধার ফাংশনগুলির মাধ্যমে ডেটা প্রক্রিয়া করুন।
threadMarket
ফাংশন: সাবথ্রেডগুলিতে ডেটা গ্রহণ, বিশ্লেষণ এবং সর্বশেষতম গভীরতা এবং লেনদেনের তথ্য সঞ্চয় করা।৫. তথ্য সংগ্রহের পদ্ধতি পুনর্লিখন
প্রতিটি এক্সচেঞ্জের জন্য গভীরতা এবং লেনদেনের তথ্য পাওয়ার পদ্ধতিটি পুনর্লিখন করুন, বাস্তব সময়ে আপডেট হওয়া ডেটাকে অগ্রাধিকার দিন।
$.setupWebsocket()
লক্ষ্য এক্সচেঞ্জের ওয়েবসকেট সংযোগ প্রারম্ভিককরণ।GetDepth()
এবংGetTrades()
ফাংশন, যা স্বয়ংক্রিয়ভাবে ওয়েবসকেট রিয়েল-টাইম ডেটা ব্যবহার করে বাজারের গভীরতা এবং লেনদেনের রেকর্ডের প্রত্যাবর্তন করে।যদি ইভেন্টলুপ () ফাংশনটি নীতিতে যুক্ত করা হয় তবে এটি একটি ট্রিগার মেশিন হিসাবে পরিবর্তিত হয় যা যখন ডাব্লুএসএস ডেটা আপডেট হয় তখন স্বয়ংক্রিয়ভাবে তাত্ক্ষণিকভাবে পাওয়া যায়, কোনও আপডেট ডেটা না থাকলে অপেক্ষা করা হয়। স্মার্ট স্লিপ ফাংশনের সমতুল্য, অবশ্যই সরাসরি স্লিপ ব্যবহার করা যেতে পারে।
function main() {
$.setupWebsocket()
while (true) {
exchanges.map(e=>{
Log(e.GetName(), e.GetDepth())
Log(e.GetName(), e.GetTrades())
})
EventLoop(100) // trigger by websocket
}
}
আমার আগের মাল্টি মুদ্রা ট্রেডিং কৌশল গাইড দেখুনhttps://www.fmz.com/digest-topic/10506এখানে একটি খুব সুবিধাজনক উপায় যা আপনি ওয়েবসকেট সমর্থন করতে পারেনঃ
function MakeOrder() {
for (let i in Info.trade_symbols) {
let symbol = Info.trade_symbols[i];
let buy_price = exchange.GetDepth(symbol + '_USDT').Asks[0].Price;
let buy_amount = 50 / buy_price;
if (Info.position[symbol].value < 2000){
Trade(symbol, "buy", buy_price, buy_amount, symbol);
}
}
}
function OnTick() {
try {
UpdatePosition();
MakeOrder();
UpdateStatus();
} catch (error) {
Log("循环出错: " + error);
}
}
function main() {
$.setupWebsocket()
InitInfo();
while (true) {
let loop_start_time = Date.now();
if (Date.now() - Info.time.last_loop_time > Info.interval * 1000) {
OnTick();
Info.time.last_loop_time = Date.now();
Info.time.loop_delay = Date.now() - loop_start_time;
}
Sleep(5);
}
}
আপনি যদি এই নীতির টেমপ্লেটটি অনুসরণ করেন এবং নীচের ফর্ম্যাটটি অনুকরণ করেন তবে আপনি এক্সচেঞ্জের এপিআই ডকুমেন্টেশনটি দেখতে পারেনঃ
supports["Binance"] = function (ctx:ICtx) {
let processMsg = function (obj) {
let event = {
ts: obj.E,
instId: obj.s,
depth: null,
trades: [],
}
if (obj.e == "depthUpdate") {
let depth = {
asks: [],
bids: []
}
obj.b.forEach(function (item) {
depth.bids.push({
price: Number(item[0]),
qty: Number(item[1])
})
})
obj.a.forEach(function (item) {
depth.asks.push({
price: Number(item[0]),
qty: Number(item[1])
})
})
event.depth = depth
} else if (obj.e == 'bookTicker') {
event.depth = {
asks: [{ price: Number(obj.a), qty: Number(obj.A) }],
bids: [{ price: Number(obj.b), qty: Number(obj.B) }]
}
} else if (obj.e == 'aggTrade') {
event.ts = obj.E
event.trades = [{
price: Number(obj.p),
qty: Number(obj.q),
ts: obj.T,
side: obj.m ? "sell" : "buy"
}]
} else if (typeof (obj.asks) !== 'undefined') {
event.ts = obj.E || new Date().getTime()
let depth = {
asks: [],
bids: []
}
obj.bids.forEach(function (item) {
depth.bids.push({
price: Number(item[0]),
qty: Number(item[1])
})
})
obj.asks.forEach(function (item) {
depth.asks.push({
price: Number(item[0]),
qty: Number(item[1])
})
})
event.depth = depth
} else {
return
}
return event
}
let channels = ["depth20@100ms", /*"bookTicker", */"aggTrade"]
let ws = null
let endPoint = "wss://stream.binance.com/stream"
if (ctx.name == "Futures_Binance") {
endPoint = "wss://fstream.binance.com/stream"
}
while (true) {
if (!ws) {
let subscribes = []
ctx.symbols.forEach(function (symbol) {
channels.forEach(function (channel) {
subscribes.push(symbol.toLowerCase() + "@" + channel)
})
})
ws = MyDial(endPoint + (subscribes.length > 0 ? ("?streams=" + subscribes.join("/")) : ""))
}
if (!ws) {
Sleep(1000)
continue
}
updateSymbols(ctx, function(symbol:string, method:string) {
ws.write(JSON.stringify({
"method": method.toUpperCase(),
"params": channels.map(c=>symbol.toLowerCase()+'@'+c),
"id": 2
}))
})
let msg = ws.read(1000)
if (!msg) {
if (msg == "") {
trace("websocket is closed")
ws.close()
ws = null
}
continue
}
if (msg == 'ping') {
ws.write('pong')
} else if (msg == 'pong') {
} else {
let obj = JSON.parse(msg)
if (obj.error) {
trace(obj.error.msg, "#ff0000")
continue
}
if (!obj.stream) {
continue
}
if (obj.stream.indexOf("depth") != -1) {
if (typeof(obj.data.s) !== 'string') {
// patch
obj.data.s = obj.stream.split('@')[0].toUpperCase()
}
}
let event = processMsg(obj.data)
if (event) {
ctx.callback(event)
}
}
}
}