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

ক্রিপ্টোকারেন্সি ফিউচার ট্রেডিং এর যুক্তি

লেখক:ভাল, তৈরিঃ 2020-07-18 13:31:34, আপডেটঃ 2023-10-26 20:05:28

img

সমস্যাপূর্ণ দৃশ্য

দীর্ঘদিন ধরে, ক্রিপ্টোকারেন্সি এক্সচেঞ্জের এপিআই ইন্টারফেসের ডেটা বিলম্ব সমস্যা আমাকে সবসময় বিরক্ত করেছে। আমি এটি মোকাবেলার জন্য একটি উপযুক্ত উপায় খুঁজে পাইনি। আমি এই সমস্যার দৃশ্য পুনরুত্পাদন করব।

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

সমস্যা এই অবস্থান তথ্যে রয়েছে. যদি অর্ডার বন্ধ করা হয়, বিনিময় অবস্থান তথ্য ইন্টারফেস দ্বারা ফিরে তথ্য (অর্থাৎ বিনিময় ইন্টারফেস যে নিচের স্তর আসলে অ্যাক্সেস যখন আমরা কলexchange.GetPosition) নতুন খোলা পজিশনের তথ্য থাকতে হবে, কিন্তু যদি এক্সচেঞ্জ দ্বারা ফেরত দেওয়া ডেটা পুরানো তথ্য হয়, অর্থাৎ লেনদেন শেষ হওয়ার আগে অর্ডারটির অবস্থান তথ্য, এটি একটি সমস্যা সৃষ্টি করবে।

ট্রেডিং লজিকটি বিবেচনা করতে পারে যে অর্ডারটি পূরণ করা হয়নি এবং অর্ডারটি স্থাপন করা চালিয়ে যেতে পারে। তবে, এক্সচেঞ্জের অর্ডার স্থানান্তর ইন্টারফেসটি বিলম্বিত হয় না, তবে লেনদেনটি দ্রুত হয় এবং অর্ডারটি কার্যকর হয়। এটি একটি গুরুতর পরিণতি সৃষ্টি করবে যে কৌশলটি একটি অবস্থান খোলার অপারেশনটি ট্রিগার করার সময় বারবার অর্ডার স্থাপন করবে।

বাস্তব অভিজ্ঞতা

এই সমস্যার কারণে, আমি একটি দীর্ঘ অবস্থান পূরণ করার কৌশল দেখেছি পাগল, সৌভাগ্যবশত, বাজারে সেই সময়ে উত্থিত হয়েছিল, এবং ভাসমান মুনাফা একবার 10BTC অতিক্রম করেছে। সৌভাগ্যবশত, বাজার আকাশ ছোঁয়া হয়েছে। যদি এটি একটি পতন হয়, শেষ কল্পনা করা যেতে পারে।

সমাধান করার চেষ্টা করুন

  • ১ম পরিকল্পনা

অর্ডার স্থানান্তরের যুক্তিটি কেবলমাত্র একটি অর্ডার দেওয়ার কৌশলটির জন্য ডিজাইন করা সম্ভব। অর্ডার স্থানান্তর মূল্য সেই সময়ে প্রতিপক্ষের দামের দামের ব্যবধানের জন্য একটি বড় স্লিপিং, এবং প্রতিপক্ষের অর্ডারগুলির একটি নির্দিষ্ট গভীরতা কার্যকর করা যেতে পারে। এর সুবিধা হ'ল কেবলমাত্র একটি অর্ডার স্থাপন করা হয়, এবং এটি অবস্থানের তথ্যের ভিত্তিতে বিচার করা হয় না। এটি পুনরাবৃত্তি অর্ডার দেওয়ার সমস্যা এড়াতে পারে, তবে কখনও কখনও যখন দামের পরিবর্তন তুলনামূলকভাবে বড় হয়, তখন অর্ডারটি এক্সচেঞ্জের দামের সীমা প্রক্রিয়াটি ট্রিগার করবে এবং এর ফলে বড় স্লিপিং অর্ডারটি এখনও সম্পন্ন হয়নি এবং ট্রেডিং সুযোগটি মিস করে।

  • প্ল্যান ২

এক্সচেঞ্জের বাজার মূল্য ফাংশন ব্যবহার করে, এফএমজেডের মূল্য পাস -1 হল বাজার মূল্য। বর্তমানে, ওকেএক্স ফিউচার ইন্টারফেসটি বাজার মূল্য সমর্থন করার জন্য আপগ্রেড করা হয়েছে।

  • প্ল্যান ৩

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

প্ল্যান ৩ এর উপর ভিত্তি করে ডিজাইন

// 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উপরে ফাংশন।

টেমপ্লেটটি একটি বিটা সংস্করণ, যে কোন পরামর্শ স্বাগত জানানো হয়, আমি অবস্থান তথ্য বিলম্ব সমস্যা মোকাবেলা করার জন্য অপ্টিমাইজ করা চালিয়ে যাবে.


সম্পর্কিত

আরো