3
پر توجہ دیں
1444
پیروکار

پالیسی ٹیمپلیٹ آپ کو WebSocket مارکیٹ کو بغیر کسی رکاوٹ کے استعمال کرنے کی اجازت دیتا ہے۔

میں تخلیق کیا: 2024-10-30 09:49:20, تازہ کاری: 2024-11-05 17:45:31
comments   0
hits   1639

پالیسی ٹیمپلیٹ آپ کو WebSocket مارکیٹ کو بغیر کسی رکاوٹ کے استعمال کرنے کی اجازت دیتا ہے۔

یہ ایک WebSocket مارکیٹ ٹیمپلیٹ ہے جسے FMZ نے باضابطہ طور پر تیار کیا ہے اور اسے بطور ٹیمپلیٹ محفوظ کریں، پھر اسے استعمال کرنے کے لیے نئی حکمت عملی میں اس ٹیمپلیٹ کو منتخب کریں: https://www.fmz.com/strategy/470349

ہمیں WebSocket کی ضرورت کیوں ہے؟

فی الحال، FMZ حکمت عملی بنیادی طور پر روایتی REST API encapsulation پر مبنی ہے ہر API رسائی کے لیے پولنگ کے ذریعے مارکیٹ ڈیٹا حاصل کرنے کے لیے ایک نیٹ ورک کنکشن کی ضرورت ہوتی ہے۔ یہ طریقہ آسان اور استعمال میں آسان ہے، اور زیادہ تر ضروریات کے لیے کافی ہے۔

تاہم، REST پروٹوکول میں موروثی تاخیر کے مسائل ہیں، جن کو اس وقت بڑھایا جائے گا جب متعدد تجارتی جوڑوں اور متعدد تبادلے کی حکمت عملیوں کی ضرورت ہو۔ اگرچہ پلیٹ فارم کے گو فنکشنز کو ایک ساتھ انجام دیا جا سکتا ہے، لیکن تاخیر کا مسئلہ اب بھی موجود ہے، جس کی وجہ سے نسبتاً زیادہ تعدد والی حکمت عملی کی ٹریڈنگ کی ضروریات کو پورا کرنا مشکل ہو جاتا ہے، اس کے علاوہ، اگر بہت زیادہ تجارتی جوڑے ہوں اور پولنگ فریکوئنسی بھی ہو۔ تیزی سے، یہ تجارتی پلیٹ فارم تک رسائی کی حد کا سامنا کرے گا۔

فی الحال، ایکسچینج کے سرورز بھی بھاری بوجھ کے تحت ہیں، وہ سب ایک مکمل WebSocket پروٹوکول فراہم کرتے ہیں اور API صارفین کو اس کی سفارش کرتے ہیں۔ REST پروٹوکول کے مقابلے میں، WebSocket ایک مستقل دو طرفہ کنکشن کا طریقہ فراہم کرتا ہے، جو ایکسچینج کو ریئل ٹائم میں کلائنٹ کو ڈیٹا پہنچانے کے قابل بناتا ہے، متواتر درخواستوں اور جوابات سے گریز کرتا ہے اور تاخیر کو بہت کم کرتا ہے۔ عام طور پر، اگر REST API تک رسائی میں تاخیر تقریباً 20ms ہے، تو WebSocket کے ذریعے ڈیٹا کو آگے بڑھانے میں لیٹنسی تقریباً 2ms ہے۔ اس کے علاوہ، WebSocket پروٹوکول پلیٹ فارم کی رسائی کی فریکوئنسی تک محدود نہیں ہے، اور بنیادی طور پر ایک وقت میں درجنوں تجارتی جوڑوں کو سبسکرائب کرنا ممکن ہے۔

WebSocket اقتباس ٹیمپلیٹ کا تعارف

FMZ مقداری تجارتی پلیٹ فارم نے ایک طویل عرصے سے WebSocket پروٹوکول کی حمایت کی ہے، اور اسے کال کرنا نسبتاً آسان ہے، لیکن نوسکھئیے صارفین کے لیے، متعدد سبسکرپشنز کو ہینڈل کرنا، متعدد ایکسچینج کوٹس کو سبسکرائب کرنا، اور ان کو موثر اور آسانی کے ساتھ ایمبیڈ کرنا اب بھی بہت پیچیدہ ہے۔ پوری حکمت عملی کے عمل. یہ عوامی ویب ساکٹ ریئل ٹائم مارکیٹ ڈیٹا ایکسلریشن ٹیمپلیٹ استعمال کرنے میں بہت آسان ہے اور موجودہ انکیپسلیٹڈ API کالوں کے ساتھ مکمل طور پر مطابقت رکھتا ہے، آپ آسانی سے ان میں ترمیم کر سکتے ہیں اور انہیں تیز کرنے کے لیے استعمال کر سکتے ہیں۔ آپ کی حکمت عملی.

