4 সেপ্টেম্বর, 2026 · ব্যাকটেস্টিং

একই বারের ভেতরে আপনার স্টপ ও টার্গেট—ব্যাকটেস্ট কোনটিকে বেছে নিল?

একই বারের ভেতরে আপনার স্টপ ও টার্গেট—ব্যাকটেস্ট কোনটিকে বেছে নিল?

84,120 থেকে লং পজিশন। স্টপ 84,036-এ, টার্গেট 84,271-এ। পরের মিনিটের বারটি এলো: ওপেন 84,118, হাই 84,290, লো 84,010, ক্লোজ 84,240।

দুটি লেভেলই বারের ভেতরে। স্টপেও দাম লেগেছে, টার্গেটেও লেগেছে; আর OHLC-র 4টি সংখ্যায় কোনটি আগে ঘটেছে সে বিষয়ে একেবারেই কোনো তথ্য নেই। তবু আপনার ব্যাকটেস্ট একটি ফল দিয়েছে। লুপের কোথাও একটি লাইন সিদ্ধান্ত নিয়েছে—সম্ভবত এমন একটি লাইন, যেটি লেখার সময় আপনি মডেলিংয়ের অনুমান বলে ভাবেননি।

স্বল্প-মেয়াদি কৌশলে কৃত্রিম পারফরম্যান্সের সবচেয়ে বড় উৎস হিসেবে আমি এটিই দেখি—ফি ও স্লিপেজেরও আগে—কারণ এটিকে অনুমান বলে মনে হয় না। মনে হয় নিছক কোডের সংযোগ।

ভুল পদ্ধতি 1: if-চেইনকে সিদ্ধান্ত নিতে দেওয়া

সাধারণত কোডটা এমন হয়:

if bar.high >= target:
    exit(target, "tp")
elif bar.low <= stop:
    exit(stop, "sl")

কেউই ঠিক করেনি, “টার্গেট আগে কার্যকর হবে।” টার্গেটের শর্তটাই আগে লেখা হয়েছে, কারণ সেটাই প্রত্যাশিত পথ, আর লেখার সময় সেটিই আপনার মাথায় ছিল। দুই branch-এর ক্রম উল্টে দিলেই ইকুইটি কার্ভ বদলে যায়; এতেই বোঝা উচিত, আপনার P&L-এর একটা অংশ নির্ভর করছে কোড এডিটরে আপনি কীভাবে লিখেছেন তার ওপর।

BTCUSDT perp-এ ইচ্ছা করেই সাধারণ একটি mean-reversion scalper চালিয়েছিলাম: 1-মিনিটের বারে 3 মাস, 4,812টি ট্রেড, এন্ট্রি থেকে 0.10% স্টপ এবং 0.18% টার্গেট। সিগন্যাল একই, ফি একই—শুধু টাই-ব্রেকের নিয়ম বদলেছে।

12.6%ট্রেডে একই বারে দুই লেভেলেই দাম লেগেছে
2.31Sharpe, টার্গেট আগে কার্যকর
0.18Sharpe, স্টপ আগে কার্যকর
0.94Sharpe, 1-সেকেন্ডের বারে নিষ্পত্তি

ট্রেডের এক-অষ্টমাংশই পুরো ফল নির্ধারণ করছে। টাইট স্টপ-টার্গেট জুটির অঙ্কটা এমনই: যেসব ট্রেডে দাম দুই দিকেই গেছে, অর্থাৎ সবচেয়ে গুরুত্বপূর্ণ ট্রেডগুলোতেই অস্পষ্টতা থাকে; আর কয়েন-টসের ফল অনুযায়ী প্রতিটি ট্রেডে স্টপ থেকে টার্গেট পর্যন্ত পুরো ব্যবধানের প্রভাব পড়ে। ট্রেডের 12.6% × ব্যবধানের 0.28% = নমুনার প্রতি একক হিসাবে মোট নোশনাল টার্নওভারের 3.5%, যা কৌশলটির প্রকৃত এজের চেয়ে অনেক বড়।

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

