INFO9202 Choice Of Volatility Market
Proposal
We would like to consume tick data from a cryptocurrency option exchange (Deribit) to build our choice of volatility market representation updated at a given time frequency.
The historical raw tick data is provided as csv files, and each tick (one row in the csv file) contains the below fields.
The fields relevant to us are:
contractName: the symbol of the exchange traded contract: Underlying_ExpiryDate_Strike_OptionTYpe
time: timestamp of the update, in UTC.
msgType: update or snap
update: a best level update of a particular instrument, an update message should be applied on top of the currently maintained snapshot
snap: a snapshot of the whole market, when a snapshot is received, the locally maintained snapshot can be disgarded to avoid error accumulation. When we process a historical data csv file, we need to disgard all updates before the first snapshot.
bestBid: best bid price in unit of BTC (bitcoin)
bestBidAmount: best bid notional, in unit of BTC.
bestBidIV: implied volatility from best bid price.
bestAsk: best ask price in unit of BTC (bitcoin)
bestAskAmount: best ask notional, in unit of BTC.
bestAskIV: implied volatility from best ask price.
markPrice: we can consider this as the mid price.
markIV: implied volatility from the mark price.
underlyingIndex: the underlying futures contract name. Some underlying index starts with ‘SYN.’, this indicate that the underlying Futures contract is not listed, so the underlying Futures price could be an interpolated price. For this project, we do not need to worry about whether the underlying index is synthetic or not.
underlyingPrice: the price underlying futures contract.
lasstPrice: last transaction price of the contract.
open_interest: current open interest of the instrument, in unit of BTC.
We can ignore the rest of the fields in this project.
Step 1. Read input events from CSV
The first step is to complete the CsvFeeder class, that consumes the tick event data. The CsvFeeder class needs to be constructed using the below constructor
CsvFeeder::CsvFeeder(const std::string ticker_filename,
FeedListener feed_listener,
std::chrono::minutes interval,
TimerListener timer_listener)
ticker_filename: the filename of the input csv file,
feed_listener: the function to be called inside Step(), after an update message is loaded,
interval: the time interval to call timer_listener,
timer_listener: the function to be called at a given frequency.
FeedListener and TimerListener are our own types defined as follows.
using FeedListener = std::function[void(const Msg& msg)];
using TimerListener = std::function[void(uint64_t ms_now)];
The class Msg is given in Msg.h. You may modify or extend it. Your main job for step 1 is to complete the step-wise processing functions:
bool ReadNextMsg(std::ifstream& file, Msg& msg) {
if (file.eof()) {
return false;
}
// TODO: your implementation to read file and create the next Msg into the variable msg
return true;
}
Note that multiple rows in the csv files that has exactly the same timestamp is considered as one Msg. ReadNextMsg() should load a complete Msg until timestamp changes. It is possible that timestamp is not in strictly increasing order. But we do not need to make special treatment for this.
Note that the time stamp is parsed to unix epoch time (https://en.wikipedia.org/wiki/Unix_time) in millisecond precision, which is represented as a uint64_t. You can use the function TimeToUnixMS implemented in CsvFeeder.cpp to parse the input string to the Unix epoch timestamp. A test script test_ts_parse.cpp is there for you to test what the parser deos. You can build it using make test_ts_parser.
You may use the function getline (https://www.cplusplus.com/reference/istream/istream/getline/) to read a line from the file, and parse the line in your code by separating each field with “,”. We have also added a constructor to datetime_t that takes a unix epoch timestamp in second (note that the unix is in second, so if you use it with millisecond timestamp, you need to divide it by 1000) to construct our own type datetime_t.
It is also possible that certain fields are empty for some ticks. In that case, you can set the field to NaN using std::numeric_limits::quiet_NaN() defined in header.
Read step1.cpp, which contains a dummy FeedListener that prints basic information of the Msg given, and TimerListener that simply prints the timestamp. Build step1 using make step1 under the project folder. The run it: bin/step1.out . Without the implementation of ReadNextMsg function, the code will compile but will not function properly. Once ReadNextMsg is correctly implemented, step1 should process the input csv file and print out basic information of the input events.
Step 2: Maintain the latest market snapshot
VolSurfBuilder keeps track of the latest snapshot of the option market using the member variable std::map