اہم خصوصیات:

  • متعدد ایکسچینج سپورٹ:یہ حکمت عملی متعدد ایکسچینجز جیسے Binance، OKX، Bybit، Bitget، وغیرہ کے WebSocket کنکشنز کو سپورٹ کرتی ہے۔ صارفین خود مزید ایکسچینجز کو سپورٹ کرنے کے لیے اس ٹیمپلیٹ کے پیکیجنگ طریقہ کی نقل کر سکتے ہیں۔
  • حسب ضرورت سبسکرپشن: مخصوص مارکیٹ چینلز (جیسے گہرائی، ٹریڈنگ، وغیرہ) کی رکنیت اور تجارتی حکمت عملیوں کے ذریعے فوری استعمال کے لیے موصول ہونے والے ڈیٹا کی موثر پروسیسنگ کی اجازت دیتا ہے۔
  • ایڈوانسڈ ایرر ہینڈلنگ: بلٹ ان ایرر ٹریکنگ اور ویب ساکٹ ری کنکشن میکانزم ڈیٹا کے بہاؤ کی وشوسنییتا اور تسلسل کو یقینی بنانے کے لیے۔

نفاذ کے اصول کا مختصر تعارف

نوٹ کریں کہ یہ حکمت عملی TypeScript کا استعمال کرتی ہے، اگر آپ صرف JavaScript سے واقف ہیں تو یہ تھوڑا سا ناواقف نظر آسکتا ہے۔ TypeScript جاوا اسکرپٹ پر مبنی ایک قسم کا نظام اور زیادہ زبان کی خصوصیات متعارف کراتا ہے جیسے کہ مقداری تجارت کے لیے جو پیچیدہ منطق پر عمل کرنے کی ضرورت ہوتی ہے، TypeScript کا استعمال ممکنہ غلطیوں کو کم کر سکتا ہے اور کوڈ کی پڑھنے کی اہلیت کو بہتر بنا سکتا ہے۔ لہذا، یہ صرف اسے سیکھنے کی سفارش کی جاتی ہے.

اس کے علاوہ، حکمت عملی FMZ پلیٹ فارم کے غیر مطابقت پذیر میکانزم کا استعمال کرتی ہے، اور میکانزم ذیلی تھریڈ ہو سکتا ہےthreadPostMessage فنکشن مین تھریڈ کو پیغام بھیجتا ہے۔ یہ طریقہ غیر مطابقت پذیر ہے اور چائلڈ تھریڈ میں پیدا ہونے والے ڈیٹا اپ ڈیٹس کے مرکزی دھاگے کو مطلع کرنے کے لیے موزوں ہے۔ مین تھریڈ اور چائلڈ تھریڈ کے ذریعے منسلک کیا جا سکتا ہے۔threadGetData اور__threadSetData فنکشن ڈیٹا شیئر کرتا ہے۔ یہ نقطہ نظر تھریڈز کو مشترکہ حالت تک رسائی اور اس میں ترمیم کرنے کی اجازت دیتا ہے۔ اگر آپ ملٹی تھریڈنگ کے بارے میں جاننا چاہتے ہیں، تو یہ حکمت عملی پلیٹ فارم دستاویزات کے ساتھ مل کر سیکھنے کی ایک اچھی مثال ہے۔

اس حکمت عملی کا بنیادی اصول WebSocket کے ذریعے مین اسٹریم ڈیجیٹل کرنسی ایکسچینجز سے جڑنا اور مقداری تجارتی فیصلوں کے لیے ڈیٹا سپورٹ فراہم کرنے کے لیے حقیقی وقت میں مارکیٹ ڈیٹا (جیسے گہرائی کی معلومات اور لین دین کی معلومات) حاصل کرنا ہے۔ عمل درآمد کا مخصوص طریقہ درج ذیل ہے:

1. WebSocket کنکشن کی ترتیبات

setupWebsocket یہ فنکشن WebSocket کنکشن شروع کرنے اور مارکیٹ ڈیٹا حاصل کرنے کے لیے استعمال ہوتا ہے۔ یہ ایک پیرامیٹر حاصل کرتا ہے۔main_exchanges، اس تبادلے کی نشاندہی کرتا ہے جسے منسلک کرنے کی ضرورت ہے۔

  • MyDial فنکشن: WebSocket کنکشن بنائیں، کنکشن کا وقت ریکارڈ کریں، اور کنکشن بند ہونے پر قریبی وقت نکالیں۔
  • updateSymbols فنکشن: نئی رکنیت کی درخواستوں کے لیے باقاعدگی سے چیک کریں اور ضرورت کے مطابق موجودہ تجارتی جوڑی کی فہرست کو اپ ڈیٹ کریں۔

