paint-brush
ফাইন্যান্সিয়াল টাইম সিরিজে অনুপস্থিত ডেটা নিয়ে কাজ করা - রেসিপি এবং ক্ষতিদ্বারা@vkirilin
12,407 পড়া
12,407 পড়া

ফাইন্যান্সিয়াল টাইম সিরিজে অনুপস্থিত ডেটা নিয়ে কাজ করা - রেসিপি এবং ক্ষতি

দ্বারা Vladimir Kirilin10m2024/04/03
Read on Terminal Reader

অতিদীর্ঘ; পড়তে

আমি আর্থিক সময় সিরিজে অনুপস্থিত ডেটা পরিচালনা করার পদ্ধতিগুলিতে ফোকাস করি। কিছু উদাহরণের ডেটা ব্যবহার করে আমি দেখাই যে LOCF সাধারণত ড্রপিং এবং ইম্প্যুটেশনের তুলনায় একটি শালীন গো-টু পদ্ধতি কিন্তু এর ত্রুটি রয়েছে - অর্থাৎ ডেটাতে কৃত্রিম অবাঞ্ছিত জাম্প তৈরি করতে পারে। যাইহোক, ইন্টারপোলেশনের মত বিকল্পগুলির নিজস্ব সমস্যা রয়েছে বিশেষ করে লাইভ ভবিষ্যদ্বাণী/পূর্বাভাসের প্রসঙ্গে।
featured image - ফাইন্যান্সিয়াল টাইম সিরিজে অনুপস্থিত ডেটা নিয়ে কাজ করা - রেসিপি এবং ক্ষতি
Vladimir Kirilin HackerNoon profile picture
0-item

আপনি যদি আমার মতো কিছু হন - আপনি অন্তত একবার আপনার ডেটাসেটে অনুপস্থিত ডেটা মোকাবেলা করেছেন। বা দুবার। অথবা একটি অনেক বার…


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


আমি সেগুলির মধ্যে কয়েকটি দেখব (নীচে তালিকাভুক্ত) এবং সুবিধা এবং অসুবিধাগুলি নিয়ে আলোচনা করব:


  1. ড্রপিং

  2. LOCF (শেষ পর্যবেক্ষণ এগিয়ে নিয়ে যাওয়া)

  3. গড় (বা অনুরূপ) অভিযোজন

  4. ইন্টারপোলেশন


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


দ্রষ্টব্য: যদি কেউ পেডেন্টিক হতে চায়, তবে 2-4 এর সমস্ত পদ্ধতিই কিছু অভিযোগের উদাহরণ।


মডেল ডেটা

আসুন কিছু উদাহরণ দিয়ে শুরু করা যাক কেন কেউ প্রথমে বাদ পড়ার বিষয়ে চিন্তা করবে। ব্যাখ্যা করার জন্য, আমি কিছু অতি-সরলীকৃত দৈনিক স্টক প্রাইস ডেটা তৈরি করেছি এই অনুমান করে যে এটি কোনও প্রবাহ ছাড়াই একটি এলোমেলো পথ অনুসরণ করে (অর্থাৎ গড় দীর্ঘমেয়াদী মূল্য স্থির থাকা উচিত) - সবচেয়ে সঠিক নয় তবে একটি সৌম্য অনুমান।


 np.random.seed(10) # needed for reproducibility price_moves = 3*pd.Series(np.random.randn(100)) # generating random "steps" with 0 mean price_vec = 100 + price_moves.cumsum() # generating brownian motion price_vec.plot() 


অপরিবর্তিত মূল্য সিরিজ


ওয়েল, প্লট বেশ ভাল অর্থ দেখায়.


ধরুন আমরা এখন দৈনিক মূল্যের পার্থক্যের অভিজ্ঞতামূলক গড় খুঁজে বের করতে চাই-

 price_vec.diff().mean() #sample mean >0.20030544816842052

স্পষ্টতই নন-জিরো, জেনারেটিং সিরিজের বিপরীতে - তবে এটি কেবল নমুনা শব্দ। এ পর্যন্ত সব ঠিকই.


ডাটা ড্রপিং

এখন কয়েকটি ডেটা পয়েন্ট মুছে দিয়ে এই ডেটাটিকে কিছুটা বিকৃত করা যাক:

 price_vec_na_simple = price_vec.copy() price_vec_na_simple.iloc[90:95] = np.array([np.NaN, np.NaN, np.NaN, np.NaN, np.NaN]) # price_vec_na_simple.diff().mean() >0.1433356258183252


