Skip to content
Michael Grosner edited this page Aug 9, 2015 · 17 revisions

What is Market Making?

Market making is a trading strategy where the trader simultaneously places both buy and sell orders in an attempt to profit from the bid-ask spread. Market makers stand ready to both buy and sell from other traders, thus providing liquidity to the market.

The strategy is appealing to traders because it doesn't require traders to take a directional view of the market - there's money to be made when the market goes up and when the market goes down. It's also heavily incentivized by exchanges looking for liquidity and volume - many exchange operators will pay you to make markets on their exchanges.

An example

Lets consider a simplified market. Lets say there is three traders: Alice, Bob, and Tim. Alice is looking to sell some of her Bitcoins and Bob is looking to convert some of his Bitcoin into USD. Neither one are savvy about markets or cryptocurrency - they use Bitcoin, but aren't going to lose sleep over trying to get the absolute best prices. Tim is operating Tribeca. Now lets say that the price BTC to USD is $100. Tim could configure tribeca to send in a buy order for 1 BTC at $95 and a sell order for 1 BTC at $105. Tim would hope that Bob would come along and buy the offered sell order at $105 and Alice would come and sell BTC at $95 - netting Tim $10.

But what if that doesn't happen? What if the price of BTC/USD jumps to $103? Now Tim's buy order seems really uncompetitive at $95 - Alice doesn't want to sell for that little. And Bob could get a pretty good deal by getting the BTC at only two extra dollars. To prevent this scenario, Tim's tribeca would readjust the orders by canceling the $95-$105 orders and placing a new set of orders - also known as making a market - at $98-$108.

Like in any market these days, Bob and Alice probably aren't humans clicking buttons. They certainly aren't humans shouting on a floor in lower Manhattan. More likely, they are also computerized algorithms capable of placing orders in milliseconds. To survive as a market maker, you need to be faster than those algorithms to make a profit.

So, how does tribeca work?

As I mentioned above, market making is really the art of figuring out the price of something, then making a market around that price. So how do we know what is the real price of Bitcoin? Well... we don't. And of course the price of Bitcoin now might be radically different than the price in a day, in an hour, or even in a second from now. The best we can do is to build an estimate, or fair value, of the price of Bitcoin. In tribeca, we consume the market data from the exchange we are sending orders into as a starting point. That includes the best bids and offers and most recent trades (aka market trades) by other participants in the market.

From our fair value, we then need to make a market around that price. Back to our hypothetical example with Bob and Alice: we could make our market as $95-$105, we could have also made it $99.99-$101.01, or we could have also done $47-$332.21. So how do we decide? That's where the quoting parameters come into play. Those parameters dictate how wide of a market to make (wide=askPrice-bidPrice) and what size we want our quotes in the market to be. The procedure for coming up with profitable parameters is both an art and a science - there is no one size fits all formula.

When tribeca figures out a suitable market, tribeca will then send in the buy and sell orders. Hopefully it's able to buy for less then sell for more, and repeat many times per day. Sometimes that's not always the case - sometimes there are genuinely more buyers than sellers for the prices you are setting. Often this comes when the market is moving very fast in one direction. Luckily, tribeca will prevent you from selling too fast without finding corresponding buyers and will stop sending orders in the imbalanced side.

Where does all this happen in the code?

The code is organized into 3 layers.

  1. Engine layer - The brains of the application. Portion of the code responsible for synthesizing market data, open order status, position, fees, trades, safety information and converting that into a quote to send to the exchange. This is the portion of the code which calculates a fair value (FairValueEngine) and generates quotes (QuotingEngine)

  2. Adapter layer - The engine layer should have no idea about the individual quirks of the exchanges. The engine layer uses the adapter layer to carry out its bidding. The adapter layer also has no idea that it is being used in a manner to make markets. In theory, the adapter layer code and the gateway layer code could be divorced from the Engine layer and we could build a technical analysis or latency arbitrage bot, instead. The adapter layer also contains all the state reported by the gateways.

  3. Gateway layer - Each exchange has a their own API for interacting with the exchange. All of that business is hidden behind 4 different interfaces:

  • IMarketDataGateway: Handles order book updates and market trade updates.
  • IOrderEntryGateway: Send and cancel orders and handle updates to the orders.
  • IPositionGateway: Pulls in the latest position (how much BTC and USD do I have?) information
  • IExchangeDetailsGateway: Read-only information describing naming and exchange fee structure.

