2 সেপ্টেম্বর, 2026 · মাইক্রোস্ট্রাকচার

আপনার লিমিট অর্ডারটি পূরণ হয়নি: কিউ পজিশন, maker ব্যাকটেস্ট আর আপনার বানানো Sharpe নিয়ে একটি চিঠি

আপনার লিমিট অর্ডারটি পূরণ হয়নি: কিউ পজিশন, maker ব্যাকটেস্ট আর আপনার বানানো Sharpe নিয়ে একটি চিঠি

গত সপ্তাহে আপনি নোটবুকটা পাঠিয়েছিলেন: একই সিগন্যাল, একই ইউনিভার্স, BTCUSDT perp-এর একই 14 মাসের ডেটা। বদলেছিল শুধু execution। আপনি spread পার হয়ে অর্ডার দেওয়া বন্ধ করে এক tick ভেতরে bid রেখে দিলেন, আর Sharpe 0.42 থেকে বেড়ে 2.14 হলো। আপনি জানতে চেয়েছিলেন, ফলটা সত্যি কি না, নাকি আপনি কিছু একটা ভেঙে ফেলেছেন।

আপনি কিছু একটা ভেঙেছেন। ঠিক কোথায়, সেটা আপনাকে দেখাতে চাই, কারণ bug-টা এক লাইনের, আর এর পেছনের শিক্ষাটা ওই লাইনের চেয়ে অনেক বড়।

আপনার fill rule-টা আপনার engine থেকে হুবহু তুলে দিচ্ছি:

if bar.low <= limit_price: fill(limit_price)

এর মানে: এই মিনিটে বাজারে আমার দামের সমান বা তার নিচে কোনো trade হলে, আমার অর্ডার আমার দামেই পূরণ হয়েছে। কিন্তু আসলে এতে বলা হয়েছে, দাম আপনার স্তর ছুঁয়েছে। ছোঁয়া আর অর্ডার পূরণ হওয়া এক জিনিস নয়। এ দুটির মাঝে একটা কিউ আছে, আর আপনি সেটাকে ফাঁকা ধরে মডেল করেছেন।

আপনার সামনে কী আছে

BTCUSDT perp-এ 84,120.0 দামে bid দিলে, সেখানে আগে থেকে থাকা সব অর্ডারের পেছনে আপনার অর্ডার যোগ হয়। ওই কন্ট্রাক্টের top-of-book স্তরে দিনের সময় অনুযায়ী সাধারণত 4 থেকে 30 BTC পর্যন্ত অর্ডার থাকে; আপনার নমুনা সময়সীমায় মধ্যক প্রায় 12 BTC। আপনার অর্ডার 0.4 BTC। আপনার trade হতে হলে, আপনার আগে আসা সবার অর্ডার সরানোর মতো মোট পরিমাণে বিক্রেতাদের ওই স্তরে আঘাত করতে হবে, এবং স্তরটি আপনার নিচ থেকে বাতিল হয়ে যাওয়ার বা বাজার দাম বাড়িয়ে সরে যাওয়ার আগেই তা করতে হবে।

তাই আপনার ব্যাকটেস্টের প্রশ্নটা “দাম কি 84,120.0-এ পৌঁছেছিল?” নয়, বরং “আমার অর্ডার সেখানে থাকা অবস্থায় 84,120.0 দামে অন্তত 12.4 BTC পরিমাণ market sell execute হয়েছিল কি?” এই দুই ঘটনা একেবারেই আলাদা। আপনার ডেটায় এদের ঘটনার সংখ্যা প্রায় তিনগুণ আলাদা।

12.4 BTCদাম ছোঁয়ার সময় আপনার সামনে থাকা মধ্যক পরিমাণ
100%আপনার ব্যাকটেস্ট ধরে নেওয়া fill rate
31%আপনার কিউ সরাতে পেরেছে এমন ছোঁয়ার হার
4,180trade, যা বাস্তবে প্রায় 1,300

তিনটি fill rule, তিনটি আলাদা কৌশল

একই entry ও তিনটি execution model দিয়ে আপনার সিগন্যাল আবার চালিয়েছি। একই alpha, একই fee, একই funding। বদলেছে শুধু fill logic।

