وسائل لوڈ ہو رہے ہیں... لوڈنگ...

کریپٹو کرنسی فیوچر ٹریڈنگ کا منطق

مصنف:نیکی, تخلیق: 2020-07-18 13:31:34, تازہ کاری: 2023-10-26 20:05:28

img

مسئلہ کا منظر

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

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

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

تجارتی منطق یہ سمجھ سکتی ہے کہ آرڈر کو پورا نہیں کیا گیا ہے اور آرڈر جاری رکھنا ہے۔ تاہم ، تبادلے کے آرڈر کی جگہ کا انٹرفیس تاخیر نہیں کرتا ہے ، لیکن لین دین تیز ہے ، اور آرڈر پر عمل درآمد ہوتا ہے۔ اس کا سنگین نتیجہ یہ ہوگا کہ حکمت عملی پوزیشن کھولنے کے آپریشن کو متحرک کرتے وقت بار بار آرڈر دے گی۔

حقیقی تجربہ

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

حل تلاش کریں

  • منصوبہ 1

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

  • منصوبہ 2

ایکسچینج کے مارکیٹ پرائس فنکشن کا استعمال کرتے ہوئے ، ایف ایم زیڈ پر قیمت پاس -1 مارکیٹ پرائس ہے۔ فی الحال ، اوکیکس فیوچر انٹرفیس کو اپ گریڈ کیا گیا ہے تاکہ حقیقی مارکیٹ پرائس کی حمایت کی جاسکے۔

  • منصوبہ 3

ہم اب بھی پچھلے ٹریڈنگ منطق کا استعمال کرتے ہیں اور ایک حد آرڈر دیتے ہیں ، لیکن ہم پوزیشن کے اعداد و شمار میں تاخیر کی وجہ سے پیدا ہونے والے مسئلے کو حل کرنے کی کوشش کرنے کے لئے ٹریڈنگ منطق میں کچھ پتہ لگانے کا اضافہ کرتے ہیں۔ آرڈر دینے کے بعد ، اگر آرڈر منسوخ نہیں ہوتا ہے تو ، یہ زیر التواء آرڈرز کی فہرست میں براہ راست غائب ہوجاتا ہے (پینڈنگ آرڈرز کی فہرست دو ممکنہ طریقوں سے غائب ہوجاتی ہے: 1 آرڈر واپس لیں ، 2 پر عمل درآمد کریں) ، ایسی صورتحال کا پتہ لگائیں اور آرڈر کی رقم دوبارہ رکھیں۔ آخری آرڈر کی رقم ایک جیسی ہے۔ اس وقت ، اس بات پر توجہ دینا ضروری ہے کہ آیا پوزیشن ڈیٹا میں تاخیر ہوئی ہے۔ پروگرام کو پوزیشن کی معلومات کو دوبارہ حاصل کرنے کے لئے انتظار کی منطق میں داخل ہونے دیں۔ آپ ٹرگرنگ انتظار کی تعداد کو بہتر بنانا اور بڑھانا بھی جاری رکھ سکتے ہیں۔ اگر یہ ایک خاص تعداد سے تجاوز کرتا ہے تو ، پوزیشن انٹرفیس ڈیٹا میں تاخیر ہوتی ہے۔ مسئلہ سنگین ہے ، لین دین کی منطق کو ختم کرنے دیں۔

پلان 3 پر مبنی ڈیزائن

// Parameter
/*
var MinAmount = 1
var SlidePrice = 5
var Interval = 500
*/

function GetPosition(e, contractType, direction) {
    e.SetContractType(contractType)
    var positions = _C(e.GetPosition);
    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType == contractType && positions[i].Type == direction) {
            return positions[i]
        }
    }

    return null
}

