Add Initial commit for further testing

This commit is contained in:
Lev
2021-06-12 10:36:26 -05:00
parent 440e744ef8
commit 01becd46fa
12 changed files with 4151 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,106 @@
#include "CSVReader.h"
#include <iostream>
#include <fstream>
CSVReader::CSVReader()
{
}
std::vector<OrderBookEntry> CSVReader::readCSV(std::string csvFilename)
{
std::vector<OrderBookEntry> entries;
std::ifstream csvFile{csvFilename};
std::string line;
if (csvFile.is_open())
{
while(std::getline(csvFile, line))
{
try {
OrderBookEntry obe = stringsToOBE(tokenise(line, ','));
entries.push_back(obe);
}catch(const std::exception& e)
{
//std::cout << "CSVReader::readCSV bad data" << std::endl;
}
}// end of while
}
std::cout << "CSVReader::readCSV read " << entries.size() << " entries" << std::endl;
return entries;
}
std::vector<std::string> CSVReader::tokenise(std::string csvLine, char separator)
{
std::vector<std::string> tokens;
signed int start, end;
std::string token;
start = csvLine.find_first_not_of(separator, 0);
do{
end = csvLine.find_first_of(separator, start);
if (start == csvLine.length() || start == end) break;
if (end >= 0) token = csvLine.substr(start, end - start);
else token = csvLine.substr(start, csvLine.length() - start);
tokens.push_back(token);
start = end + 1;
}while(end > 0);
return tokens;
}
OrderBookEntry CSVReader::stringsToOBE(std::vector<std::string> tokens)
{
double price, amount;
if (tokens.size() != 5) // bad
{
//std::cout << "Bad line " << std::endl;
throw std::exception{};
}
// we have 5 tokens
try {
price = std::stod(tokens[3]);
amount = std::stod(tokens[4]);
}catch(const std::exception& e){
std::cout << "CSVReader::stringsToOBE Bad float! " << tokens[3]<< std::endl;
std::cout << "CSVReader::stringsToOBE Bad float! " << tokens[4]<< std::endl;
throw;
}
OrderBookEntry obe{price,
amount,
tokens[0],
tokens[1],
OrderBookEntry::stringToOrderBookType(tokens[2])};
return obe;
}
OrderBookEntry CSVReader::stringsToOBE(std::string priceString,
std::string amountString,
std::string timestamp,
std::string product,
OrderBookType orderType)
{
double price, amount;
try
{
price = std::stod(priceString);
amount = std::stod(amountString);
}
catch(const std::exception& e)
{
std::cout << "CSVReader::stringsToOBE Bad float!" << priceString << std::endl;
std::cout << "CSVReader::stringsToOBE Bad float!" << amountString << std::endl;
throw;
}
OrderBookEntry obe{price,
amount,
timestamp,
product,
orderType};
return obe;
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "OrderBookEntry.h"
#include <vector>
#include <string>
class CSVReader
{
public:
CSVReader();
static std::vector<OrderBookEntry> readCSV(std::string csvFile);
static std::vector<std::string> tokenise(std::string csvLine, char separator);
static OrderBookEntry stringsToOBE(std::string price,
std::string amount,
std::string timestamp,
std::string product,
OrderBookType orderType);
private:
static OrderBookEntry stringsToOBE(std::vector<std::string> strings);
};

View File

@ -0,0 +1,203 @@
#include "MerkelMain.h"
#include <iostream>
#include <vector>
#include "OrderBookEntry.h"
#include "CSVReader.h"
#include <limits>
MerkelMain::MerkelMain()
{
}
void MerkelMain::init()
{
int input;
currentTime = orderBook.getEarliestTime();
while (true)
{
printMenu();
input = getUserOption();
processUserOption(input);
}
}
void MerkelMain::printMenu()
{
// 1 print help
std::cout << "1: Print help " << std::endl;
// 2 print exchange stats
std::cout << "2: Print exchange stats" << std::endl;
// 3 make an offer
std::cout << "3: Make an ask " << std::endl;
// 4 make a bid
std::cout << "4: Make a bid " << std::endl;
// 5 print wallet
std::cout << "5: Print wallet " << std::endl;
// 6 continue
std::cout << "6: Continue " << std::endl;
std::cout << "============== " << std::endl;
std::cout << "Current time is " << currentTime << std::endl;
}
void MerkelMain::printHelp()
{
std::cout << "Help - your aim is to make money. Analyse the market and make bids and offers. " << std::endl;
}
void MerkelMain::printMarketStats()
{
// for product Asks
// for (std::string const p : orderBook.getKnownProducts())
// {
// std::cout << "Product: " << p << std::endl;
// std::vector<OrderBookEntry> entries = orderBook.getOrders(OrderBookType::ask, p, currentTime);
// std::cout << "Asks for product " << p << " are " << entries.size() << std::endl;
// std::cout << "Max ask for " << p << " is " << orderBook.getHighPrice(entries) << std::endl;
// std::cout << "Min ask for " << p << " is " << orderBook.getLowPrice(entries) << std::endl;
// }
// for product Bids
for (std::string const p : orderBook.getKnownProducts())
{
std::cout << "Product: " << p << std::endl;
std::vector<OrderBookEntry> entries = orderBook.getOrders(OrderBookType::bid, p, currentTime);
std::cout << "Bids for product " << p << " are " << entries.size() << std::endl;
std::cout << "Max bid for " << p << " is " << orderBook.getHighPrice(entries) << std::endl;
std::cout << "Min bid for " << p << " is " << orderBook.getLowPrice(entries) << std::endl;
}
// Overall stats
// std::cout << "OrderBook contains : " << orders.size() << " entries" << std::endl;
// unsigned int bids = 0;
// unsigned int asks = 0;
// for (OrderBookEntry& e : orders)
// {
// if (e.orderType == OrderBookType::ask)
// {
// asks ++;
// }
// if (e.orderType == OrderBookType::bid)
// {
// bids ++;
// }
// }
// std::cout << "OrderBook asks: " << asks << " bids:" << bids << std::endl;
}
void MerkelMain::enterAsk()
{
std::cout << "Make an ask (product, price, amount. e.g. 'ETH/BTC, 125, 0.5'): " << std::endl;
std::string input;
std::getline(std::cin, input);
std::vector<std::string> tokens = CSVReader::tokenise(input, ',');
if (tokens.size() != 3)
{
std::cout << "MerkelMain::enterAsk - Bad input!" << input << std::endl;
}
else
{
try
{
OrderBookEntry obe = CSVReader::stringsToOBE(tokens[1], tokens[2], currentTime, tokens[0], OrderBookType::ask);
orderBook.insertOrder(obe);
}
catch (const std::exception &e)
{
std::cout << "MerkelMain::enterAsk - Bad input!" << input << std::endl;
}
}
//std::cout << "You typed: " << input << std::endl;
}
void MerkelMain::enterBid()
{
std::cout << "Make a bid (product, price, amount. e.g. 'ETH/BTC, 150, 0.5'): " << std::endl;
std::string input;
std::getline(std::cin, input);
std::vector<std::string> tokens = CSVReader::tokenise(input, ',');
if (tokens.size() != 3)
{
std::cout << "MerkelMain::enterBid - Bad input!" << input << std::endl;
}
else
{
try
{
OrderBookEntry obe = CSVReader::stringsToOBE(tokens[1], tokens[2], currentTime, tokens[0], OrderBookType::bid);
orderBook.insertOrder(obe);
}
catch (const std::exception &e)
{
std::cout << "MerkelMain::enterAsk - Bad input!" << input << std::endl;
}
}
}
void MerkelMain::printWallet()
{
std::cout << "Your wallet is empty. " << std::endl;
}
void MerkelMain::gotoNextTimeframe()
{
std::cout << "Going to next time frame. " << std::endl;
std::vector<OrderBookEntry> sales = orderBook.matchAsksToBids("ETH/BTC", currentTime);
std::cout << "Sales: " << sales.size() << std::endl;
for(OrderBookEntry& sale : sales)
{
std::cout << "Sale price: " << sale.price << " Sale amount: " << sale.amount << std::endl;
}
currentTime = orderBook.getNextTime(currentTime);
}
int MerkelMain::getUserOption()
{
int userOption = 0;
std::string line;
std::cout << "Type in 1-6" << std::endl;
std::getline(std::cin, line);
try
{
userOption = std::stoi(line);
}
catch (const std::exception &e)
{
std::cout << "Invalid input!" << std::endl;
}
std::cout << "You chose: " << userOption << std::endl;
return userOption;
}
void MerkelMain::processUserOption(int userOption)
{
if (userOption == 0) // bad input
{
std::cout << "Invalid choice. Choose 1-6" << std::endl;
}
if (userOption == 1)
{
printHelp();
}
if (userOption == 2)
{
printMarketStats();
}
if (userOption == 3)
{
enterAsk();
}
if (userOption == 4)
{
enterBid();
}
if (userOption == 5)
{
printWallet();
}
if (userOption == 6)
{
gotoNextTimeframe();
}
}

View File

@ -0,0 +1,26 @@
#pragma once
#include <vector>
#include "OrderBookEntry.h"
#include "OrderBook.h"
class MerkelMain
{
public:
MerkelMain();
/** Call this to start the sim */
void init();
private:
void loadOrderBook();
void printMenu();
void printHelp();
void printMarketStats();
void enterAsk();
void enterBid();
void printWallet();
void gotoNextTimeframe();
int getUserOption();
void processUserOption(int userOption);
std::string currentTime;
OrderBook orderBook{"test.csv"};
};

View File

@ -0,0 +1,143 @@
#include "OrderBook.h"
#include "CSVReader.h"
#include <map>
#include <algorithm>
/* Construct, reading a csv data file */
OrderBook::OrderBook(std::string filename)
{
orders = CSVReader::readCSV(filename);
}
/* return vector of all known products in the dataset */
std::vector<std::string> OrderBook::getKnownProducts()
{
std::vector<std::string> products;
std::map<std::string, bool> productMap;
for(OrderBookEntry& entry : orders)
{
productMap[entry.product] = true;
}
for(auto const&entry : productMap)
{
products.push_back(entry.first);
}
return products;
}
/* return vector of Orders according to the sent filters */
std::vector<OrderBookEntry> OrderBook::getOrders(OrderBookType type, std::string product, std::string timestamp)
{
std::vector<OrderBookEntry> order_selection;
for(OrderBookEntry& entry : orders)
{
if(entry.orderType == type && entry.product == product && entry.timestamp == timestamp)
{
order_selection.push_back(entry);
}
}
return order_selection;
}
double OrderBook::getHighPrice(std::vector<OrderBookEntry>& orderList)
{
double max = orderList[0].price;
for(OrderBookEntry& entry : orderList)
{
if(entry.price > max)
max = entry.price;
}
return max;
}
double OrderBook::getLowPrice(std::vector<OrderBookEntry>& orderList)
{
double min = orderList[0].price;
for(OrderBookEntry& entry : orderList)
{
if(entry.price < min)
min = entry.price;
}
return min;
}
std::string OrderBook::getEarliestTime()
{
return orders[0].timestamp;
}
std::string OrderBook::getNextTime(std::string timestamp)
{
std::string next_timestamp = "";
for(OrderBookEntry& entry : orders)
{
if(entry.timestamp > timestamp)
{
next_timestamp = entry.timestamp;
break;
}
}
if(next_timestamp == "")
{
next_timestamp = orders[0].timestamp;
}
return next_timestamp;
}
void OrderBook::insertOrder(OrderBookEntry& order)
{
orders.push_back(order);
std::sort(orders.begin(), orders.end(), OrderBookEntry::compareByTimestamp);
}
std::vector<OrderBookEntry> OrderBook::matchAsksToBids(std::string product, std::string timestamp)
{
std::vector<OrderBookEntry> asks = getOrders(OrderBookType::ask, product, timestamp);
std::vector<OrderBookEntry> bids = getOrders(OrderBookType::bid, product, timestamp);
std::vector<OrderBookEntry> sales;
std::sort(asks.begin(), asks.end(), OrderBookEntry::compareByPriceAsc);
std::sort(bids.begin(), bids.end(), OrderBookEntry::compareByPriceDesc);
for(OrderBookEntry& thisAsk : asks)
{
for(OrderBookEntry& thisBid : bids)
{
if(thisBid.price >= thisAsk.price)
{
OrderBookEntry sale{thisAsk.price, 0, timestamp, product, OrderBookType::sale};
if(thisBid.amount == thisAsk.amount)
{
sale.amount = thisAsk.amount;
sales.push_back(sale);
thisBid.amount = 0;
break;
}
else if(thisBid.amount > thisAsk.amount)
{
sale.amount = thisAsk.amount;
sales.push_back(sale);
thisBid.amount = thisBid.amount - thisAsk.amount;
break;
}
else if(thisBid.amount < thisAsk.amount)
{
sale.amount = thisBid.amount;
sales.push_back(sale);
thisAsk.amount = thisAsk.amount - thisBid.amount;
thisBid.amount = 0;
continue;
}
}
}
}
return sales;
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "OrderBookEntry.h"
#include "CSVReader.h"
#include <string>
#include <vector>
class OrderBook
{
public:
/* Construct, reading a csv data file */
OrderBook(std::string filename);
/* return vector of all known products in the dataset */
std::vector<std::string> getKnownProducts();
/* return vector of Orders according to the sent filters */
std::vector<OrderBookEntry> getOrders(OrderBookType type, std::string product, std::string timestamp);
/** returns earliest time in the order book */
std::string getEarliestTime();
/** returns the next time after the sent time in the orderbook
* If no next timestamp is found, wraps to the start */
std::string getNextTime(std::string timestamp);
void insertOrder(OrderBookEntry& order);
std::vector<OrderBookEntry> matchAsksToBids(std::string product, std::string timestamp);
static double getHighPrice(std::vector<OrderBookEntry>& orderList);
static double getLowPrice(std::vector<OrderBookEntry>& orderList);
private:
std::vector<OrderBookEntry> orders;
};

View File

@ -0,0 +1,29 @@
#include "OrderBookEntry.h"
OrderBookEntry::OrderBookEntry( double _price,
double _amount,
std::string _timestamp,
std::string _product,
OrderBookType _orderType)
: price(_price),
amount(_amount),
timestamp(_timestamp),
product(_product),
orderType(_orderType)
{
}
OrderBookType OrderBookEntry::stringToOrderBookType(std::string s)
{
if (s == "ask")
{
return OrderBookType::ask;
}
if (s == "bid")
{
return OrderBookType::bid;
}
return OrderBookType::unknown;
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <string>
enum class OrderBookType{bid, ask, unknown, sale};
class OrderBookEntry
{
public:
OrderBookEntry( double _price,
double _amount,
std::string _timestamp,
std::string _product,
OrderBookType _orderType);
static OrderBookType stringToOrderBookType(std::string s);
static bool compareByTimestamp(OrderBookEntry& entry1, OrderBookEntry& entry2)
{
return entry1.timestamp < entry2.timestamp;
}
static bool compareByPriceAsc (OrderBookEntry& entry1, OrderBookEntry& entry2)
{
return entry1.timestamp < entry2.timestamp;
}
static bool compareByPriceDesc (OrderBookEntry& entry1, OrderBookEntry& entry2)
{
return entry1.timestamp > entry2.timestamp;
}
double price;
double amount;
std::string timestamp;
std::string product;
OrderBookType orderType;
};

Binary file not shown.

View File

@ -0,0 +1,12 @@
#include <iostream>
#include <string>
#include <vector>
#include "OrderBookEntry.h"
#include "MerkelMain.h"
#include "CSVReader.h"
int main()
{
MerkelMain app{};
app.init();
}

View File

@ -0,0 +1,2 @@
2020/03/17 17:01:24.884492,ETH/BTC,bid,13,1.0
2020/03/17 17:01:24.884492,ETH/BTC,ask,13,1.0
1 2020/03/17 17:01:24.884492 ETH/BTC bid 13 1.0
2 2020/03/17 17:01:24.884492 ETH/BTC ask 13 1.0