Fill ruleFill-এর সংখ্যাFill-এর পর গড় 60s edgeSharpe
Touch: low <= limit4,180+2.6 bp2.14
দামের ভেতর দিয়ে যাওয়া: low < limit - 1 tick1,712+0.4 bp0.61
স্তরভিত্তিক ভলিউম কিউ সিম1,306+0.9 bp0.77

মাঝের সারিটি হলো সেই মোটামুটি সমাধান, যা সবাই প্রথমে চেষ্টা করে: বাজার আপনার দাম পেরিয়ে trade করলেই শুধু fill ধরুন—যুক্তিটা হলো, দাম আপনার ওপারে গেলে নিশ্চয়ই আপনাকে সরিয়ে দিয়েছে। দিকটা ঠিক, আর এতে কল্পনার বেশির ভাগই বাদ পড়ে। তবে এরও একটা বড় পক্ষপাত আছে, সে প্রসঙ্গে পরে আসছি।

নিচের সারির মডেলটাই আপনার তৈরি করা উচিত। এর জন্য L3 feed বা প্রতিটি অর্ডারের পুনর্গঠন দরকার নেই। এর বেশির ভাগ উপকরণ আপনার হাতেই আছে।

aggTrades থেকে তৈরি করা যায় এমন কিউ সিম

ক্লাইনসের বদলে aggregate trade stream নিন। প্রতিটি trade-এ থাকে দাম, পরিমাণ, timestamp এবং maker-side flag, যা বলে দেয় aggressor কিনছিল নাকি বিক্রি করছিল। আপনার নিজস্ব passive order-এর কার্যকর সিমুলেশন করতে এটুকুই যথেষ্ট:

  1. আপনার অর্ডার দেওয়ার সময় ওই দামে থাকা মোট অর্ডারের পরিমাণের snapshot নিন। আপনার কাছে যদি শুধু 100ms book feed থাকে, সর্বশেষ snapshot ব্যবহার করুন; যে ভুলটা ঠিক করছেন, তার তুলনায় এ ভুল সামান্য।
  2. সেট করুন queue_ahead = resting_size। সতর্ক থাকুন, ধরে নিন আপনি সবার শেষে আছেন। স্তরটি আপনিই তৈরি না করলে, আপনি সেখানেই থাকবেন।
  3. trade stream ধরে এগোন। আপনার দামে বা তার নিচে প্রতিটি sell-aggressor trade-এর পরিমাণ দিয়ে queue_ahead কমান। পরিমাণ শূন্যের নিচে নামলেই, ওই timestamp-এ আপনার অর্ডার আপনার দামেই পূরণ হয়েছে।
  4. দাম এক tick সরে গেলে কিউ আবার শূন্য করবেন না; ধীরে কমান। স্তরটি পুরোনো হয়ে গেলে আপনার সামনের কিছু অর্ডার বাতিল হয়, কিছু হয় না। touch-এর বাইরে পুরো এক সেকেন্ড থাকলে 30-40% কমানো—দুই চরমের যেকোনোটির চেয়ে আমার পুনর্গঠনের সঙ্গে ভালো মিলেছে।
  5. আপনার কৌশলে cancel করে আবার অর্ডার দেওয়ার কথা থাকলে, পুনরায় দেওয়া অর্ডারটিকে নতুন স্তরের পেছনে নতুন অর্ডার হিসেবে মডেল করুন। এই ধাপটাই অনেকে বাদ দেন, আর বাকি কল্পনার লুকোনোর জায়গা এটাই।

ধাপ 2 নিয়েই আপনি আমার সঙ্গে তর্ক করতে চাইবেন। হ্যাঁ, কখনো কখনো আপনি কিউয়ের সামনের দিকে থাকেন, কারণ স্তর তৈরি হওয়ার মুহূর্তেই অর্ডার দিয়েছিলেন। ঠিক আছে—এটা মেপে দেখুন, ধরে নেবেন না। অর্ডার দেওয়ার সময়ের resting size log করুন, আর আপনার কত অর্ডার সত্যিই শুরুতেই ছিল তা ডেটা থেকে বের করুন। আপনার কৌশলে তা ছিল 11%, কারণ কোনো মুভের পর আপনার সিগন্যাল আসে; অর্থাৎ আপনি যে স্তরে যোগ দিচ্ছেন, সেটি আগে থেকেই আছে এবং সেখানে ভিড়ও জমেছে।

আপনি যে fill পান, সেগুলোই না পেলেই ভালো হতো