function Open(e, contractType, direction, opAmount) {
    var initPosition = GetPosition(e, contractType, direction);
    var isFirst = true;
    var initAmount = initPosition ? initPosition.Amount : 0;
    var nowPosition = initPosition;
    var directBreak = false 
    var preNeedOpen = 0
    var timeoutCount = 0
    while (true) {
        var ticker = _C(e.GetTicker)
        var needOpen = opAmount;
        if (isFirst) {
            isFirst = false;
        } else {
            nowPosition = GetPosition(e, contractType, direction);
            if (nowPosition) {
                needOpen = opAmount - (nowPosition.Amount - initAmount);
            }
            // Detect directBreak and the position has not changed
            if (preNeedOpen == needOpen && directBreak) {
                Log("Suspected position data is delayed, wait 30 seconds", "#FF0000")
                Sleep(30000)
                nowPosition = GetPosition(e, contractType, direction);
                if (nowPosition) {
                    needOpen = opAmount - (nowPosition.Amount - initAmount);
                }
                /*
                timeoutCount++
                if (timeoutCount > 10) {
                    Log("Suspected position delay for 10 consecutive times, placing order fails!", "#FF0000")
                    break
                }
                */
            } else {
                timeoutCount = 0
            }
        }
        if (needOpen < MinAmount) {
            break;
        }
        
        var amount = needOpen;
        preNeedOpen = needOpen
        e.SetDirection(direction == PD_LONG ? "buy" : "sell");
        var orderId;
        if (direction == PD_LONG) {
            orderId = e.Buy(ticker.Sell + SlidePrice, amount, "Open long position", contractType, ticker);
        } else {
            orderId = e.Sell(ticker.Buy - SlidePrice, amount, "Open short position", contractType, ticker);
        }

        directBreak = false
        var n = 0
        while (true) {
            Sleep(Interval);
            var orders = _C(e.GetOrders);
            if (orders.length == 0) {
                if (n == 0) {
                    directBreak = true
                }
                break;
            }
            for (var j = 0; j < orders.length; j++) {
                e.CancelOrder(orders[j].Id);
                if (j < (orders.length - 1)) {
                    Sleep(Interval);
                }
            }
            n++
        }
    }

    var ret = {
        price: 0,
        amount: 0,
        position: nowPosition
    };
    if (!nowPosition) {
        return ret;
    }
    if (!initPosition) {
        ret.price = nowPosition.Price;
        ret.amount = nowPosition.Amount;
    } else {
        ret.amount = nowPosition.Amount - initPosition.Amount;
        ret.price = _N(((nowPosition.Price * nowPosition.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount);
    }
    return ret;
}

function Cover(e, contractType, opAmount, direction) {
    var initPosition = null;
    var position = null;
    var isFirst = true;

    while (true) {
        while (true) {
            Sleep(Interval);
            var orders = _C(e.GetOrders);
            if (orders.length == 0) {
                break;
            }
            for (var j = 0; j < orders.length; j++) {
                e.CancelOrder(orders[j].Id);
                if (j < (orders.length - 1)) {
                    Sleep(Interval);
                }
            }
        }

        position = GetPosition(e, contractType, direction)
        if (!position) {
            break
        }
        if (isFirst == true) {
            initPosition = position;
            opAmount = Math.min(opAmount, initPosition.Amount)
            isFirst = false;
        }

        var amount = opAmount - (initPosition.Amount - position.Amount)
        if (amount <= 0) {
            break
        }

        var ticker = _C(exchange.GetTicker)
        if (position.Type == PD_LONG) {
            e.SetDirection("closebuy");
            e.Sell(ticker.Buy - SlidePrice, amount, "Close long position", contractType, ticker);
        } else if (position.Type == PD_SHORT) {
            e.SetDirection("closesell");
            e.Buy(ticker.Sell + SlidePrice, amount, "Close short position", contractType, ticker);
        }

        Sleep(Interval)
    }

    return position
}

$.OpenLong = function(e, contractType, amount) {
    if (typeof(e) == "string") {
        amount = contractType
        contractType = e
        e = exchange
    }

    return Open(e, contractType, PD_LONG, amount);
}

$.OpenShort = function(e, contractType, amount) {
    if (typeof(e) == "string") {
        amount = contractType
        contractType = e
        e = exchange
    }

    return Open(e, contractType, PD_SHORT, amount);
};

$.CoverLong = function(e, contractType, amount) {
    if (typeof(e) == "string") {
        amount = contractType
        contractType = e
        e = exchange
    }

    return Cover(e, contractType, amount, PD_LONG);
};

$.CoverShort = function(e, contractType, amount) {
    if (typeof(e) == "string") {
        amount = contractType
        contractType = e
        e = exchange
    }

    return Cover(e, contractType, amount, PD_SHORT);
};


function main() {
    Log(exchange.GetPosition())
    var info = $.OpenLong(exchange, "quarter", 100)
    Log(info, "#FF0000")

    Log(exchange.GetPosition())
    info = $.CoverLong(exchange, "quarter", 30)
    Log(exchange.GetPosition())
    Log(info, "#FF0000")

    info = $.CoverLong(exchange, "quarter", 80)
    Log(exchange.GetPosition())
    Log(info, "#FF0000")
}

نمونہ کا پتہ:https://www.fmz.com/strategy/203258

ٹیمپلیٹ انٹرفیس کو بلانے کا طریقہ بالکل اسی طرح ہے$.OpenLongاور$.CoverLongمیںmainاوپر کی تقریب.

ٹیمپلیٹ ایک بیٹا ورژن ہے، کسی بھی تجاویز کا خیر مقدم کر رہے ہیں، میں پوزیشن کے اعداد و شمار میں تاخیر کے مسئلے سے نمٹنے کے لئے بہتر بنانے کے لئے جاری رکھیں گے.


متعلقہ

مزید