আমরা এখনই কয়েকটি জিনিস লক্ষ্য করি -

  1. গড়টি একরকম অ-এনএ যদিও diff ভেক্টরে স্পষ্টভাবে এনএ থাকবে

  2. গড় আমরা আগে প্রাপ্ত এক থেকে ভিন্ন


এখন, #1 বেশ সহজ - pd.mean স্বয়ংক্রিয়ভাবে ডিফল্টরূপে NA মুছে ফেলুন।

কিন্তু #2 সম্পর্কে কি? আসুন আমরা কি কম্পিউট করছি তা পুনর্বিবেচনা করি।


এটা দেখানো সহজ যে অন্ততপক্ষে এনএ ছাড়া, গড় মূল্যের পার্থক্য কেবল হওয়া উচিত (price_vec[99]-price_vec[0])/99 - প্রকৃতপক্ষে, আমরা যখন দামের পার্থক্যগুলি যোগ করি, তখন সমস্ত "মধ্যবর্তী" অংশ বাতিল হয়ে যায়, যেমন (price_vec[1] - price_vec[0]) + (price_vec[2] - price_vec[1]) + .. !


এখন, অনুপস্থিত ডেটা ঢোকানোর সাথে, যদি আমরা প্রথমে পার্থক্য নিই এবং তারপর NA গুলি বাদ দেই, এই বাতিলকরণটি ভেঙে যায় - কিছু সহজ গণিত দেখায় যে আপনি এখন গণনা করছেন (price_vec[99] - price_vec[0] - price_vec[95] + price_vec[89])/93


এটি দেখানোর জন্য, লক্ষ্য করুন যে নিম্নলিখিত দুটি পদ এখন বাদ দেওয়া হয়েছে - price_vec[95] - price_vec[94] এবং price_vec[90] - price_vec[89] , যেহেতু (NA - any number) NA-তে মূল্যায়ন করে এবং তারপর বাদ দেওয়া হয়।


আসুন এটি যাচাই করি:

 (price_vec[99] - price_vec[0])/99 >0.20030544816842052 (price_vec[99] - price_vec[0] - price_vec[95] + price_vec[89])/93 >0.1433356258183252


এখন, এটা পরিষ্কার হয়ে গেছে যে আমরা কীভাবে জিনিসগুলি ঠিক করতে পারি - আমাদের প্রথমে এনএ ড্রপ করতে হবে এবং তারপরে diff -

 price_vec_na_simple.dropna().diff().mean() >0.21095999328376203


গড়টি যেখানে হওয়া উচিত সেখানে প্রায় ফিরে এসেছে - একটি ছোট অসঙ্গতি ঘটে কারণ আমাদের এখন গড়-এ কম পদ আছে - 99 এর পরিবর্তে 94৷


ঠিক আছে, মনে হচ্ছে যদি আমরা শুধুমাত্র গড় সম্পর্কে চিন্তা করি, আমরা ঠিক dropna ব্যবহার করে ঠিক আছি (যতক্ষণ আমরা এটি ঠিক করি)? সর্বোপরি, 0.2 এবং 0.21 এর মধ্যে পার্থক্যটি প্রথম স্থানে আমাদের শব্দ সহনশীলতার মধ্যে স্পষ্টভাবে রয়েছে। ঠিক আছে, পুরোপুরি না - আসুন দেখি কেন।


LOCF

LOCF কি?

LOCF এর অর্থ হল Last Observation Carried Forward। এর পিছনের ধারণাটি খুবই সহজ - যদি আমি কিছু সময়ের ব্যবধানে ডেটা রেকর্ড করি, তবে তা নিয়মিত হতেও পারে বা নাও হতে পারে, যদি কিছু নির্দিষ্ট ব্যবধানের পর্যবেক্ষণ অনুপস্থিত থাকে, আমরা কেবল ধরে নিই আমাদের ভেরিয়েবলের সাথে কিছুই পরিবর্তিত হয়নি এবং এটিকে শেষ অ-এর সাথে প্রতিস্থাপন করব। অনুপস্থিত মান (উদাহরণস্বরূপ - [3, 5, NA, 8] → [3, 5, 5, 8])। কেউ জিজ্ঞাসা করতে পারে - কেন একটি অনুপস্থিত পর্যবেক্ষণের সাথে একটি ব্যবধানের বিষয়ে প্রথমে যত্ন নেবেন, অর্থাৎ কেবল "ড্রপিং" পদ্ধতিতে এটি মুছে ফেলবেন না? ঠিক আছে, উত্তরটি "ড্রপিং" এর অন্তর্নিহিত ত্রুটির মধ্যে রয়েছে যা আমি উপরে উল্লেখ করিনি।


