Skip to content

Commit

Permalink
trim some columns
Browse files Browse the repository at this point in the history
  • Loading branch information
letianzj committed Aug 4, 2020
1 parent 38249e3 commit d051bf9
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 123 deletions.
4 changes: 4 additions & 0 deletions quanttrading2/backtest_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,15 @@ def _tick_event_handler(self, tick_event):
self._strategy.on_tick(tick_event)

def _order_event_handler(self, order_event):
"""
backtest doesn't send order_event back to strategy. It fills directly and becoems fill_event
"""
self._backtest_brokerage.place_order(order_event)

def _fill_event_handler(self, fill_event):
self._position_manager.on_fill(fill_event)
self._performance_manager.on_fill(fill_event)
self._strategy.on_fill(fill_event)

# -------------------------------- end of private functions -----------------------------#
def run(self):
Expand Down
97 changes: 63 additions & 34 deletions quanttrading2/brokerage/ib_brokerage.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,21 @@ def __init__(self, event_engine, account: str):
self.event_engine = event_engine # save events to event queue
self.api = IBApi(self)
self.account = account
self.contract_detail_request_contract_dict = {}
self.contract_detail_request_symbol_dict = {}
self.contract_detail_request_contract_dict = {} # reqid ==> contract
self.contract_detail_request_symbol_dict = {} # reqid ==> symbol
self.sym_contract_dict = {} # sym ==> contract
self.contract_symbol_dict = {} # conId ==> symbol
self.market_data_subscription_dict = {}
self.market_data_subscription_reverse_dict = {}
self.market_data_tick_dict = {} # to combine tickprice and ticksize
self.market_depth_subscription_dict = {}
self.market_depth_subscription_reverse_dict = {}
self.market_depth_tick_dict = {} # to combine tickprice and ticksize
self.market_depth_tick_dict = {} # to combine tickprice and ticksize
self.hist_data_request_dict = {}
self.order_dict = {}
self.order_dict = {} # order id ==> order_event
self.account_summary_reqid = -1
self.account_summary = AccountEvent()
self.account_summary.brokerage = 'IB'
self.clientid = 0
self.reqid = 0
self.orderid = 0
Expand Down Expand Up @@ -86,7 +89,7 @@ def _calculate_commission(self, full_symbol, fill_price, fill_size):
pass

def next_order_id(self):
pass
return self.orderid

def place_order(self, order_event):
if not self.api.connected:
Expand All @@ -103,6 +106,8 @@ def place_order(self, order_event):
return

order_event.order_id = self.orderid
order_event.account = self.account
order_event.timestamp = datetime.now().strftime("%H:%M:%S")
self.api.placeOrder(self.orderid, ib_contract, ib_order)
self.order_dict[self.orderid] = order_event
self.orderid += 1
Expand All @@ -114,6 +119,8 @@ def cancel_order(self, order_id):
if not order_id in self.order_dict.keys():
_logger.error(f'Order to cancel not found. order id {order_id}')

self.order_dict[order_id].cancel_time = datetime.now().strftime("%H:%M:%S")

self.api.cancelOrder(order_id)

def cancel_all_orders(self):
Expand Down Expand Up @@ -271,7 +278,7 @@ def contract_to_symbol(ib_contract):
elif ib_contract.secType == 'CASH':
full_symbol = ' '.join([ib_contract.symol+ib_contract.currency, 'CASH', ib_contract.exchange])
elif ib_contract.secType == 'FUT':
full_symbol = ' '.join([ib_contract.localSymbol, 'FUT', ib_contract.exchange])
full_symbol = ' '.join([ib_contract.localSymbol, 'FUT', ib_contract.primaryExchange])

return full_symbol

Expand Down Expand Up @@ -335,7 +342,6 @@ def __init__(self, broker):

self.nKeybInt = 0
self.connected = False
self.nextValidOrderId = None
self.globalCancelOnly = False
self.simplePlaceOid = None

