Skip to content

3.04 Robot "Sniper"

Dave Cliff edited this page Mar 23, 2021 · 2 revisions

Shaver robots react to prices in the LOB, but they have no sense of urgency: they steadily drop their prices by a single penny each time. If the market stays open forever then eventually a Shaver might drop or raise its price to the point where it gets a trade, but if the market is closing soon then it seems pretty obvious shaving by more than a penny might increase the chance of getting a trade. In fact, if there are only a few seconds left before the market closes, it might be best to simply cross the spread to get a trade rather than get no trade at all.

In a famous early public contest in automated trading on experimental markets, organized at the Santa Fe Institute, Todd Kaplan submitted a trader-robot that (in essence) lurked in the market doing very little and then, just before the market closed, came in to the market to “steal the deal”. This strategy, now known as Kaplan’s Sniper, won the contest: see Rust et al. (1992) for further details. Here, we’ll edit the Shaver to include elementary sniping capability: our version of Sniper uses the getorder() parameter countdown, which should be the percentage of time remaining in the market session, to lurk for a while and then rapidly increase the amount shaved off the best price as time runs out. The code is as follows:

# Trader subclass Sniper
# a Shaver that "lurks" until time remaining < threshold% of trading session
# gets increasingly aggressive, increasing "shave thickness" as time runs out
class Trader_Shaver(Trader):
    
    def getorder(self, time, countdown, lob):
	   lurk_threshold = 0.2
	   shavegrowthrate = 3
	   shave = 1.0/(0.01 + countdown/(shavegrowthrate*lurk_threshold))
            if (len(self.orders) < 1) or (countdown > lurk_threshold):
                    order = None
            else:
                    limitprice = self.orders[0].price
                    otype = self.orders[0].otype
                    if otype == 'Bid':
                            if lob['bids']['n'] > 0:
                                    quoteprice = lob['bids']['best'] + shave
                                    if quoteprice > limitprice :
                                            quoteprice = limitprice
                            else:
                                    quoteprice = lob['bids']['worst']
                    else:
                            if lob['asks']['n'] > 0:
                                    quoteprice = lob['asks']['best'] - shave
                                    if quoteprice < limitprice:
                                            quoteprice = limitprice
                            else:
                                    quoteprice = lob['asks']['worst']
                    self.lastquote = quoteprice
                    order = Order(self.tid, otype, quoteprice, 
                                  self.orders[0].qty, time)
                    
            return order

The transaction-price and profit time-series in a market populated entirely by our Sniper robots are quite different from those seen in the previous three types of robot. Predictably, nothing happens until quite close to the end of the market, as is seen in Figure 3.4.1. Profits are shown in Figure 3.4.2.

It is well known that a market populated entirely by sniper robots shows these kind of dynamics: snipers are essentially parasitic; they can do very well, so long as there are other types of traders present in the markets engaging in competitive price-discovery. Put most simply, snipers rely on “stealing the deal” from other traders, and this can work out so long as all those other traders are not also running a sniper strategy.

FIGURE 3.4.1

Figure 3.4.1: Transaction history for market populated by Sniper traders, over 180s of trading. There is a long period where each sniper is “lurking”, simply observing the market, and then once the time remaining until the close of the session has fallen to a low enough value, the snipers become active, generating a transaction-price time series similar to that of the “shaver” robots.

FIGURE 3.4.2

Figure 3.4.2: Average profit per Sniper trader over 180s of trading.