রিসোর্স লোড হচ্ছে... লোডিং...

একটি নীতিমালা টেমপ্লেট যা আপনাকে ওয়েবসকেট ক্ষেত্রের সাথে নির্বিঘ্নে ব্যবহার করতে দেয়

লেখক:ঘাস, তৈরিঃ ২০২৪-১০-৩০ ০৯ঃ৪৯ঃ২০, আপডেটঃ ২০২৪-১১-০৫ ১৭ঃ৪৫ঃ৩১

img

এটি একটি ওয়েবসকেট টেমপ্লেট যা 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ফাংশন: সাবথ্রেডগুলিতে ডেটা গ্রহণ, বিশ্লেষণ এবং সর্বশেষতম গভীরতা এবং লেনদেনের তথ্য সঞ্চয় করা।

৫. তথ্য সংগ্রহের পদ্ধতি পুনর্লিখন

প্রতিটি এক্সচেঞ্জের জন্য গভীরতা এবং লেনদেনের তথ্য পাওয়ার পদ্ধতিটি পুনর্লিখন করুন, বাস্তব সময়ে আপডেট হওয়া ডেটাকে অগ্রাধিকার দিন।

টেমপ্লেট ব্যবহারের পদ্ধতি

  1. প্রাথমিকীকরণব্যবহারঃ$.setupWebsocket()লক্ষ্য এক্সচেঞ্জের ওয়েবসকেট সংযোগ প্রারম্ভিককরণ।
  2. সাবস্ক্রাইব করুন: সিস্টেমটি স্বয়ংক্রিয়ভাবে আপনার ট্রেডিংয়ের জন্য প্রাসঙ্গিক চ্যানেলগুলিতে সাবস্ক্রাইব করবে (যেমন গভীরতা, ট্রেডিং ইত্যাদি) ।
  3. তথ্য সংগ্রহকল করুনঃGetDepth()এবংGetTrades()ফাংশন, যা স্বয়ংক্রিয়ভাবে ওয়েবসকেট রিয়েল-টাইম ডেটা ব্যবহার করে বাজারের গভীরতা এবং লেনদেনের রেকর্ডের প্রত্যাবর্তন করে।
  4. ভুল ব্যবহার: নীতিতে একটি ট্র্যাকিং প্রক্রিয়া অন্তর্ভুক্ত রয়েছে যা সংযোগ এবং ডেটা ত্রুটিগুলি রেকর্ড করে এবং সংযোগ বিচ্ছিন্ন হলে স্বয়ংক্রিয়ভাবে পুনরায় সংযোগ করার চেষ্টা করে।

যদি ইভেন্টলুপ () ফাংশনটি নীতিতে যুক্ত করা হয় তবে এটি একটি ট্রিগার মেশিন হিসাবে পরিবর্তিত হয় যা যখন ডাব্লুএসএস ডেটা আপডেট হয় তখন স্বয়ংক্রিয়ভাবে তাত্ক্ষণিকভাবে পাওয়া যায়, কোনও আপডেট ডেটা না থাকলে অপেক্ষা করা হয়। স্মার্ট স্লিপ ফাংশনের সমতুল্য, অবশ্যই সরাসরি স্লিপ ব্যবহার করা যেতে পারে।

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)
                }
            }
        }
    }
    

আরো