বারের সময়সীমাএকই বারে দুই লেভেল থাকা ট্রেডSharpe (টার্গেট আগে)
1s0.3%0.91
1m12.6%2.31
5m34%3.60
15m49%4.42
1h71%5.88

টেবিলটি আসলে কী বলছে, তা দেখুন। মোটা বারে ব্যাকটেস্টের ফল ভালো হয়েছে। প্রত্যেক গবেষকের ধারণা, ঘণ্টাভিত্তিক বারই বেশি রক্ষণশীল—কম নয়েজ, মাইক্রোস্ট্রাকচারে কম ওভারফিটিং। কিন্তু ইন্ট্রাবার নিয়মে যদি নিজের পক্ষে ফল মেলে, মোটা বার মানে শুধু আরও বড় বাক্স, যার ভেতরে ধরে নেওয়া যায় যে আপনি ভাগ্যবান ছিলেন। 1h বারে 10টির মধ্যে 7টি ট্রেডের ফল নিছক নিয়মের ওপর নির্ভরশীল। সেই ব্যাকটেস্ট কোনো কৌশল যাচাই করছে না; 3,400 বার দুটি `if` স্টেটমেন্টের ক্রম পরীক্ষা করছে।

ভুল পদ্ধতি 2: ধরে নেওয়া, স্টপের দামেই স্টপ পূরণ হয়েছে

ধরা যাক, আপনি ক্রম ঠিক করলেন। স্টপ আগে কার্যকর হলো, ঠিক 0.10% লোকসান আর taker fee হিসাব করলেন, এবং ভাবলেন কাজটা নির্ভুল হয়েছে। তবু 2টি বিষয় ভুল রয়ে গেছে।

প্রথমত, স্টপ হলো ট্রিগার, ফিল নয়। Binance USDⓈ-M-এ STOP_MARKET অর্ডারের শর্ত পূরণ হলেই সেটি মার্কেট অর্ডারে পরিণত হয়, তারপর অর্ডারবুকে যা আছে তা নিয়ে ফিল হয়। শান্ত মিনিটে এতে এক-দুই টিক স্লিপেজ হয়। কিন্তু যে মিনিটে সত্যিই আপনার স্টপ ট্রিগার হয়েছে—40-পয়েন্টের ক্যান্ডেল বডি আর নিচে লিকুইডেশনের ধসসহ সেই মিনিটে—আপনি যে পাশে অর্ডার মেলাচ্ছেন, অর্ডারবুক ঠিক সেখানেই পাতলা থাকে। আমার নমুনায় টিক টেপের সঙ্গে স্টপ ট্রিগার মিলিয়ে দেখেছি: ফিলের মধ্যক ট্রিগারের চেয়ে 1.4 bps খারাপ, আর 95তম পার্সেন্টাইল 11 bps। 10 bps স্টপে, টেইল রিস্কের যে মাত্রা ভেবেছিলেন, তার আরও এক-দশমাংশ খরচ করায়।

দ্বিতীয় বিষয়টি সূক্ষ্ম এবং perps-নির্দিষ্ট: কোন দাম স্টপ ট্রিগার করে। Binance-এ স্টপ অর্ডারের ডিফল্ট ট্রিগার হলো mark price; এটি ইনডেক্স ও স্মুথ করা basis থেকে তৈরি, ওই ভেন্যুর শেষ ট্রেড থেকে নয়। আপনার OHLC সিরিজ হলো last price। দুটো আলাদা সিরিজ, আর ঠিক যে ঘটনাগুলো স্টপ ট্রিগার করে, সেগুলোর সময়ই এদের পার্থক্য সবচেয়ে বেশি হয়।

