지난 기사에서는 이벤트에 의한 백테스터의 개념을 설명했습니다. 이 시리즈의 나머지 기사에서는 전체 시스템을 구성하는 개별 클래스 계층별로 집중할 것입니다. 이 기사에서는 이벤트를 고려하고 객체 간의 정보를 통신하는 데 사용할 수 있습니다.
이전 기사에서 논의 된 바와 같이 거래 시스템은 외부와 내부의 두 개의 윙을 사용합니다. 내부의 윙은 메모리 큐에서 이벤트를 캡처하고 다음 작업을 위해 적절한 구성 요소로 라우팅합니다. 이 인프라에는 네 가지 유형의 이벤트가 있습니다.
부모 클래스는 이벤트라고 불립니다. 그것은 기본 클래스이며 어떤 기능이나 특정 인터페이스를 제공하지 않습니다. 후기 구현에서 이벤트 객체는 더 많은 복잡성을 개발할 가능성이 있으며 따라서 우리는 클래스 계층을 생성함으로써 그러한 시스템의 디자인을 미래로 증명하고 있습니다.
# 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
MarketEvent는 Event에서 계승되며,
# 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의 앞서 언급한 속성 외에도 양분 필드를 포함하고 있기 때문에 OrderEvent보다 약간 복잡합니다. 양은 포트폴리오 제약에 의해 결정됩니다. 또한 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는 가장 복잡한 이벤트입니다. 주문이 완료 된 시점, 주문의 기호 및 거래소가 실행된 시점, 거래된 주식량, 실제 구매 가격 및 수수료를 포함합니다.
수수료는 인터랙티브 브로커 수수료를 사용하여 계산됩니다. 미국 API 주문의 경우 이 수수료는 주문당 최소 1.30 USD이며, 거래 규모가 500 유닛 이하 또는 이상인지에 따라 주당 0.013 USD 또는 0.08 USD의 일정한 비율로 계산됩니다.
# 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
이 시리즈의 다음 기사에서는 같은 클래스 인터페이스를 통해 역사적인 백테스팅과 실시간 거래를 모두 허용하는 시장 데이터 핸들러 클래스 계층 구조를 개발하는 방법을 고려할 것입니다.