ধরুন আপনি একবারে একাধিক পরিমাণ রেকর্ড করেন, বিশেষ করে যেগুলি সাধারণত খুব দ্রুত পরিবর্তন হয় না - যেমন তাপমাত্রা এবং আর্দ্রতার প্রতি ঘণ্টায় রেকর্ডিং। ধরুন আপনার 10:00, 11:00 এবং 12:00-এর জন্য উভয় মানই আছে, কিন্তু শুধুমাত্র 13:00-এ আর্দ্রতা। আপনি কি শুধু সেই "সারি" মুছে ফেলবেন - অর্থাৎ 13:00 পর্যন্ত আপনার পড়া নেই? ঠিক আছে, আপনার কাছে দুটি ভেরিয়েবল থাকলে ঠিক আছে - যদিও আপনি কিছু সম্ভাব্য মূল্যবান তথ্য সরিয়েছেন (13:00 আর্দ্রতা)। কিন্তু আপনার যদি একবারে এরকম অনেক ঘটনা বা অনেকগুলি ভেরিয়েবল থাকে, তাহলে ড্রপ করলে আপনার কাছে কার্যত কোনো ডেটা থাকবে না!


একটি খুব আকর্ষণীয় বিকল্প হল শুধুমাত্র অনুমান করা যে 12:00 এবং 13:00 এর মধ্যে তাপমাত্রার জন্য কিছুই পরিবর্তিত হয়নি। সর্বোপরি, যদি কেউ আমাদের কাছে 12:30 এ এসে জিজ্ঞাসা করে - "বর্তমান তাপমাত্রা কত", আমরা সঠিকভাবে 12:00 রিডিং দিয়ে উত্তর দিতাম (যদি আমরা অবিলম্বে একটি নতুন রিডিং পেতে সক্ষম না হই, অবশ্যই ) কেন 13:00 মানের জন্য একই যুক্তি ব্যবহার করবেন না?


কেন LOCF (অর্থায়নে) ব্যবহার করবেন?

প্রথমে, আগে থেকে ডেটার উপর আমাদের নতুন-আবিষ্কৃত পদ্ধতি পরীক্ষা করা যাক:

 price_vec_na_simple.ffill().diff().mean() # ffill performs LOCF by default >0.20030544816842052


মনে হচ্ছে আমরা আমাদের পুরানো মান অবিকল পুনরুদ্ধার করেছি! এছাড়াও, আপনি যদি দামের পার্থক্যের ডেটা নিয়ে আরও গবেষণা করতে চান - এটি এখন আরও "শৃঙ্খল" দেখাচ্ছে কারণ এতে প্রতিদিন একটি এন্ট্রি রয়েছে, যদিও সেই এন্ট্রিগুলির মধ্যে পাঁচটি এখন 0 (কেন? price_vec_na_simple.ffill().diff().iloc[90:95] চালানোর চেষ্টা করুন) price_vec_na_simple.ffill().diff().iloc[90:95] নিজের জন্য দেখতে)।


তা ছাড়াও, অর্থে, অনুপস্থিত ডেটা এবং আউটলিয়ার ডেটা প্রায়শই একত্রিত হয়। আমাকে ব্যাখ্যা করা যাক:

 #inflate two observations, delete three next ones price_moves_na[90] += 20 price_moves_na[91] += 30 price_moves_na[92] -= 50 # to "deflate" the price shock back price_vec_na = (100 + price_moves_na.cumsum()) price_vec_na[92:95] = [np.NaN, np.NaN, np.NaN] price_vec_na.tail(20).plot() price_vec_na.diff().dropna().mean() >0.7093365245831178 

স্পাইক + ডেটা অনুপস্থিত


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


