আমরা গত কয়েক মাস ধরে পাইথন এবং পান্ডা ব্যবহার করে বিভিন্ন ট্রেডিং কৌশল ব্যাকটেস্টিংয়ে ব্যয় করেছি। পান্ডার ভেক্টরাইজড প্রকৃতি নিশ্চিত করে যে বড় ডেটাসেটে নির্দিষ্ট ক্রিয়াকলাপগুলি অত্যন্ত দ্রুত। তবে আমরা এখন পর্যন্ত অধ্যয়ন করেছি এমন ভেক্টরাইজড ব্যাকটেস্টারের রূপগুলি ব্যবসায়ের কার্য সম্পাদনের সিমুলেশন পদ্ধতিতে কিছু অসুবিধার সম্মুখীন হয়। এই সিরিজের নিবন্ধগুলিতে আমরা পাইথন ব্যবহার করে একটি ইভেন্ট-চালিত ব্যাকটেস্টিং পরিবেশ তৈরি করে historicalতিহাসিক কৌশল সিমুলেশনের আরও বাস্তবসম্মত পদ্ধতির বিষয়ে আলোচনা করতে যাচ্ছি।
এই ধরনের ব্যাকটেস্টারের বিকাশের আগে আমাদের ইভেন্ট-চালিত সিস্টেমগুলির ধারণাটি বুঝতে হবে। ভিডিও গেমগুলি ইভেন্ট-চালিত সফ্টওয়্যারগুলির জন্য একটি প্রাকৃতিক ব্যবহারের কেস সরবরাহ করে এবং অন্বেষণের জন্য একটি সহজ উদাহরণ সরবরাহ করে। একটি ভিডিও গেমের একাধিক উপাদান রয়েছে যা উচ্চ ফ্রেমরেটে রিয়েল-টাইম সেটিংয়ে একে অপরের সাথে ইন্টারঅ্যাক্ট করে। এটি একটি
গেম-লুপের প্রতিটি টিকের সময় একটি ফাংশনকে সর্বশেষ ইভেন্টটি গ্রহণ করতে বলা হয়, যা গেমের মধ্যে কিছু সংশ্লিষ্ট পূর্ববর্তী ক্রিয়াকলাপ দ্বারা উত্পন্ন হবে। ইভেন্টের প্রকৃতির উপর নির্ভর করে, যার মধ্যে কী-প্রেস বা মাউস ক্লিক অন্তর্ভুক্ত থাকতে পারে, কিছু পরবর্তী ক্রিয়া নেওয়া হয়, যা হয় লুপটি শেষ করবে বা কিছু অতিরিক্ত ইভেন্ট উত্পন্ন করবে। প্রক্রিয়াটি তারপরে অব্যাহত থাকবে। এখানে কিছু উদাহরণ ছদ্ম কোড রয়েছেঃ
while True: # Run the loop forever
new_event = get_new_event() # Get the latest event
# Based on the event type, perform an action
if new_event.type == "LEFT_MOUSE_CLICK":
open_menu()
elif new_event.type == "ESCAPE_KEY_PRESS":
quit_game()
elif new_event.type == "UP_KEY_PRESS":
move_player_north()
# ... and many more events
redraw_screen() # Update the screen to provide animation
tick(50) # Wait 50 milliseconds
কোডটি ক্রমাগত নতুন ইভেন্টগুলির জন্য পরীক্ষা করে এবং তারপরে এই ইভেন্টগুলির উপর ভিত্তি করে ক্রিয়া সম্পাদন করে। বিশেষত এটি রিয়েল-টাইম রেসপন্স হ্যান্ডলিংয়ের ভ্রান্তিকে অনুমতি দেয় কারণ কোডটি ক্রমাগত লুপ করা হচ্ছে এবং ইভেন্টগুলি পরীক্ষা করা হচ্ছে। যেমনটি স্পষ্ট হয়ে উঠবে এটি হ'ল আমাদের উচ্চ ফ্রিকোয়েন্সি ট্রেডিং সিমুলেশন পরিচালনা করার জন্য যা প্রয়োজন।
ইভেন্ট-চালিত সিস্টেমগুলি ভেক্টরাইজড পদ্ধতির তুলনায় অনেক সুবিধা প্রদান করেঃ
যদিও ইভেন্ট-চালিত সিস্টেমগুলি অনেক সুবিধা নিয়ে আসে তবে তারা সহজ ভেক্টরাইজড সিস্টেমের তুলনায় দুটি প্রধান অসুবিধার সম্মুখীন হয়। প্রথমত, তারা বাস্তবায়ন এবং পরীক্ষার জন্য উল্লেখযোগ্যভাবে বেশি জটিল। আরও
দ্বিতীয়ত, একটি ভেক্টরাইজড সিস্টেমের তুলনায় এগুলি বাস্তবায়ন করা ধীর। গাণিতিক গণনা সম্পাদন করার সময় সর্বোত্তম ভেক্টরাইজড অপারেশনগুলি ব্যবহার করা যায় না। আমরা পরবর্তী নিবন্ধগুলিতে এই সীমাবদ্ধতাগুলি কাটিয়ে উঠার উপায়গুলি নিয়ে আলোচনা করব।
ব্যাকটেস্টিং সিস্টেমে ইভেন্ট-চালিত পদ্ধতির প্রয়োগ করার জন্য আমাদের উপাদানগুলি (বা বস্তুগুলি) সংজ্ঞায়িত করা প্রয়োজন যা নির্দিষ্ট কাজগুলি পরিচালনা করবেঃ
এটি একটি ট্রেডিং ইঞ্জিনের বেশ মৌলিক মডেল। সম্প্রসারণের জন্য উল্লেখযোগ্য সুযোগ রয়েছে, বিশেষ করে পোর্টফোলিওটি কীভাবে ব্যবহার করা হয় তা বিবেচনা করে। উপরন্তু, বিভিন্ন লেনদেনের ব্যয় মডেলগুলি তাদের নিজস্ব শ্রেণীর শ্রেণিবিন্যাসেও বিমূর্ত করা যেতে পারে। এই পর্যায়ে এটি এই সিরিজের নিবন্ধগুলির মধ্যে অপ্রয়োজনীয় জটিলতা প্রবর্তন করে তাই আমরা বর্তমানে এটি আরও আলোচনা করব না। পরবর্তী টিউটোরিয়ালগুলিতে আমরা সম্ভবত অতিরিক্ত বাস্তববাদ অন্তর্ভুক্ত করার জন্য সিস্টেমটি প্রসারিত করব।
এখানে পাইথন কোডের একটি স্নিপেট রয়েছে যা ব্যাকটেস্টারটি অনুশীলনে কীভাবে কাজ করে তা দেখায়। কোডে দুটি লুপ ঘটে। বাইরের লুপটি ব্যাকটেস্টারকে হার্টবিট দেওয়ার জন্য ব্যবহৃত হয়। লাইভ ট্রেডিংয়ের জন্য এটি এমন ফ্রিকোয়েন্সি যা নতুন বাজারের ডেটা জরিপ করা হয়। ব্যাকটেস্টিং কৌশলগুলির জন্য এটি কঠোরভাবে প্রয়োজনীয় নয় কারণ ব্যাকটেস্টার ড্রপ-ফিড আকারে সরবরাহ করা বাজার ডেটা ব্যবহার করে (বারগুলি দেখুন।update_bars))) লাইন) ।
অভ্যন্তরীণ লুপটি আসলে ইভেন্টস কিউ অবজেক্ট থেকে ইভেন্টগুলি পরিচালনা করে। নির্দিষ্ট ইভেন্টগুলি সংশ্লিষ্ট উপাদানটিতে প্রেরণ করা হয় এবং পরবর্তীকালে নতুন ইভেন্টগুলি সারিতে যুক্ত করা হয়। যখন ইভেন্টস কিউ খালি থাকে, তখন হার্টবিট লুপটি অব্যাহত থাকেঃ
# Declare the components with respective parameters
bars = DataHandler(..)
strategy = Strategy(..)
port = Portfolio(..)
broker = ExecutionHandler(..)
while True:
# Update the bars (specific backtest code, as opposed to live trading)
if bars.continue_backtest == True:
bars.update_bars()
else:
break
# Handle the events
while True:
try:
event = events.get(False)
except Queue.Empty:
break
else:
if event is not None:
if event.type == 'MARKET':
strategy.calculate_signals(event)
port.update_timeindex(event)
elif event.type == 'SIGNAL':
port.update_signal(event)
elif event.type == 'ORDER':
broker.execute_order(event)
elif event.type == 'FILL':
port.update_fill(event)
# 10-Minute heartbeat
time.sleep(10*60)
এটি একটি ইভেন্ট-চালিত ব্যাকটেস্টার কীভাবে ডিজাইন করা হয় তার প্রাথমিক রূপরেখা। পরবর্তী নিবন্ধে আমরা ইভেন্ট ক্লাসের শ্রেণিবিন্যাস নিয়ে আলোচনা করব।