पायथन के साथ घटना-संचालित बैकटेस्टिंग - भाग II

लेखक:अच्छाई, बनाया गयाः 2019-03-23 09:13:33, अद्यतन किया गयाः

पिछले लेख में हमने एक घटना-संचालित बैकटेस्टर की अवधारणा का वर्णन किया था। इस श्रृंखला के शेष लेख समग्र प्रणाली बनाने वाले प्रत्येक अलग-अलग वर्ग पदानुक्रम पर ध्यान केंद्रित करेंगे। इस लेख में हम घटनाओं पर विचार करेंगे और उनका उपयोग ऑब्जेक्ट के बीच जानकारी संचार करने के लिए कैसे किया जा सकता है।

जैसा कि पिछले लेख में चर्चा की गई है, ट्रेडिंग सिस्टम दो जबकि लूप का उपयोग करता है - एक बाहरी और एक आंतरिक। आंतरिक जबकि लूप एक इन-मेमोरी कतार से घटनाओं के कैप्चर को संभालता है, जिसे बाद की कार्रवाई के लिए उपयुक्त घटक पर रूट किया जाता है। इस बुनियादी ढांचे में चार प्रकार की घटनाएं हैंः

  • MarketEvent - यह तब ट्रिगर किया जाता है जब बाहरी while लूप एक नया heartbeat शुरू करता है। यह तब होता है जब DataHandler ऑब्जेक्ट किसी भी प्रतीक के लिए बाजार डेटा का एक नया अपडेट प्राप्त करता है जिसे वर्तमान में ट्रैक किया जा रहा है। इसका उपयोग नई ट्रेडिंग संकेत उत्पन्न करने वाली रणनीति ऑब्जेक्ट को ट्रिगर करने के लिए किया जाता है। इवेंट ऑब्जेक्ट में बस एक पहचान होती है कि यह एक बाजार घटना है, जिसमें कोई अन्य संरचना नहीं है।
  • SignalEvent - Strategy ऑब्जेक्ट नए SignalEvents बनाने के लिए बाजार के डेटा का उपयोग करता है। SignalEvent में एक टिकर प्रतीक, एक टाइमस्टैम्प होता है जब यह उत्पन्न हुआ था और एक दिशा (लंबी या छोटी) होती है। SignalEvents का उपयोग पोर्टफोलियो ऑब्जेक्ट द्वारा व्यापार करने के लिए सलाह के रूप में किया जाता है।
  • OrderEvent - जब पोर्टफोलियो ऑब्जेक्ट SignalEvents प्राप्त करता है तो यह उन्हें जोखिम और स्थिति आकार के संदर्भ में पोर्टफोलियो के व्यापक संदर्भ में मूल्यांकन करता है। यह अंततः OrderEvents के लिए जाता है जो एक ExecutionHandler को भेजे जाएंगे।
  • FillEvent - जब एक ExecutionHandler एक OrderEvent प्राप्त करता है तो उसे ऑर्डर को ट्रांजेक्ट करना होता है। एक बार ऑर्डर ट्रांजेक्ट हो जाने के बाद यह FillEvent जनरेट करता है, जो खरीद या बिक्री की लागत के साथ-साथ ट्रांजेक्शन की लागत, जैसे फीस या स्लिप के बारे में बताता है।

माता-पिता वर्ग को घटना कहा जाता है. यह एक आधार वर्ग है और कोई कार्यक्षमता या विशिष्ट इंटरफ़ेस प्रदान नहीं करता है. बाद के कार्यान्वयन में घटना वस्तुओं में अधिक जटिलता विकसित होने की संभावना है और इस प्रकार हम एक वर्ग पदानुक्रम बनाकर ऐसे सिस्टम के डिजाइन को भविष्य-सबूत कर रहे हैं.

# event.py

class Event(object):
    """
    Event is base class providing an interface for all subsequent 
    (inherited) events, that will trigger further events in the 
    trading infrastructure.   
    """
    pass

मार्केट इवेंट इवेंट से विरासत में मिलता है और यह एक मार्केट प्रकार की घटना होने की आत्म-पहचान से थोड़ा अधिक प्रदान करता है।

# event.py

class MarketEvent(Event):
    """
    Handles the event of receiving a new market update with 
    corresponding bars.
    """

    def __init__(self):
        """
        Initialises the MarketEvent.
        """
        self.type = 'MARKET'

एक SignalEvent को पोर्टफोलियो ऑब्जेक्ट को सूचित करने के लिए एक टिकर प्रतीक, जनरेशन के लिए एक टाइमस्टैम्प और दिशा की आवश्यकता होती है।

# event.py

class SignalEvent(Event):
    """
    Handles the event of sending a Signal from a Strategy object.
    This is received by a Portfolio object and acted upon.
    """
    
    def __init__(self, symbol, datetime, signal_type):
        """
        Initialises the SignalEvent.

        Parameters:
        symbol - The ticker symbol, e.g. 'GOOG'.
        datetime - The timestamp at which the signal was generated.
        signal_type - 'LONG' or 'SHORT'.
        """
        
        self.type = 'SIGNAL'
        self.symbol = symbol
        self.datetime = datetime
        self.signal_type = signal_type