আমাদের কাছে কোন নতুন তথ্য না থাকলে সবচেয়ে স্বাভাবিক অনুমান কি? ভাল, মনে রাখবেন যে আমাদের ডেটা-জেনারেটিং মডেলটি মূলত মূল্য পরিবর্তনের উপর ভিত্তি করে ছিল। তাই যদি কোন নতুন তথ্য না থাকে, সম্ভবত দাম সব পরিবর্তন হচ্ছে না? LOCF (লাস্ট অবজারভেশন ক্যারিড ফরোয়ার্ড) ঠিক এটাই ধরে নেয়।

প্রসঙ্গ জন্য কিছু গণিত

একটি অনুসন্ধিৎসু পাঠকের জন্য একটি পার্শ্ব নোট - সম্ভবত LOCF কেন স্টকের মূল্য ডেটার জন্য বিশেষভাবে উপযুক্ত সে সম্পর্কে আরও মৌলিক দৃষ্টিভঙ্গি হল যে এটি সাধারণত একটি মার্টিংগেল হিসাবে তৈরি করা হয়৷ মোটামুটিভাবে বলতে গেলে, একটি মার্টিংগেল এমন কিছু যেখানে আগামীকালের জন্য আমাদের সেরা অনুমান হল আমরা আজ যা দেখছি, বা E[x_{t+1} | x_t] = x_t


ঠিক আছে, প্রকৃত তথ্য ফিরে! আসুন দৃষ্টিগত এবং সংখ্যাগতভাবে LOCF এর ফলাফলগুলি পরীক্ষা করি:

 price_vec_na.ffill().tail(20).plot() price_vec_na.ffill().diff().mean() >0.20030544816842052 

LOCF অভিযোজন


অবিলম্বে, আমরা LOCF এর ভাল-মন্দ দেখতে পাই (বেশ আক্ষরিক অর্থেই)! একের জন্য, গড়টি যেখানে আমরা "প্রত্যাশিত" সেখানে ফিরে এসেছে - অর্থাৎ অপরিবর্তিত অভিজ্ঞতামূলক মূল্য। যাইহোক, আমরা একটি বরং কুৎসিত সময়ের পরিচয় করিয়ে দিচ্ছি যেখানে দাম "সাধারণ" এবং 94 এবং 95 দিনের মধ্যে দামের কৃত্রিম হ্রাসের সাথে সঙ্গতিপূর্ণ নয়।

অভিযুক্তি সম্পর্কে কি?

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


  • আপনি যদি শুধুমাত্র সমস্ত-নমুনা গড় ব্যবহার করেন, তাহলে আপনি একটি সুস্পষ্ট-সামনের পক্ষপাতের পরিচয় দেন - অর্থাৎ আপনি অতীতের মানগুলিকে দোষারোপ করার জন্য ভবিষ্যতের ডেটা ব্যবহার করেন।

  • কিছু ধরণের লুক-ব্যাক বা রোলিং মানে ব্যবহার করা অবশ্যই ভাল - তবে, এটি কখনও কখনও মার্টিঙ্গেল "বেসলাইন" ভিউয়ের সাথে উত্তেজনায় আসতে পারে যা আমরা আগে বর্ণনা করেছি।


এর একটু বিস্তারিতভাবে এই তাকান করা যাক. আমি আমাদের পুরানো ডেটাতে লুক-ব্যাক ইম্পুটেশন ব্যবহার করব -

 price_vec_na_impute = price_vec_na.copy() price_vec_na_impute[price_vec_na_impute.isna()] = price_vec_na.iloc[:90].mean() price_vec_na_impute.diff().mean() >0.20030544816842052 

অভিযোজন মানে

আমরা "সঠিক" মূল্য পরিবর্তনের মানে পুনরুদ্ধার করি, LOCF এর মতোই। কিন্তু আমরা 91 এবং 92 দিনের মধ্যে একটি কৃত্রিম মূল্য হ্রাস প্রবর্তন করি যা কিছু উপায়ে আমাদের আগের তুলনায় আরও খারাপ। সর্বোপরি, ঘটনাটি সম্ভবত শান্ত হওয়ার পরে বা তার পরে ঘটেছিল, যেখানে এটি কেবল অনুমান করে যে সবকিছু এখনই স্বাভাবিক হয়ে যায়। তা বাদ দিয়ে, বাস্তবে লুক-ব্যাক উইন্ডোতে ভারসাম্য বজায় রাখা কিছুটা চ্যালেঞ্জিং হতে পারে যেমন আমরা ক) সাম্প্রতিক প্রবণতা ক্যাপচার করি কিন্তু খ) দীর্ঘমেয়াদী প্রবণতা (সাধারণ পক্ষপাত-ভেরায়েন্স ট্রেডঅফ) ক্যাপচার করি।