এবার আসল গুরুত্বপূর্ণ অংশটি, আর যে কারণে দামের ভেতর দিয়ে যাওয়ার rule-টিতে পক্ষপাত আছে।

ভাবুন, কখন আপনার bid পুরোপুরি সরিয়ে ফেলা হয়। যখন বিক্রির চাপ এত বেশি হয় যে পুরো স্তরটি শেষ হয়ে যায়। অর্থাৎ, সংজ্ঞা অনুযায়ী, ঠিক তখনই বাজার আপনার দামের নিচ দিয়ে নামছে। যেসব fill সম্পর্কে আপনার সবচেয়ে বেশি নিশ্চয়তা আছে, সেগুলোতেই আপনি সঙ্গে সঙ্গে লোকসানের দিকে চলে যান।

fill কীভাবে হয়েছে, সেই অনুযায়ী ভাগ করুন এবং 60-সেকেন্ডের mark-out মাপুন:

Fill-এর ধরনFill-এর অনুপাত60s-এ mark-out
স্তরে trade হয়েছে, দাম ঘুরে ওপরে উঠেছে38%+3.1 bp
স্তরে trade হয়েছে, দাম স্থির21%+0.2 bp
দাম 2+ tick নিচ দিয়ে গেছে41%−2.4 bp

আপনার সাদামাটা ব্যাকটেস্ট তিনটি ভাগেরই সব fill দিয়েছে এবং সবকটিকে বিনা খরচের ধরে দাম বসিয়েছে। দামের ভেতর দিয়ে যাওয়ার rule-এ প্রায় শুধু তৃতীয় ভাগটিই থাকে, তাই এর edge কিউ সিমের তুলনায় আরও বেশি কমেছে। কোনোটিই ঠিক নয়। কিউ সিম আপনাকে বাস্তবসম্মত মিশ্রণ দেয়, আর খেলাটা পুরোটাই এই মিশ্রণের: passive execution আপনাকে spread আয় করতে দেয়, কিন্তু প্রতিকূল নির্বাচনের মূল্যও দিতে হয়। এই দুটির অনুপাতই আপনার প্রকৃত কৌশল।

ইকুইটিজ ডেস্কের পুরোনো ব্যাখ্যাটি এখনো খাটে: maker order হলো বাজারের কাছে বিক্রি করা একটি বিনামূল্যের option। যখন সেটি কারও লাভজনক মনে হয়, তখনই সে exercise করে। আপনার ব্যাকটেস্ট premium সংগ্রহ করেছে, কিন্তু option-এর payoff দিকটির কথা ভুলে গেছে।

যে trade-গুলো পাননি, সেগুলো শুধু খরচ নয়, কৌশলটাও বদলে দেয়

এই বিষয়টি নিয়েই আমি আপনাকে সবচেয়ে বেশি ভাবতে বলতে চাই। taker execution ভুলভাবে মডেল করলে, সঠিক trade-গুলোই ভুল দামে পান; fee ঠিক করলেই বেশির ভাগ সমস্যার সমাধান হয়। maker execution ভুলভাবে মডেল করলে, আপনার হাতে আসে একেবারেই ভুল trade-গুলোর সেট। আপনার 4,180টি entry-র প্রায় 2,900টিই ঘটেনি। সেগুলোর কিছু ছিল আপনার সেরা signal, এমন ক্যান্ডেলে যা হঠাৎ বেড়ে আবার উল্টে গেছে—ঠিক সেই পরিস্থিতি, যখন বাজার আপনাকে ছাড়াই এগিয়ে গেছে।

তাই fill না হওয়ার পর কৌশল কী করবে, তারও বাস্তবসম্মত logic দরকার। signal অকার্যকর হওয়ার সময় পর্যন্ত entry পূরণ না হলে কৌশল কী করে? spread আর impact দিয়ে taker order পাঠিয়ে পিছু নেয়? কম দামে আবার অর্ডার দিয়ে আলাদা entry basis মেনে নেয়? trade বাদ দিয়ে flat থাকে? প্রতিটি সিদ্ধান্তে equity curve উল্লেখযোগ্যভাবে বদলে যায়, আর কোনো সিদ্ধান্তের মানেই “ধরে নিন fill হয়েছে” নয়। আমাদের run-এ, সৎভাবে পিছু নেওয়ার rule যোগ করলে—20 seconds ধরে fill না হলে crossing, slippage সর্বোচ্চ 3 bp—বাদ পড়া trade-এর প্রায় এক-তৃতীয়াংশ ফিরে আসে এবং সাদামাটা Sharpe ও কিউ সিমের Sharpe-র ব্যবধানের প্রায় অর্ধেক পুষিয়ে যায়। ফলটা সত্যিই বেশ আগ্রহজাগানো, আর fill model যথেষ্ট বাস্তব হলেই কেবল প্রশ্নটার অর্থপূর্ণ উত্তর পাওয়া যায়।