Last price (আপনার klines)Mark price (ডিফল্ট ট্রিগার)
উৎসএই ভেন্যুর ট্রেডএকাধিক ভেন্যুর ইনডেক্স + basis
উইকের আচরণপুরো ওঠানামাঅনেকটাই মসৃণ
সাধারণ বিচ্যুতিশান্ত সময়ে 1–3 bps, ধসের মিনিটে 20–35 bps
ব্যাকটেস্টে প্রভাবযেসব স্টপ কার্যকর হওয়ার কথা ছিল না, সেগুলো কার্যকর দেখায়—এবং উল্টোটাও ঘটে

তাই last-price টেপে 25 bps-এর উইক ব্যাকটেস্টে আপনাকে স্টপ-আউট করাতে পারে, যদিও live mark price আপনার ট্রিগারের 10 bps-এর মধ্যেও আসেনি। আবার উল্টোটাও হতে পারে, যেদিন ইনডেক্স নড়ে আর আপনার ভেন্যু পিছিয়ে থাকে। workingTypeকে CONTRACT_PRICE সেট করলে অন্তত লাইভ আচরণ আপনার ডেটার সঙ্গে মেলে; গবেষকের জন্য সাধারণত এটাই ঠিক সিদ্ধান্ত, কারণ mark-price ট্রিগার সৎভাবে সিমুলেট করতে হলে পুরো fill engine জুড়ে দ্বিতীয় একটি সিরিজ রাখতে হয়।

এর যে উদাহরণটা আমার সবচেয়ে ভালো মনে আছে: আমাদের দলের একজন 0.18% থেকে 0.21%-এ টেক-প্রফিট সরিয়ে কৌশলটিকে “উন্নত” করেছিলেন। Sharpe 2.3 থেকে 3.1-এ উঠেছিল। নতুন কোনো এজ আসেনি। টার্গেটটি শুধু 1-মিনিটের উইক বণ্টনের ঘন অংশের বাইরে চলে গিয়েছিল, তাই কম ট্রেড অস্পষ্টতার সেই ভাগে পড়েছিল, যেখানে কোড চুপিসারে সেগুলোকে জয়ী দেখাচ্ছিল। তিনি টাই-ব্রেকার অপ্টিমাইজ করেছিলেন।

ভুল পদ্ধতি 3: সব সময় সবচেয়ে খারাপটা ধরে নিয়ে তাকে রক্ষণশীলতা বলা

তাৎক্ষণিক সমাধানটা হলো হতাশাবাদী হওয়া। দুই লেভেলেই দাম লাগলে স্টপ ধরে নিন। হয়ে গেল, আর আশাবাদ নেই, এবার চালু করুন।

আগে আমিও এটাই করতাম। বিকল্পটির চেয়ে ভালো, তবু ভুল—2টি কারণে।

এতে ভালো কৌশলও বাদ পড়ে যায়। 12.6% ট্রেডে হতাশাবাদী নিষ্পত্তি এই কৌশলের Sharpe-কে টিক-ভিত্তিক 0.94-এর তুলনায় 2.1 পয়েন্ট কমিয়েছে। প্রকৃত মান যদি 0.94 হয় আর আপনার নিয়মে 0.18 দেখায়, তাহলে ধারণাটা ছুড়ে ফেলে আরও খারাপ কিছু নিয়ে কাজ শুরু করবেন। 2 Sharpe পয়েন্টের ভুল রক্ষণশীলতা নয়; নৈতিকতার ভঙ্গি নেওয়া নয়েজ।

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

অন্য সবকিছুর আগে আমরা এই সহজ নিয়মটি মানি: stop_distance + target_distanceযদি আপনার বারের সময়সীমার 75তম পার্সেন্টাইল রেঞ্জের চেয়ে ছোট হয়, তাহলে আপনার ইন্ট্রাবার অনুমানের প্রভাব P&L-এ সিগন্যালের চেয়েও বেশি। দুটি সংখ্যাই হিসাব করুন। 4 লাইনেই হয়ে যায়, আর অন্য যেকোনো একক পরীক্ষার চেয়ে বেশি কৌশল পর্যালোচনার ইতি টেনেছে এটি।