একটি দ্বিতীয় পরিবর্তনশীল যোগ করা হচ্ছে

ধরুন আমরা এখন একটি আরও জটিল কাজ করতে চাই - অভিজ্ঞতামূলক ডেটা থেকে দুটি সম্পদের মূল্য চালনার মধ্যে পারস্পরিক সম্পর্ক বের করুন, যখন মূল্য সিরিজের এক বা উভয়ের ডেটা অনুপস্থিত থাকে। অবশ্যই, আমরা এখনও ড্রপিং ব্যবহার করতে পারি, কিন্তু:


  • এমনকি যদি আমরা এটি ব্যবহার করতে পারি, এটি কি সর্বোত্তম?

  • যদি আমাদের অনেকগুলি ভেরিয়েবল থাকে - তাহলে অন্তত একটি NA সহ সমস্ত সারি বাদ দিলে আমাদের কাছে কোনও ডেটাই থাকবে না!


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


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


 np.random.seed(2) # needed to ensure a fixed second series price_moves_2 = pd.Series(np.random.randn(100)) price_vec_2 = 50+(0.4*price_moves/3 + np.sqrt(1-0.4**2)*price_moves_2).cumsum() # all this math to ensure we get a 0.4 "theoretical" correlation with the first one


আসুন "বেসলাইন" পরীক্ষামূলক সম্পর্ক পরীক্ষা করা যাক - অর্থাৎ, এনএ এবং জাম্প ছাড়াই।

 pd.concat([price_vec, price_vec_2], axis = 1).diff().corr().iloc[0,1] >0.4866403018044526


এখন এটি যুক্তিসঙ্গতভাবে "তাত্ত্বিক" পারস্পরিক সম্পর্কের কাছাকাছি - এটি সুপরিচিত যে পারস্পরিক সম্পর্কের অভিজ্ঞতামূলক পরিমাপ বরং বড় গোলমালের প্রবণ।


আউটলায়ার ছাড়া এনএ

পরবর্তী পদক্ষেপ হিসাবে, আমরা NAs-এর সাথে কেসটি পরীক্ষা করব, কিন্তু কোন আউটলায়ার নেই। আমরা diff আগে এবং পরে dropna করলে কি হবে তাও আমরা তুলনা করব

 pd.concat([price_vec_na_simple, price_vec_2], axis = 1).diff().corr().iloc[0,1] # implicit dropna after diff >0.5022675176281746 pd.concat([price_vec_na_simple, price_vec_2], axis = 1).dropna().diff().corr().iloc[0,1] >0.5287405341268966


উভয় ফলাফল বেশ কাছাকাছি এবং আমরা আগে পেয়েছিলাম "অভিজ্ঞতামূলক" মান থেকে খুব বেশি দূরে নয়। আসুন LOCF যাচাই করি এবং অনুযোগও ঠিক আছে:

 pd.concat([price_vec_na_simple, price_vec_2], axis = 1).ffill().diff().corr().iloc[0,1] >0.5049380499525835 price_vec_na_simple_impute = price_vec_na_simple.copy() price_vec_na_simple_impute[price_vec_na_simple_impute.isna()] = price_vec_na_simple_impute.iloc[:90].mean() pd.concat([price_vec_na_simple_impute, price_vec_2], axis = 1).ffill().diff().corr().iloc[0,1] >0.4866728183859715


উপরের 4টি ফলাফলের তুলনা করে, আমরা দেখতে পাচ্ছি যে সমস্ত পদ্ধতি বেশ ভাল কাজ করে। সম্ভবত আমরা বাইরের ক্ষেত্রে একই আশা করা উচিত তাহলে?


আউটলায়ার সহ এনএ

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


 price_vec_na_2 = 50+(0.4*price_moves_na/3 + np.sqrt(1-0.4**2)*price_moves_2).cumsum()


