2020 Fall Competition Case Packet: Traders@mit - Edu Traders - Mit.edu
2020 Fall Competition Case Packet: Traders@mit - Edu Traders - Mit.edu
2020 Fall Competition Case Packet: Traders@mit - Edu Traders - Mit.edu
Case Packet
[email protected]
traders.mit.edu
1 Introduction 4
1.2 Piazza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.5.1 AWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1
2.8 Scoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.9 Advice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3 Fixed Income 10
3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.1 Auctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.4 Limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5 Kirin API 15
5.1.1 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2
5.3 Order Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3
1 Introduction
Our competition consists of electronic trading. Teams will be ranked overall based
on their total weighted rankings from each of the three cases. Between rounds, you will
also have several opportunities to speak with our attending sponsors.
Silver: Barclays, Cubist, D. E. Shaw, Flow Traders, Schonfeld Strategic Advisors, SIG,
Tower Research
The three cases are: High-Frequency Trading, Fixed Income, and the Five Rings Cap-
ital Information Valuation case. The High-Frequency Trading case will be algorithmi-
cally traded using our low-latency C++ exchange, Kirin. Competitors must algorithmi-
cally trade and cannot click trade. You will be expected to submit your code before the
day of the competition.
The two cases held on competition day are Fixed Income and Information Valuation.
Relatively little advance preparation is expected, but we’d recommend familiarizing
yourself with statistical analysis packages in Python and installing relevant packages
on the laptop you’ll be using. More information on the cases can be found in the fol-
lowing sections.
4
1.1 Schedule of Events
Note that all events in this schedule are mandatory for competitors to attend if they
wish to receive dining reimbursements and be eligible for prize money; attendance
will be taken. If this is not possible for you, then please email [email protected]
with a detailed reason as to why you have a conflict with any of the events.
1.2 Piazza
We have created a Piazza forum to answer questions about cases and any other ques-
tions you may have. Most of our updates and announcements will be placed here,
so it is in your best interest to be on this forum. We will be answering all questions
through this forum, and not by email:
https://piazza.com/mit/fall2020/tamit2020
Traders@MIT executive board members will do our best to reply to all questions within
24 hours.
5
2 High-Frequency Trading (HFT)
2.1 Overview
In this case, you will implement a low-latency trading strategy in C++ to trade a single
stock in a standard limit order book. At a high level, you could profit in this case by:
1. Market making (i.e. putting in limit orders around the fair price, in the hopes of
earning the bid-ask spread)
Trading occurs through a limit order book. You place limit orders, which indicate will-
ingness to buy/sell a certain quantity at or below/above a certain price. If your order
matches with limit orders already on the book (i.e. someone had previously indicated
willingness to take a trade in the opposite direction at the price you indicated), then a
trade occurs at the price of the limit order already on the book. The limit orders on the
book are matched to yours in order of best price, with ties broken by earliest time. If the
quantity of your order is not filled completely by such trades, the remaining quantity is
inserted as a limit order into the book, unless it is marked immediate-or-cancel (IOC),
in which case the remaining quantity is discarded.
All participants in the market get updates for all order insertions, cancels, and trades.
6
2.3 Limits
We are imposing position limits on the security: you may not hold more than 2000
shares, or have open orders out that could be filled in a way that would cause you to
hold more than 2000 shares.
To be clear, we will not allow you to submit an order if it and your other open orders
can be filled in a way that allows you to exceed your position limit. For example, you
would not be able to put in a bid for 1500 shares if you already hold 800 shares.
You may not perform more than 10000 actions in any 10-second period, where an action
is an order placement or a cancel. An action will be rejected if 10000 actions have been
performed in the last 10 seconds.
You will not be allowed to have more than 500 open orders. We will reject any order if
you already have 500 open orders out.
You must not use more than 1GB of memory, including the heap and the data segment
of your program. Your process may be killed if you do so. You shouldn’t need to use
anywhere near this much memory for this case.
For you to test your bots before the competition, we will provide you with an object
file containing Kirin that you can use to compile and run your bot.
However, during the actual competition, you will just submit your competitor.cpp
file containing your bot, which will then run in a separate process from Kirin, and will
communicate through shared memory.
The code submission deadline for this case is 11:59pm ET on Thursday, October 5, 2020.
We will run and score each team’s submission before the competition, and announce
the result on competition day.
7
2.5 AWS and Building Kirin
2.5.1 AWS
Before accessing your AWS instance, you’ll need to start it using our web interface
(instructions on Piazza). Afterward, use the IP address and password provided to you
via email. In a terminal, type:
ssh ec2-user@{ip}
But replace {ip} the the IP address which you received from us (e.g. 68.53.237.147).
Depending on your machine, you may have to install software that will let you use
ssh. Additionally, if you would like to develop in a local text editor without having
to transfer files to and from your AWS instance, we recommend checking out sshfs or
Unison.
These commands should be run in separate terminal sessions (unless you want to
run Kirin in the background). The main method we have written in competitor.cpp
will register your bot and run the case for infinitely long.
In a third terminal session (or another background process), you can run python3
print_book.py, which periodically prints the book logged by our sample code in book.log.
You will want to edit the various callbacks we have provided you for market updates
etc. in the MyBot class in competitor.cpp. Search for EDIT THIS METHOD in the file to
see where to go. We have provided a lot of code for maintaining the state of the order
book, your open orders, etc. in the MyState class. Feel free to edit this class (there may
be benefits to improving its performance) or get rid of it entirely.
There is some sample code in the MyBot class that shows you how to place and cancel
orders.
8
2.6.1 Callback Model
See the sample code already in competitor.cpp for examples, and see the API in Sec-
tion 5. There is only one stock being traded in this case, and it is denoted with .ticker
= 0 in orders/cancels. Note that the sample code hardly qualifies as a strategy and is
just for demonstrational purposes.
Orders must have strictly positive prices and quantities. Cancels must have a valid
order ID that you are the owner of.
The code we have provided runs indefinitely. The most relevant statistic is PNL per
second, which we print out in the sample code every time your bot makes a trade. You
should be aiming to get hundreds of dollars per second.
2.8 Scoring
Every round will be a 1v1 with another team and will last exactly 60 seconds. At the
end of the round, the team with the higher PnL wins. We will run a simple round robin,
and rank the teams by number of wins. We will then run a final round with the top 10
teams running simultaneously to determine the overall results.
2.9 Advice
For determining signals, you should be looking at the order book (quantities, prices)
and how it changes in time, and trades (directions, quantities, prices) and how they
occur over time.
The market dynamics of this case will differ markedly when you are competing against
other teams compared to when you test by yourself. Note that you are essentially
competing to exploit the same inefficiencies created by our internal bots.
Thus, you want your code to be robust to different market conditions (e.g. a tighter
spread). Additionally, engineering your code to be low-latency will help you beat other
teams. One way to test the effect of latency is to run a slow version of your bot against
a fast version of your bot.
9
3 Fixed Income
3.1 Overview
In this case, you will manually trade bonds. Your goal will be to maximize the amount
of money you make in a given round relative to other teams in your exchange.
There will be three ways to participate in trades: bidding in auctions, trading with
other competitors, and providing to customers.
3.2.1 Auctions
The primary way to acquire bonds is by bidding in auctions. Each year, you can place
bids for any bond expiring at most N years from the current year (N is to be deter-
mined). Each bid will only specify a size (or amount of notional). At the end of the
year, all auctions will be conducted, and bonds will be allocated to teams based on
their bids.
Each bond auction is at a fixed price (or yield), and has a certain size (amount of no-
tional) available. For a given bond auction, if the sum of all teams’ bids is less than the
size available, then all teams will receive the amount they bid for that bond. Otherwise,
each team will receive an amount proportional to their bid.
For example, suppose a bond X expiring in 2020 is up for auction with $100000 no-
tional available. If the bids are as follows:
• Team 1: $20000
• Team 2: $30000
• Team 3: $40000
then each team will receive their bid amount in notional of X expiring 2020.
10
However, if the bids are as follows:
• Team 1: $60000
• Team 2: $70000
• Team 3: $70000
then since the total sum of bids is $200000, the payout will be as follows:
You will also be able to trade with other teams on an open market.
Trading occurs through a limit order book. You place limit orders, which indicate will-
ingness to buy (sell) a certain amount of notional at or above (below) a certain yield.
Note that yield is inversely related to price. If your order matches with limit orders
already on the book (i.e. someone had previously indicated willingness to take a trade
in the opposite direction at the yield you indicated), then a trade occurs at the yield of
the limit order already on the book (the limit orders on the book are matched to yours
in order of best yield, with ties broken by earliest time). If the quantity of your order is
not filled completely by such trades, the remaining quantity is inserted as a limit order
into the book.
All prices are multiples of 0.1% (subject to change), referred to as one tick.
Periodically, customers will ask to buy certain bonds from you. These customers will
appear to different teams at different times, and will be announced to your team the
year before the order is available.
11
3.3 Information about Bonds
A bond is a financial instrument that pays out a fixed coupon every year until maturity
(as a percentage of its notional value), and pays out its notional value at expiration. For
example, if you own $100 notional of a bond with a 2% coupon expiring 5 years from
now, you will receive $2 every year for the next five years and $100 in five years (along
with the coupon payment for that year). So, you will receive $110 total over five years.
• $2 after 1 year
• $2 after 2 years
• $2 after 3 years
• $2 after 4 years
The notional value of a bond is just a face value used to calculate its payout structure,
and is not related to how much you might pay for the bond, as bonds are tradeable on
the market. If you pay some amount for a bond, then the average rate your money
grows at based on the payout structure is the yield for that bond. So, yield is inversely
related to price, and is just another way to state the price. However, you will trade
bonds by specifying a yield (in percent), rather than by specifying a price in dollars.
For a bond expiring in T years, a notional amount N, and a coupon payment C per
year, the price P is related to the yield Y (in percent) by the following formula:
C C C C+N
P= + +···+ −
+ .
1 + Y/100 (1 + Y/100) 2 (1 + Y/100) T 1 (1 + Y/100)T
The coupon fraction is C/N. So if the bond had a 2% coupon, then C/N would be
0.02. Note that P is approximately N for low values of C and Y. For the above bond
($100 notional with 2% coupon expiring in 5 years), if you buy it at a 2% yield, you pay
2 2 2 2 102
P= + + + + = 100.
1.02 1.022 1.023 1.024 1.025
This equality makes sense; if the yield is equal to the coupon, you pay the notional
amount. For a yield > 2%, you would pay < $100.
Because yield is inversely related to price, buying a bond at a low yield is akin to
buying it for a high price. Note that yield can be negative. The market for a bond then
has buy orders at higher yields than sell orders.
12
3.4 Limits
The sum of the notionals in all your open buy orders and bids cannot exceed the
amount of capital you have. Also, the amount of notional in open sell orders for a
bond cannot exceed the amount of that bond you possess. You will be prevented from
making orders or bids that violate these bounds.
We will send specific case details the day before the competition. The case will be held
on Discord. Please make a Discord account if you do not already have one and submit
your username using this form:
https://tinyurl.com/traders2020discord
13
4 Five Rings Information Valuation
4.1 Overview
For the Information Valuation case, you will have the opportunity to buy and sell as-
sets, as well as the opportunity to buy certain data sources that may or may not predict
price movement. Your goal will be to build a bot that uses the purchasable data to
make good trades. To do so, you will need to determine which data sources are useful
and what predictive models work best.
You will not receive any training or testing data to begin. All data must be purchased
via your bot. There is no bid-ask spread, and you will not be trading against other
competitors. Instead, we will run your strategy on a test data set, and your goal is to
maximize your profit over all time steps.
In this case, you will periodically submit a Python bot that executes your strategy for
you. We will provide some starter code for convenience, though you will be expected
to write Python code (both to improve your bot, and to analyze results). Code perfor-
mance is not a priority, though particularly slow submissions may be disqualified.
Once you submit your bot for a round, your bot will be evaluated on many timesteps.
As feedback, you will receive your profits for that round, price data, and the specific
data you chose to buy. You will then be able to use this information to improve your
bot for the next round. The event will last 2-2.5 hours, with each round lasting 5-30
minutes.
A more detailed case packet will be made available at the beginning of the case. You are
not expected to work on this case before the competition, though familiarity with data
science packages (e.g. matplotlib, sklearn, and numpy) as well as Jupyter notebooks,
is recommended.
14
5 Kirin API
Kirin uses a callback mechanism to deliver updates to your bot about the market. You
can find these callbacks in MyBot in competitor.cpp, and you are responsible for im-
plementing them. The callbacks mechanism are implemented in AbstractBot, which
internally polls our system for market updates and delivers to you with the appropriate
call back.
It’s important to recognize that every update on the market from other people are for-
warded to your callbacks, not just your activities.
It’s important that calls backs return since everything in your bot is single threaded,
and you won’t get another update until a call back that is invoked returns.
Each callback takes Bot::Communicator& object which is what you use to submit and
cancel orders. You are allowed to submit orders any time.
We describe the types of call back below. For more details, refer to competitor.cpp
where sample usage is outlined. You can find the definition of structs used in the
callbacks in kirin.hpp.
5.1.1 Initialization
You should use this callback to initialize your bot with state. Its only called once at the
beginning of the case.
15
This is called every time an order happens on Kirin. The update object is a struct that
contains the ticker, price, and quantity.
Layout of OrderUpdate:
struct OrderUpdate {
ticker_t ticker; // ticker symbol (0 for HFT 2019)
price_t price; // price of order
quantity_t quantity; // quantity of order
order_id_t order_id; // order id, unique across all orders
bool buy; // direction of buy
}
struct RejectOrderUpdate {
ticker_t ticker;
order_id_t order_id; // order id that was rejected
RejectReason reason; //reason for rejection
}
This is called every time a trade happens on the the market and the update contains
which orders traded, at what price and quantity.
struct TradeUpdate {
ticker_t ticker;
price_t price;
quantity_t quantity; //quantity traded
order_id_t resting_order_id; // order id that was already on the book
order_id_t aggressing_order_id; // order id that arrived and traded
bool buy; // direction of aggressing order
}
16
5.1.5 Cancel Updates
Called when a cancel is accepted on Kirin. This is the struct layout for Cancel Update:
struct CancelUpdate {
ticker_t ticker;
order_id_t order_id; // order id that was canceled
}
Called when a cancel is rejected on Kirin. Possible reasons for rejection could be that
the order is not active on Kirin, order limits have been exceeded, etc.
struct RejectCancelUpdate{
ticker_t ticker; // ticker
order_id_t order_id; // order id of rejected cancel
RejectReason reason; // reason for rejection
}
Messages are delivered as packets to our internal system. A packet can contain multi-
ple order/trade updates.
The callbacks noted above take in a Communicator object, which you can use to submit
/ cancel orders.
17
5.2.1 Submitting Order
Places an order to Kirin. The order struct has an extra member "trader_id" compared
to the struct OrderUpdate. You should set this to your trader id, otherwise you will get
OrderReject callbacks.
Places a cancel to Kirin. The cancel struct has an extra member "trader_id" compared
to struct OrderUpdate. You should set this to your trader id, otherwise you will get
CancelReject callbacks.
The provided MyBot implementation also maintains an order book per ticker. You have
full freedom to implement your own order book. If you want to use the one we pro-
vided, make sure to maintain the calls to it in the callbacks. The order book provides
functionality to get:
Best price:
price_t get_bbo(bool buy) // current best price to buy stock if "buy" is true, or to
sell if buy is false.
Mid price:
18
Quote Size:
quantity_t quote_size(bool buy) //returns quote size on the side of buy provided
Spread:
19