Execution Algorithms 101

Problem Definition

  • Two variables: Time and Price
  • Liquidity
  • Bid-Ask Spread

A simple algorithm

def buy_sell_logic(self, update):
    # Check if the time limit has exceeded
    if self.watch.ts >= self.exec_request.end_time:
        self._time_exceeded(update)
        return

    if self.om.num_orders() == 0:
        # Send limit order
        order_price = self.book.passive_price(self.buysell, num_ticks=0)
        order = self.om.create_order('L', self.buysell, self.size, order_price)
        self.om.send_order(order)

How to check if we did a good job?

Metrics

  • Arrival Mid Price
  • Arrival Aggressive Price
  • VWAP 
  • TWAP 
  • Implementation Shortfall

Execution Algorithm Improvements

def divide_orders(self):
    self._sub_orders = []
    for i in range(self.num_orders):
        order_size = max(self.size // self._num_orders, 100)
        self._sub_orders.append(order_size) 

def buy_sell_logic(self, update):
    # Check if the time limit has exceeded
    if self.watch.ts >= self.exec_request.end_time:
        self._time_exceeded(update)
            return
    
     # Get the current bucket number
     bucket = self._get_bucket()

     if self.om.num_orders() == 0 and bucket > self._current_bucket:
        # Send limit order
        order_size = self._sub_orders[bucket]
        order_price = self.book.passive_price(self.buysell, num_ticks=0)
        order = self.om.create_order('L', self.buysell, order_size, order_price)
        self.om.send_order(order)

More Improvements

Passive TWAP algorithm

def divide_orders(self):
    self._sub_orders = []
    for i in range(self.num_orders):
        order_size = max(self.size // self._num_orders, 100)
        self._sub_orders.append(order_size)
    
def buy_sell_logic(self, update):
    # Check if the time limit has exceeded
    if self.watch.ts >= self.exec_request.end_time:
        self._time_exceeded(update)
        return

    # Get the latest top price
    order_price = self.book.passive_price(self.buysell, 0)

    if self.om.num_orders() > 0:
        if time_diff >= self._interval:
            # Modify to improve/aggressive price
            self.om.modify_price(self.buysell, order_price)

    # Get the current bucket number
    bucket = self._get_bucket()

    if self.om.num_orders() == 0 and bucket > self._current_bucket:
        # Send limit order
        order_size = self._sub_orders[bucket]
        order_price = self.book.passive_price(self.buysell, num_ticks=0)
        order = self.om.create_order('L', self.buysell, order_size, order_price)
        self.om.send_order(order)

Production setup

  • API server receives the orders and passes them to the run_execs.py process through RabbitMQ.
  • API server maintains the status of the order including the benchmarks.
  • Benchmarks as well as the order status updates are sent from run_execs.py process.

Production setup

Issues with prices

  • Nanex process fetches the live prices. We push the "important" updates in binary format to kafka. (We have not benchmarked this operation.)
  • For NASDAQ, the prices are fetched from Google/Yahoo/Robinhood. This affects both the trading and the benchmarking.
  • There are often issues with the price APIs - creating more issues in reliably measuring the performance.
  • Backtests are likely to have inferior results on average - this is due to the presence of hidden orders in market.

Issues with IB

  • BUY orders have to wait till SELL orders get completed.

APEX results by securities

APEX results by securities

Security Average PNL (bps)
FSTA 6.11
FMAT 5.86
VOX 5.49
VBR 4.61
FIDU 4.27

APEX results by securities

Security Average PNL (bps)
IVV -2.68
VUG -1.45
IVE -1.27
XLE -1.00
REM -0.69

APEX results by date

APEX results by date

Date Total PNL ($)
2017-07-27 4435
2017-08-15 2642
2017-08-23 1725
2017-03-15 1066
​2017-08-18 932

APEX results by date

Date Total PNL ($)
2017-08-28 -2353
2017-06-14 -1964
2017-06-09 -685
2017-06-22 -293
2017-09-06 -267

APEX results by size

Size Average PNL (bps)
<500 1.20
>=500 1.05

Next steps

Execution Algorithms 101

By Hardik Patel

Execution Algorithms 101

  • 853