আসুন আবার আমাদের সমস্ত পদ্ধতির কর্মক্ষমতা তুলনা করি -

 pd.concat([price_vec_na, price_vec_na_2], axis = 1).diff().corr().iloc[0,1] >0.6527112906179914 pd.concat([price_vec_na, price_vec_na_2], axis = 1).dropna().diff().corr().iloc[0,1] >0.7122391279139506


তাত্ত্বিক এবং অভিজ্ঞতামূলক উভয় মূল্যের সাথে এটি বেশ পার্থক্য! কিভাবে LOCF এবং অভিযুক্ত?

 pd.concat([price_vec_na, price_vec_na_2], axis = 1).ffill().diff().corr().iloc[0,1] >0.33178239830519984 pd.concat([price_vec_na_impute, price_vec_na_2], axis = 1).dropna().diff().corr().iloc[0,1] >0.7280990594963112


এখন আমরা অবশেষে দেখতে পাচ্ছি LOCF এর মূল্য কত! এটা স্পষ্টভাবে অন্য সব পদ্ধতি outperforms!


সম্ভাব্য ক্ষতি + ইন্টারপোলেশন

অবশ্যই, এটি 100% শক্তিশালী নয়। একের জন্য, LOCF করার মাধ্যমে আমরা যখন হারিয়ে যাওয়া ডেটা শেষ হয়ে যায় তখন আমরা একটি বড় মূল্য হ্রাস প্রবর্তন করি। যদি এটি দ্বিতীয় মূল্য ভেক্টরের কিছু আউটলারের সাথে মিলে যায় তবে ফলাফলগুলি বেশ কিছুটা পরিবর্তন হতে পারে। (*পাঠকের জন্য একটি ব্যায়াম - price_vec_na_2[95] এর প্রাইস মুভের সাইনটি ফ্লিপ করুন এবং এটি ফলাফলকে কীভাবে প্রভাবিত করে তা পরীক্ষা করুন)। দামের সর্বোচ্চ price_vec_na[91] এবং "স্বাভাবিক" মানের পরবর্তী price_vec_na[95] এর মধ্যে প্রসারিত করার বিপরীতে কেবলমাত্র এই মূল্য হ্রাসকে প্রবর্তন করা "পরিষ্কার" কিনা তা পুরোপুরি পরিষ্কার নয়। যাইহোক, বিশেষ করে একটি "লাইভ" ব্যবহারের জন্য, ইন্টারপোলেশন সত্যিই সম্ভব নয়! সর্বোপরি, আজ যদি দিন #93 হয়, তাহলে কিভাবে আমরা দিনের #95 শেষে রেকর্ড করা ভবিষ্যত মান ব্যবহার করে ইন্টারপোলেট করতে পারি? একটি ঐতিহাসিক অধ্যয়নের জন্য - নিশ্চিত, এটি একটি বিকল্প থেকে যায়, কিন্তু তারপরে এটি কীভাবে ব্যাখ্যা করা যায় এবং প্রকৃত পূর্বাভাসের জন্য এটি ব্যবহার করা যায় তা স্পষ্ট নয়! উপসংহারে, সময়ের মাত্রা জুড়ে ইন্টারপোলেশন সম্ভব, তবে কিছুটা বেশি প্রশ্নবিদ্ধ।


উপসংহার

আর্থিক সময় সিরিজে অনুপস্থিত ডেটা পরিচালনা করার জন্য কেন LOCF প্রায়শই ব্যবহার করার জন্য সবচেয়ে আকর্ষণীয় এবং সহজ বিকল্প হিসাবে পরিচিত এবং সমর্থন করার জন্য আমি একটি ছোট কেস স্টাডি দেওয়ার চেষ্টা করেছি।


রিক্যাপ করার জন্য, সুবিধাগুলি হল:

  • মার্টিংগেল/"তথ্য প্রবাহ" দৃষ্টিকোণ থেকে আকর্ষণীয়
  • বাস্তবায়ন করা সুপার সহজ
  • অপ্টিমাইজ করার দরকার নেই (অভিযোগের বিপরীতে)
  • অন্তত শালীনভাবে outliers হ্যান্ডেল


কিছু অসুবিধা:

  • অনুপস্থিত সময়ের শেষে সম্ভাব্য বড় জাম্প হতে পারে
  • বিভিন্ন ভেরিয়েবলের জন্য ব্যবহার করা হলে কিছু সূক্ষ্ম যুগ্ম গতিবিদ্যা মিস করতে পারে


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