রিসোর্স লোড হচ্ছে... লোডিং...

পাইথনের সাথে ইভেন্ট-ড্রাইভ ব্যাক টেস্টিং - পার্ট I

লেখক:ভাল, তৈরিঃ 2019-03-22 11:53:50, আপডেটঃ

আমরা গত কয়েক মাস ধরে পাইথন এবং পান্ডা ব্যবহার করে বিভিন্ন ট্রেডিং কৌশল ব্যাকটেস্টিংয়ে ব্যয় করেছি। পান্ডার ভেক্টরাইজড প্রকৃতি নিশ্চিত করে যে বড় ডেটাসেটে নির্দিষ্ট ক্রিয়াকলাপগুলি অত্যন্ত দ্রুত। তবে আমরা এখন পর্যন্ত অধ্যয়ন করেছি এমন ভেক্টরাইজড ব্যাকটেস্টারের রূপগুলি ব্যবসায়ের কার্য সম্পাদনের সিমুলেশন পদ্ধতিতে কিছু অসুবিধার সম্মুখীন হয়। এই সিরিজের নিবন্ধগুলিতে আমরা পাইথন ব্যবহার করে একটি ইভেন্ট-চালিত ব্যাকটেস্টিং পরিবেশ তৈরি করে 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

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

কেন ইভেন্ট-ড্রাইভড ব্যাকটেস্টার?

ইভেন্ট-চালিত সিস্টেমগুলি ভেক্টরাইজড পদ্ধতির তুলনায় অনেক সুবিধা প্রদান করেঃ

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

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

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

ইভেন্ট-চালিত ব্যাকটেস্টারের ওভারভিউ

ব্যাকটেস্টিং সিস্টেমে ইভেন্ট-চালিত পদ্ধতির প্রয়োগ করার জন্য আমাদের উপাদানগুলি (বা বস্তুগুলি) সংজ্ঞায়িত করা প্রয়োজন যা নির্দিষ্ট কাজগুলি পরিচালনা করবেঃ

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

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

এখানে পাইথন কোডের একটি স্নিপেট রয়েছে যা ব্যাকটেস্টারটি অনুশীলনে কীভাবে কাজ করে তা দেখায়। কোডে দুটি লুপ ঘটে। বাইরের লুপটি ব্যাকটেস্টারকে হার্টবিট দেওয়ার জন্য ব্যবহৃত হয়। লাইভ ট্রেডিংয়ের জন্য এটি এমন ফ্রিকোয়েন্সি যা নতুন বাজারের ডেটা জরিপ করা হয়। ব্যাকটেস্টিং কৌশলগুলির জন্য এটি কঠোরভাবে প্রয়োজনীয় নয় কারণ ব্যাকটেস্টার ড্রপ-ফিড আকারে সরবরাহ করা বাজার ডেটা ব্যবহার করে (বারগুলি দেখুন।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)

এটি একটি ইভেন্ট-চালিত ব্যাকটেস্টার কীভাবে ডিজাইন করা হয় তার প্রাথমিক রূপরেখা। পরবর্তী নিবন্ধে আমরা ইভেন্ট ক্লাসের শ্রেণিবিন্যাস নিয়ে আলোচনা করব।


আরো