Expand Down Expand Up @@ -389,23 +395,27 @@ def openOrder(self, orderId: OrderId, contract: Contract, order: Order, orderSta
_logger.info(msg)
self.broker.log(msg)

order_event = InteractiveBrokers.ib_order_to_order(order)
order_event.order_id = orderId
if orderId in self.broker.order_dict.keys():
order_event = self.broker.order_dict[orderId]
else: # not placed by algo
order_event = InteractiveBrokers.ib_order_to_order(order)
order_event.order_id = orderId
order_event.full_symbol = InteractiveBrokers.contract_to_symbol(contract)
order_event.account = self.broker.account
order_event.source = -1 # unrecognized source
self.broker.order_dict[orderId] = order_event

if orderState.status == 'Submitted':
order_event.order_status = OrderStatus.SUBMITTED
elif orderState.status == 'Filled':
order_event.order_status = OrderStatus.FILLED
elif orderState.status == 'PreSubmitted':
order_event.order_status = OrderStatus.PENDING_SUBMIT
elif orderState.status == 'Cancelled':
order_event.order_status = OrderStatus.CANCELED
else:
order_event.order_status = OrderStatus.UNKNOWN

if orderId in self.broker.order_dict.keys():
order_event.full_symbol = self.broker.order_dict[orderId].full_symbol
else: # not placed by algo
order_event.full_symbol = InteractiveBrokers.contract_to_symbol(contract)
self.broker.order_dict[orderId] = order_event.full_symbol

self.broker.event_engine.put(copy(order_event))

def openOrderEnd(self):
Expand All @@ -425,17 +435,28 @@ def orderStatus(self, orderId: OrderId, status: str, filled: float,
_logger.info(msg)
self.broker.log(msg)

order_event = self.broker.order_dict.get(OrderId, None)
if not order_event is None:
if status == 'Submitted':
order_event.order_status = OrderStatus.SUBMITTED
elif status == 'Filled':
order_event.order_status = OrderStatus.FILLED
elif status == 'PreSubmitted':
order_event.order_status = OrderStatus.PENDING_SUBMIT
else:
order_event.order_status = OrderStatus.UNKNOWN
order_event.fill_size = filled
order_event = self.broker.order_dict.get(orderId, None)
if order_event is None:
order_event = OrderEvent()
order_event.order_id = orderId
# order_event.full_symbol = InteractiveBrokers.contract_to_symbol(contract)
order_event.account = self.broker.account
order_event.source = -1 # unrecognized source
self.broker.order_dict[orderId] = order_event

if status == 'Submitted':
order_event.order_status = OrderStatus.SUBMITTED
elif status == 'Filled':
order_event.order_status = OrderStatus.FILLED
elif status == 'PreSubmitted':
order_event.order_status = OrderStatus.PENDING_SUBMIT
elif status == 'Cancelled':
order_event.order_status = OrderStatus.CANCELED
order_event.fill_size = filled # remaining = order_size - fill_size
order_event.cancel_time = datetime.now().strftime("%H:%M:%S")
else:
order_event.order_status = OrderStatus.UNKNOWN
order_event.fill_size = filled

self.broker.event_engine.put(copy(order_event))

Expand Down Expand Up @@ -465,6 +486,8 @@ def updateAccountValue(self, key: str, val: str, currency: str,
msg = f'UpdateAccountValue. Key: {key}, Value: {val}, Currency: {currency}, AccountName: {accountName}'
_logger.info(msg)

self.broker .account_summary.timestamp = datetime.now().strftime("%H:%M:%S")

if key == 'NetLiquidationByCurrency' and currency == 'USD':
self.broker.account_summary.balance = float(val)
elif key == 'NetLiquidation' and currency == 'USD':
Expand Down Expand Up @@ -503,6 +526,7 @@ def updatePortfolio(self, contract: Contract, position: float,
position_event.average_cost = averageCost / multiplier
position_event.realized_pnl = realizedPNL
position_event.unrealized_pnl = unrealizedPNL
position_event.timestamp = datetime.now().strftime("%H:%M:%S")
self.broker.event_engine.put(position_event)

def updateAccountTime(self, timeStamp: str):
Expand Down Expand Up @@ -795,6 +819,10 @@ def contractDetails(self, reqId: int, contractDetails: ContractDetails):
super().contractDetails(reqId, contractDetails)
if reqId in self.broker.contract_detail_request_contract_dict.keys():
self.broker.contract_detail_request_contract_dict[reqId] = contractDetails.contract
self.broker.sym_contract_dict[self.broker.contract_detail_request_symbol_dict[reqId]] = contractDetails.contract
self.broker.contract_symbol_dict[contractDetails.contract.conId] = self.broker.contract_detail_request_symbol_dict[reqId]
else:
_logger.error(f'Orphaned contract details request {reqId}, {contractDetails.underSymbol}')

def bondContractDetails(self, reqId: int, contractDetails: ContractDetails):
super().bondContractDetails(reqId, contractDetails)
Expand Down Expand Up @@ -888,21 +916,22 @@ def execDetails(self, reqId: int, contract: Contract, execution: Execution):
f"Currency: {contract.currency}, {execution}"
_logger.info(msg)

if execution.orderId in self.broker.order_dict.keys():
full_symbol = self.broker.order_dict[execution.orderId]
else: # not placed by algo
full_symbol = InteractiveBrokers.contract_to_symbol(contract)

fill_event = FillEvent()
fill_event.order_id = execution.orderId
fill_event.fill_id = execution.execId
fill_event.fill_price = execution.price
fill_event.fill_size=execution.shares * (1 if execution.side == 'BUY' else -1)
fill_event.fill_size=execution.shares * (1 if execution.side == 'BUY' else -1) # BUY SLD
fill_event.fill_time=datetime.strptime(execution.time, "%Y%m%d %H:%M:%S")
fill_event.exchange = contract.exchange
fill_event.full_symbol = full_symbol
fill_event.account = self.broker.account

if execution.orderId in self.broker.order_dict.keys():
fill_event.full_symbol = self.broker.order_dict[execution.orderId].full_symbol
fill_event.source = self.broker.order_dict[execution.orderId].source
else: # not placed by algo
fill_event.full_symbol = InteractiveBrokers.contract_to_symbol(contract)

self.broker.put(fill_event)
self.broker.event_engine.put(fill_event)

def execDetailsEnd(self, reqId: int):
super().execDetailsEnd(reqId)
Expand Down
34 changes: 14 additions & 20 deletions quanttrading2/gui/ui_account_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ def __init__(self, account_manager, parent=None):
super(AccountWindow, self).__init__(parent)

self.header = ['AccountID',
'Yesterday_Net',
'Net',
'Available',
'Commission',
'Margin',
'Closed_PnL',
'Open_PnL',
Expand Down Expand Up @@ -44,27 +42,23 @@ def update_table(self,account_event):

if account_event.account_id in self._account_ids:
row = self._account_ids.index(account_event.account_id)
self.setItem(row, 1, QtWidgets.QTableWidgetItem(str(account_event.preday_balance)))
self.setItem(row, 2, QtWidgets.QTableWidgetItem(str(account_event.balance)))
self.setItem(row, 3, QtWidgets.QTableWidgetItem(str(account_event.available)))
self.setItem(row, 4, QtWidgets.QTableWidgetItem(str(account_event.commission)))
self.setItem(row, 5, QtWidgets.QTableWidgetItem(str(account_event.margin)))
self.setItem(row, 6, QtWidgets.QTableWidgetItem(str(account_event.closed_pnl)))
self.setItem(row, 7, QtWidgets.QTableWidgetItem(str(account_event.open_pnl)))
self.setItem(row, 8, QtWidgets.QTableWidgetItem(account_event.brokerage))
self.setItem(row, 9, QtWidgets.QTableWidgetItem(account_event.timestamp))
self.setItem(row, 1, QtWidgets.QTableWidgetItem(str(account_event.balance)))
self.setItem(row, 2, QtWidgets.QTableWidgetItem(str(account_event.available)))
self.setItem(row, 3, QtWidgets.QTableWidgetItem(str(account_event.margin)))
self.setItem(row, 4, QtWidgets.QTableWidgetItem(str(account_event.closed_pnl)))
self.setItem(row, 5, QtWidgets.QTableWidgetItem(str(account_event.open_pnl)))
self.setItem(row, 6, QtWidgets.QTableWidgetItem(account_event.brokerage))
self.setItem(row, 7, QtWidgets.QTableWidgetItem(account_event.timestamp))

else:
self._account_ids.insert(0, account_event.account_id)
self.insertRow(0)
self.setItem(0, 0, QtWidgets.QTableWidgetItem(account_event.account_id))
self.setItem(0, 1, QtWidgets.QTableWidgetItem(str(account_event.preday_balance)))
self.setItem(0, 2, QtWidgets.QTableWidgetItem(str(account_event.balance)))
self.setItem(0, 3, QtWidgets.QTableWidgetItem(str(account_event.available)))
self.setItem(0, 4, QtWidgets.QTableWidgetItem(str(account_event.commission)))
self.setItem(0, 5, QtWidgets.QTableWidgetItem(str(account_event.margin)))
self.setItem(0, 6, QtWidgets.QTableWidgetItem(str(account_event.closed_pnl)))
self.setItem(0, 7, QtWidgets.QTableWidgetItem(str(account_event.open_pnl)))
self.setItem(0, 8, QtWidgets.QTableWidgetItem(account_event.brokerage))
self.setItem(0, 9, QtWidgets.QTableWidgetItem(account_event.timestamp))
self.setItem(0, 1, QtWidgets.QTableWidgetItem(str(account_event.balance)))
self.setItem(0, 2, QtWidgets.QTableWidgetItem(str(account_event.available)))
self.setItem(0, 3, QtWidgets.QTableWidgetItem(str(account_event.margin)))
self.setItem(0, 4, QtWidgets.QTableWidgetItem(str(account_event.closed_pnl)))
self.setItem(0, 5, QtWidgets.QTableWidgetItem(str(account_event.open_pnl)))
self.setItem(0, 6, QtWidgets.QTableWidgetItem(account_event.brokerage))
self.setItem(0, 7, QtWidgets.QTableWidgetItem(account_event.timestamp))

36 changes: 14 additions & 22 deletions quanttrading2/gui/ui_fill_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,13 @@ def __init__(self, order_manager, parent=None):

self.header = ['OrderID',
'FillID',
'SID',
'Symbol',
'Name',
'Security_Type',
'Direction',
'Order_Flag',
'Fill_Price',
'Filled',
'Fill_Time',
'Exchange',
'Account',
'Source']
'Account']

self.init_table()
self._order_manager = order_manager
Expand All @@ -42,27 +38,23 @@ def update_table(self,fill_event):
'''
Only add row
'''
if fill_event.broker_fill_id in self._fillids:
if fill_event.fill_id in self._fillids:
row = self._orderids.index(fill_event.broker_order_id)
self.item(row, 9).setText(fill_event.fill_time)
self.item(row, 6).setText(fill_event.fill_time)
print('received same fill twice')
else: # including empty
try:
self._fillids.insert(0, fill_event.broker_fill_id)
self._fillids.insert(0, fill_event.fill_id)
self.insertRow(0)
self.setItem(0, 0, QtWidgets.QTableWidgetItem(str(fill_event.client_order_id)))
self.setItem(0, 1, QtWidgets.QTableWidgetItem(str(fill_event.broker_fill_id)))
self.setItem(0, 2, QtWidgets.QTableWidgetItem(fill_event.full_symbol))
self.setItem(0, 3, QtWidgets.QTableWidgetItem(""))
self.setItem(0, 4, QtWidgets.QTableWidgetItem(""))
self.setItem(0, 5, QtWidgets.QTableWidgetItem('Long' if fill_event.fill_size > 0 else 'Short'))
self.setItem(0, 6, QtWidgets.QTableWidgetItem(self._order_manager.retrieve_order(fill_event.client_order_id).order_flag.name))
self.setItem(0, 7, QtWidgets.QTableWidgetItem(str(fill_event.fill_price)))
self.setItem(0, 8, QtWidgets.QTableWidgetItem(str(fill_event.fill_size)))
self.setItem(0, 9, QtWidgets.QTableWidgetItem(fill_event.fill_time))
self.setItem(0, 10, QtWidgets.QTableWidgetItem(""))
self.setItem(0, 11, QtWidgets.QTableWidgetItem(fill_event.account))
self.setItem(0, 12, QtWidgets.QTableWidgetItem(fill_event.source))
self.setItem(0, 0, QtWidgets.QTableWidgetItem(str(fill_event.order_id)))
self.setItem(0, 1, QtWidgets.QTableWidgetItem(str(fill_event.fill_id)))
self.setItem(0, 2, QtWidgets.QTableWidgetItem(str(fill_event.source)))
self.setItem(0, 3, QtWidgets.QTableWidgetItem(fill_event.full_symbol))
self.setItem(0, 4, QtWidgets.QTableWidgetItem(str(fill_event.fill_price)))
self.setItem(0, 5, QtWidgets.QTableWidgetItem(str(fill_event.fill_size)))
self.setItem(0, 6, QtWidgets.QTableWidgetItem(fill_event.fill_time))
self.setItem(0, 7, QtWidgets.QTableWidgetItem(fill_event.exchange))
self.setItem(0, 8, QtWidgets.QTableWidgetItem(fill_event.account))
except:
print('unable to find order that matches this fill')

Expand Down
4 changes: 2 additions & 2 deletions quanttrading2/gui/ui_main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ def _fill_event_handler(self, fill_event):
self._order_manager.on_fill(fill_event) # update order manager with fill
self._strategy_manager.on_fill(fill_event) # feed fill to strategy
self.fill_window.fill_signal.emit(fill_event) # display
self.order_window.update_order_status(fill_event.client_order_id,
self._order_manager.retrieve_order(fill_event.client_order_id).order_status)
self.order_window.update_order_status(fill_event.order_id,
self._order_manager.retrieve_order(fill_event.order_id).order_status)

def _position_event_handler(self, position_event):
self._position_manager.on_position(position_event) # position received
Expand Down
Loading

0 comments on commit d051bf9

Please sign in to comment.