Gateways are ideally stateless (some state may be needed in order to perform exchange-specific functionality) and are mostly translation layers between exchange APIs and the tribeca API.

How do I see what's going on?

How do I control tribeca's quotes?

In the web UI, there is two rows of panels with cryptic looking names and editable textboxes. Those are the quoting parameters, the knobs which we can turn to affect how tribeca will trade.

  • mode - Sets the quoting mode

    • Join - Sets our quote to be at the best bid and the best offered price, If the BBO is narrower than width, set our bid quote at FV - width / 2 and ask quote at FV + width / 2.

    • Top - Same as Join, but if the the code can better the best bid or offer by a penny and not violate width, set that as the quote so we will then be at the top of the market.

    • Mid - Set our bid quote at FV - width / 2 and ask quote at FV + width / 2

    • Inverse Join - Set the quote at the BBO if the BBO is narrower than width, otherwise make the quote so wide that no one will trade with it.

    • Inverse Top - Same as Inverse Join but make our orders jump to the very top of the order book.

  • fv - Sets the fair value calculation mode

    • BBO - FV = ([best bid price] + [best ask price])/2.0

    • wBBO - FV = ([best bid price]*[best ask size] + [best ask price]*[best bid size])/([best ask size] + [best bid size])

  • apMode

    • Off - tribeca will not try to automatically manage positions.

    • EwmaBasic - tribeca will use a 200 minute and 100 minute exponential weighted moving average calculation to buy up BTC when the 100 minute line crosses over the 200 minute line, and sell BTC when the reverse happens. The values of 100mins and 200mins are currently not exposed in the UI, but are represented in the code as shortEwma and longEwma.

  • width - Minimum width of our quote in USD (ex. a value of .3 is 30 cents). With the exception for when apr is checked and the system is aggressively rebalancing positions after they get out of whack, width shall never be violated.

  • size - Maximum size of our quote in BTC (ex. a value of 1.5 is 1.5 bitcoins). With the exception for when apr is checked and the system is aggressively rebalancing positions after they get out of whack, size shall never be violated.

  • tbp - Only used when apMode is Off. Sets a static "Target Base Position" for tribeca to stay near. In off auto-position mode, tribeca will still try to respect pDiv and not make your position fluctuate by more than that value. So if you have 10 BTC to trade, set tbp = 3, set apMode = Off, and pDiv = 1, your holding of BTC will never be less than 2 or greater than 4.

  • pDiv - If your "Target Base Position" diverges more from this value, tribeca will stop sending orders to stop too much directional trading. So if you have 10 BTC to trade, "Target Base Position" is reporting 5, and pDiv is set to 3, your holding of BTC will never be less than 2 or greater than 8.

  • ewma? - Use a 100 minute EWMA smoothed line of the price to not send

  • apr? - If you're in a state where tribeca has stopped sending orders because your position has diverged too far from Target Base Position, this setting will much more aggressively try to fix that discrepancy by placing orders much larger than size and at prices much more aggressive than width normally allows. It's a bit risky to use this setting.

  • trds - Often, only buying or selling many times in a short timeframe indicates that there is going to be a price swing. trds and /sec are highly related: If you do more than trds buy trades in /sec seconds, tribeca will stop sending more buy orders until either /sec seconds has passed, or you have sold enough at a higher cost to make all those buy orders profitable. The number of trades is reported by side in the UI; "BuyTS", "SellTS", and "TotTS". If "BuyTS" goes above trds, tribeca will stop sending buy orders, and the same for sells. For example, if trds is 2 and /sec is 1800 (half an hour):

Time | Side | Price | Size | BuyTS | SellTS | Notes -------- |------|-------|------|-------|--------| 12:00:01 | Buy | 10 | 1 | 1 | 0 | 12:00:02 | Buy | 10 | 0.5 | 1.5 | 0 | Partial fills of size get counted fractionally 12:00:03 | Sell | 11 | 0.75 | 0.75 | 0 | Sell for more decrements the imabalance 12:00:05 | Sell | 5 | 0.75 | 0.75 | 0 | Sell for less than the other buys doesn't help 12:00:06 | Buy | 10 | 0.5 | 1.75 | 0 | 12:00:07 | Buy | 10 | 0.5 | 2.75 | 0 | Stop sending buy orders!

  • /sec - see trds

How do I manage risk?

How can I test new trading strategies?

Tribeca is packaged with a backtesting mode.

Clone this wiki locally