22 অক্টোবর, 2026 · ডেটা

ডেটা সরবরাহকারী তার ইতিহাস বদলানোর পর আমরা ব্যাকটেস্টটি নতুন করে তৈরি করেছি

ডেটা সরবরাহকারী তার ইতিহাস বদলানোর পর আমরা ব্যাকটেস্টটি নতুন করে তৈরি করেছি

ব্যাকটেস্ট চালানোর ছয় সপ্তাহ পর একই কোড, কনফিগারেশন ও তারিখের পরিসর দিয়ে সেটি আবার চালালাম। শেষের ইকুইটি ছিল আলাদা। খুব বেশি আলাদা নয়, তবে Sharpe অনুপাত 1.31 থেকে 1.08-এ নামানোর এবং কোন প্যারামিটার সেটটি সেরা দেখাচ্ছে তা বদলে দেওয়ার মতো যথেষ্ট।

স্ট্র্যাটেজি বদলায়নি। বদলেছিল ঐতিহাসিক ডেটা। সরবরাহকারী কয়েক দিনের ট্রেড ও বার সংশোধন করেছিল, আর আমাদের প্রথম রানটি সুনির্দিষ্ট ইনপুট স্ন্যাপশট সংরক্ষণ করেনি। পরের কয়েক দিন আমরা বোঝার চেষ্টা করেছি, নতুন ফলাফলটি ডেটা সংশোধনের কারণে এসেছে, পাইপলাইনের বাগ থেকে, নাকি এমন গবেষণা-প্রক্রিয়ার কারণে এসেছে যা আমরা পুনরুৎপাদন করতে পারি না।

সোমবার: আবার চালানো ফলের সঙ্গে মিলল না

প্রথম ইঙ্গিতটি ছিল একটি তরল স্পট পেয়ারে ছোট্ট একটি ব্যবধান। আমাদের আগের বারে সর্বোচ্চ দাম ছিল 62,418। আবার চালানোর পর দেখা গেল 62,431। প্রথমে পার্থক্যটি তেমন গুরুত্বপূর্ণ মনে হয়নি, যতক্ষণ না স্ট্র্যাটেজির এন্ট্রি খতিয়ে দেখলাম: এর থ্রেশহোল্ড এই দুই দামের মাঝখানে ছিল। কয়েকটি বার বদলানোর অর্থ ছিল সিগন্যাল বদলানো, আর তার ফলে কয়েক দিন পরের পজিশনও বদলে যাওয়া।

আমরা দৈনিক ট্রেডের সংখ্যা মিলিয়ে দেখলাম, অমিলটি শুরু হয়েছে একটি নির্দিষ্ট তারিখে। এরপর সেই তারিখের জন্য ব্যবহৃত কাঁচা রো-গুলো তুলনা করলাম। সরবরাহকারীর বর্তমান রেসপন্সে কয়েকটি সংশোধিত ট্রেড ও একটি সংশোধিত অ্যাগ্রিগেট বার ছিল। আমরা যে রেসপন্সটি ব্যবহার করেছিলাম, তার সঙ্গে কোনো পরিবর্তন-তালিকা দেওয়া ছিল না।

ডেটার ক্ষেত্রে এমনটা স্বাভাবিক। এক্সচেঞ্জ রেকর্ড সংশোধন করে; সরবরাহকারীরা ফাঁক পূরণ করে, ভুল প্রিন্ট ঠিক করে এবং অ্যাগ্রিগেশনের নিয়ম বদলায়। “জানুয়ারির ডেটা” চাইলেও মার্চে ভিন্ন ফল আসতে পারে।

মঙ্গলবার: হারানো রসিদটি খুঁজে পেলাম

রানের রেকর্ডে সরবরাহকারীর নাম, সিম্বল ও তারিখের পরিসর রেখেছিলাম। কিন্তু রেসপন্সটি বা প্রতিটি ইনপুট পার্টিশনের কনটেন্ট হ্যাশ রাখিনি। তাই আমরা কী চেয়েছিলাম, তা প্রমাণ করতে পারতাম; কিন্তু সরবরাহকারী ঠিক কোন বাইট পাঠিয়েছিল, তা নয়।

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

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

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

বুধবার: সংশোধনে বদলে গেল ফলের ব্যাখ্যা

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

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

বৃহস্পতিবার: গবেষণার রেকর্ড বদলালাম

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

স্টোরেজ বা লাইসেন্সের নিয়মে কাঁচা ডেটা রেখে দেওয়া সম্ভব না হলে, শর্ত যতটা অনুমতি দেয় ততটাই শক্ত প্রমাণ রাখি: হ্যাশ, অনুরোধের প্যারামিটার, উৎসের সংস্করণ শনাক্তকারী এবং সমস্যার কারণ খুঁজতে পার্স করা রো-র একটি ছোট নমুনা। হ্যাশ দিয়ে ডেটা ফিরে পাওয়া যায় না, তবে দুটি রান অভিন্ন বাইট ব্যবহার করেনি কি না তা বোঝা যায়।

পুনরুৎপাদনযোগ্য ব্যাকটেস্টের জন্য শুধু ডেটা URL নয়, ইনপুটের পরিচয়ও দরকার। কী এসেছে, কখন এসেছে এবং আপনার স্ট্র্যাটেজির ব্যবহৃত রো-তে কীভাবে রূপান্তরিত হয়েছে—সব নথিভুক্ত করুন।

শুক্রবার: পরের বার আমরা যা বাদ দেব

শুধু সারসংক্ষেপের মেট্রিক তুলনা করা বাদ দেব। Sharpe বদলেছে মানে কিছু একটা বদলেছে; কিন্তু কারণটা কোথায়, তা এতে ধরা পড়ে না। প্রথমে রো-র সংখ্যা ও পার্টিশন হ্যাশ দেখুন, তারপর ইনপুটের কোন তারিখে প্রথম অমিল হয়েছে তা খুঁজুন। সেখান থেকে এই ক্রমে রূপান্তরিত রো, সিগন্যাল, অর্ডার এবং ফিল তুলনা করুন।

সংশোধিত ইতিহাস দিয়ে পুরোনো ডেটা নিঃশব্দে প্রতিস্থাপন করাও বাদ দেব। সংশোধন কাজে লাগে, তবে পুরোনো রানগুলো তাদের আসল ইনপুটের সঙ্গেই যুক্ত থাকা উচিত। নতুন ডেটাসেটের জন্য নতুন রান তৈরি হওয়া উচিত, এবং পুরোনোটির সঙ্গে তার সম্পর্ক স্পষ্টভাবে দেখানো উচিত।

এখন আমাদের ব্যবহারিক নিয়মটি সহজ: কোনো রান যদি একটি পরীক্ষা পুনরুৎপাদনের জন্য হয়, ডেটা স্ন্যাপশট নির্দিষ্ট করে দিন। আর সংশোধিত ইতিহাস কাজে লাগানোর জন্য হলে, সেটিকে নতুন পরীক্ষা হিসেবে চিহ্নিত করুন। এই পার্থক্য বুঝতে আমাদের কয়েক দিন লেগেছিল; এখন রান ম্যানিফেস্টে তা এক লাইনের বিষয়।

বাজারের ডেটাব্যাকটেস্টিংডেটা ইঞ্জিনিয়ারিংপুনরুৎপাদনযোগ্যতা
শেয়ার করুনXLinkedInFacebookRedditHacker NewsWhatsAppTelegramEmail
← সব পোস্ট