যা সত্যিই কাজে দেয়

বারের ভেতরের পথও ডেটা। সংগ্রহ করুন, আর যা সংগ্রহ করতে পারবেন না তার সীমা নির্ধারণ করুন।

  1. আপনার কাছে থাকা সবচেয়ে সূক্ষ্ম সিরিজে নিষ্পত্তি করুন। প্রাসঙ্গিক মিনিটগুলোর Binance aggTrades-এ কয়েকশো সারিই যথেষ্ট, আর তাতেই প্রশ্নের সরাসরি উত্তর মেলে: কোন লেভেলে আগে দাম লেগেছে, এবং সুইপটি কোন দামে ফিল হয়েছে। পুরো ব্যাকটেস্টে টিক ডেটা লাগবে না; শুধু অস্পষ্ট বারগুলোর জন্য দরকার। আমার নমুনায় 129,600 মিনিটের মধ্যে এমন ছিল 606টি। ডাউনলোডটা ছোট, অবকাঠামোগত প্রকল্প নয়।
  2. টিক ডেটা না পেলে, শুধু নিষ্পত্তির জন্য এক বা দুই ধাপ ছোট টাইমফ্রেম নিন। সিগন্যাল 15m-এ, এক্সিটের নিষ্পত্তি 1s বা 1m বারে। অস্পষ্টতা 49% থেকে নেমে এক শতাংশের ভগ্নাংশে আসে, আর যা অবশিষ্ট থাকে তা সততার সঙ্গে উপেক্ষা করার মতো সামান্য।
  3. সব সময় ফলের সীমা জানান। প্রতিটি ব্যাকটেস্ট 2 বার চালান—আশাবাদী ও হতাশাবাদী নিষ্পত্তিতে—এবং নিষ্পত্তি করা ফলের পাশাপাশি দুই Sharpe-ই দেখান। এই ব্যবধানই আপনার ইন্ট্রাবার অনিশ্চয়তা; Sharpe-এর জন্য যে confidence interval দেখান, তার পাশেই tear sheet-এ এটি থাকা উচিত। সীমা যখন 0.2–2.3, তখন তার ভেতরের কোনো সিদ্ধান্তই বাস্তব নয়।
  4. অস্পষ্টতার হারকে একটি প্রধান মেট্রিক হিসেবে ট্র্যাক করুন। আমাদের প্রতিটি কৌশল কার্ডের ওপরে থাকে এটি, ট্রেডের সংখ্যা ও টার্নওভারের পাশে। হার প্রায় 5%-এর বেশি হলে পরীক্ষাধীন বিষয়টি এন্ট্রি লজিক নয়, এক্সিট লজিক।
  5. ট্রিগার আর ফিল আলাদাভাবে মডেল করুন। ভেন্যু যে দামের সিরিজ ব্যবহার করে, সেটিতে ট্রিগার করুন; টেপ থেকে ক্যালিব্রেট করা স্লিপেজ ড্র যোগ করে ফিল ধরুন, ট্রিগার দামে নয়।

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

এগুলোর কোনোটাই দুর্বোধ্য বিষয় নয়। বুঝতে হবে, একটি বার হলো সারাংশ; আর স্টপ-টার্গেট কৌশল বাজি ধরে এমন ঘটনার ক্রমের ওপর, যা সেই সারাংশে বাদ পড়েছে। পেপার-ট্রেডিং ইঞ্জিন যখন লাইভ টেপে কৌশলটি চালায়, টেপের সেই ক্রম নিয়ে নিজস্ব মত থাকে—আর আপনি if-স্টেটমেন্টের কোন branch আগে লিখেছেন, তা নিয়ে টেপের কোনো দিনই মাথাব্যথা ছিল না।

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