10 মিনিটের সহজ যাচাই: একই সময়সীমায় আপনার live paper-trading log আর ব্যাকটেস্ট তুলনা করুন। PnL নয়, fill rate মেলান। ব্যাকটেস্ট যদি resting order-এর 100% পূরণ করে আর paper trading-এ হয় 34%, তাহলে আপনি কৌশল তুলনা করছেন না—fill model-এর bug দেখছেন। কোনো return-এর অঙ্ক দেখার আগে সেটা ঠিক করুন।

আরেকটু সময় নিয়ে আরও দুটি বিষয় বলি

Post-only reject। maker fee tier নিশ্চিত করতে post-only ব্যবহার করলে, আপনার সিদ্ধান্ত আর exchange-এর ack-এর মাঝখানে order book সরে যেতে পারে; তখন অর্ডারটি resting না থেকে reject হয়ে ফেরে। স্বাভাবিক সময়ে BTCUSDT-এ আমাদের paper log-এ এমন হয় 3-6% চেষ্টায়, আর US CPI প্রকাশের পরের মিনিটে 15%-এরও বেশি। reject হওয়া অর্ডার fill হয়নি, আবার resting অর্ডার হিসেবে অপূর্ণও থাকেনি; সেটি এমন trade, যা কখনো ঘটেইনি। আপনার ব্যাকটেস্টে এই অবস্থা না থাকলে, যেসব বাজার পরিস্থিতি আপনার কাছে সবচেয়ে গুরুত্বপূর্ণ, সেখানেই trade-এর সংখ্যা ফুলে-ফেঁপে উঠবে।

Self-trade prevention এবং আপনার নিজের footprint। 0.4 BTC-তে আপনি BTCUSDT-এর দাম নাড়াচ্ছেন না, তাই বিষয়টি বাদ দিন। তবে আপনি বলেছিলেন, এমন একটি mid-cap alt perp-এ এটি চালাতে চান যেখানে top-of-book-এর notional প্রায়ই $15k-এর নিচে থাকে। সেখানে আপনার অর্ডার কিউয়ের উল্লেখযোগ্য অংশ হয়ে ওঠে, আর আপনার নেওয়া snapshot-এ queue-ahead-এর হিসাবে আপনার আগের অর্ডারের প্রভাবও থাকে। আপনার size resting level-এর প্রায় 10%-এর বেশি হলেই, অন্যরা আপনাকে দেখে কীভাবে প্রতিক্রিয়া জানায়, সিমে তা ধরতে হবে। সত্যি বলতে, তখন আপনার বা আমার লেখা যেকোনো simulation-এর চেয়ে paper trading-কে বেশি বিশ্বাস করব।

কিউ সিম দিয়ে আবার চালিয়ে fill-এর ধরন অনুযায়ী ভাগ করা mark-out table পাঠান। bounce ভাগটিতে যদি এখনো edge-এর বেশির ভাগ থাকে এবং through ভাগটি যদি পুরোটা খেয়ে না ফেলে, তাহলে paper trading-এ পরীক্ষা করার মতো কিছু আপনার হাতে থাকতে পারে। আর পুরো ফলটাই যদি ওই 2,900টি fill-এর ওপর দাঁড়িয়ে থাকে, যেগুলো আপনি কখনোই পেতেন না, তাহলে নোটবুকের প্রতিশ্রুতি অনুযায়ী paper account কাজ না করার চার সপ্তাহ পর শেখার চেয়ে এখনই শেখা ভালো।

লিমিট অর্ডারকিউ পজিশনপ্রতিকূল নির্বাচনব্যাকটেস্টিংক্রিপ্টো ফিউচার্স
শেয়ার করুনXLinkedInFacebookRedditHacker NewsWhatsAppTelegramEmail
← সব পোস্ট