2. ڈیٹا پروسیسنگ

supports آبجیکٹ تعاون یافتہ تبادلے اور ان کے پروسیسنگ افعال کی وضاحت کرتا ہے (جیسےBinance)۔ ہر ایکسچینج کا پروسیسنگ فنکشن موصول ہونے والے پیغامات کو پارس کرنے اور متعلقہ ڈیٹا نکالنے کا ذمہ دار ہے۔

  • processMsg فنکشن: ایکسچینجز سے پیغامات پر کارروائی کریں، ڈیٹا کی مختلف اقسام کی شناخت کریں (جیسے گہرائی کے اپ ڈیٹس، لین دین وغیرہ)، اور انہیں متحد ایونٹ اشیاء میں فارمیٹ کریں۔

3. سبسکرپشن ڈیٹا

ہر کنکشن پر، سسٹم موجودہ تجارتی جوڑی کی بنیاد پر متعلقہ مارکیٹ ڈیٹا چینلز کو سبسکرائب کرے گا۔

  • getFunction فنکشن: ایکسچینج کے نام کے مطابق متعلقہ پروسیسنگ فنکشن حاصل کریں۔
  • this.wssPublic فنکشن: WebSocket کنکشن شروع کریں اور ڈیٹا وصول کرنا شروع کریں۔

4. تھریڈ مینجمنٹ

ہر ایکسچینج کے لیے ایک تھریڈ شروع کریں، ریئل ٹائم میں ڈیٹا وصول کریں اور کال بیک فنکشنز کے ذریعے ڈیٹا پر کارروائی کریں۔

  • threadMarket فنکشن: چائلڈ تھریڈ میں ڈیٹا حاصل کریں، تازہ ترین گہرائی اور لین دین کی معلومات کو پارس اور اسٹور کریں۔

5. ڈیٹا کے حصول کا طریقہ دوبارہ لکھیں۔

ریئل ٹائم میں اپ ڈیٹ ہونے والے ڈیٹا کو واپس کرنے کو ترجیح دیتے ہوئے، ہر ایکسچینج کے لیے گہرائی اور ٹریڈنگ کی معلومات حاصل کرنے کے طریقوں کو دوبارہ لکھیں۔

ٹیمپلیٹ کا استعمال کیسے کریں۔

  1. ابتدا:استعمال$.setupWebsocket() ٹارگٹ ایکسچینج سے WebSocket کنکشن شروع کریں۔
  2. رکنیت: سسٹم خود بخود متعلقہ چینلز کو سبسکرائب کر لے گا (جیسے کہ گہرائی، ٹریڈنگ وغیرہ) ان مصنوعات کے لیے جو آپ تجارت کرتے ہیں۔
  3. ڈیٹا کا حصول: بلا کرGetDepth() اورGetTrades() فنکشن، مارکیٹ کی گہرائی اور لین دین کے ریکارڈ کو واپس کرنے کے لیے خودکار طور پر WebSocket کا ریئل ٹائم ڈیٹا استعمال کرتا ہے۔
  4. ہینڈلنگ میں خرابی: پالیسی میں ایک ٹریکنگ میکانزم شامل ہے جو کنکشن اور ڈیٹا کی غلطیوں کو لاگ کرتا ہے اور کنکشن کھو جانے کی صورت میں خود بخود دوبارہ جڑنے کی کوشش کرتا ہے۔

اگر ایونٹ لوپ () فنکشن کو حکمت عملی میں شامل کیا جاتا ہے، تو اسے ٹرگر میکانزم میں تبدیل کر دیا جائے گا جب wss ڈیٹا اپ ڈیٹ ہو جائے گا، یہ خود بخود فوری طور پر حاصل ہو جائے گا، اور اگر کوئی تازہ ترین ڈیٹا نہیں ہے، تو یہ انتظار کرے گا۔ یہ ایک ذہین سلیپ فنکشن کے برابر ہے، آپ براہ راست سلیپ بھی استعمال کر سکتے ہیں۔

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 سے رجوع کریں، جہاں WebSocket کو سپورٹ کرنے کے لیے اسے آسانی سے تبدیل کیا جا سکتا ہے:

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

خود ایک نیا تبادلہ کیسے شامل کریں۔

صرف حکمت عملی کے سانچے پر عمل کریں، درج ذیل فارمیٹ کی تقلید کریں، اور ایکسچینج API دستاویزات کا حوالہ دیں:

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