OrderEvent एक SignalEvent की तुलना में थोड़ा अधिक जटिल है क्योंकि इसमें SignalEvent के उपर्युक्त गुणों के अलावा एक मात्रा क्षेत्र होता है। मात्रा पोर्टफोलियो बाधाओं द्वारा निर्धारित की जाती है। इसके अलावा OrderEvent में एक print_order))) विधि है, जिसका उपयोग यदि आवश्यक हो तो कंसोल को जानकारी आउटपुट करने के लिए किया जाता है।

# event.py

class OrderEvent(Event):
    """
    Handles the event of sending an Order to an execution system.
    The order contains a symbol (e.g. GOOG), a type (market or limit),
    quantity and a direction.
    """

    def __init__(self, symbol, order_type, quantity, direction):
        """
        Initialises the order type, setting whether it is
        a Market order ('MKT') or Limit order ('LMT'), has
        a quantity (integral) and its direction ('BUY' or
        'SELL').

        Parameters:
        symbol - The instrument to trade.
        order_type - 'MKT' or 'LMT' for Market or Limit.
        quantity - Non-negative integer for quantity.
        direction - 'BUY' or 'SELL' for long or short.
        """
        
        self.type = 'ORDER'
        self.symbol = symbol
        self.order_type = order_type
        self.quantity = quantity
        self.direction = direction

    def print_order(self):
        """
        Outputs the values within the Order.
        """
        print "Order: Symbol=%s, Type=%s, Quantity=%s, Direction=%s" % \
            (self.symbol, self.order_type, self.quantity, self.direction)

FillEvent सबसे अधिक जटिलता वाली घटना है। इसमें एक ऑर्डर कब भरा गया था, ऑर्डर का प्रतीक और जिस एक्सचेंज पर इसे निष्पादित किया गया था, लेनदेन की गई शेयरों की मात्रा, खरीदारी की वास्तविक कीमत और कमीशन शामिल है।

कमीशन की गणना इंटरएक्टिव ब्रोकर के कमीशन का उपयोग करके की जाती है। अमेरिकी एपीआई ऑर्डर के लिए यह कमीशन प्रति ऑर्डर न्यूनतम 1.30 अमरीकी डालर है, जिसमें ट्रेड आकार 500 इकाइयों से कम या अधिक है या नहीं, इसके आधार पर 0.013 अमरीकी डालर या 0.08 अमरीकी डालर प्रति शेयर की फ्लैट दर है।

# event.py

class FillEvent(Event):
    """
    Encapsulates the notion of a Filled Order, as returned
    from a brokerage. Stores the quantity of an instrument
    actually filled and at what price. In addition, stores
    the commission of the trade from the brokerage.
    """

    def __init__(self, timeindex, symbol, exchange, quantity, 
                 direction, fill_cost, commission=None):
        """
        Initialises the FillEvent object. Sets the symbol, exchange,
        quantity, direction, cost of fill and an optional 
        commission.

        If commission is not provided, the Fill object will
        calculate it based on the trade size and Interactive
        Brokers fees.

        Parameters:
        timeindex - The bar-resolution when the order was filled.
        symbol - The instrument which was filled.
        exchange - The exchange where the order was filled.
        quantity - The filled quantity.
        direction - The direction of fill ('BUY' or 'SELL')
        fill_cost - The holdings value in dollars.
        commission - An optional commission sent from IB.
        """
        
        self.type = 'FILL'
        self.timeindex = timeindex
        self.symbol = symbol
        self.exchange = exchange
        self.quantity = quantity
        self.direction = direction
        self.fill_cost = fill_cost

        # Calculate commission
        if commission is None:
            self.commission = self.calculate_ib_commission()
        else:
            self.commission = commission

    def calculate_ib_commission(self):
        """
        Calculates the fees of trading based on an Interactive
        Brokers fee structure for API, in USD.

        This does not include exchange or ECN fees.

        Based on "US API Directed Orders":
        https://www.interactivebrokers.com/en/index.php?f=commission&p=stocks2
        """
        full_cost = 1.3
        if self.quantity <= 500:
            full_cost = max(1.3, 0.013 * self.quantity)
        else: # Greater than 500
            full_cost = max(1.3, 0.008 * self.quantity)
        full_cost = min(full_cost, 0.5 / 100.0 * self.quantity * self.fill_cost)
        return full_cost

श्रृंखला के अगले लेख में हम विचार करने जा रहे हैं कि एक ही वर्ग इंटरफ़ेस के माध्यम से, ऐतिहासिक बैकटेस्टिंग और लाइव ट्रेडिंग दोनों की अनुमति देने वाले मार्केट डेटा हैंडलर क्लास पदानुक्रम को कैसे विकसित किया जाए।


अधिक