Add implemented new OrderBook statistical functions
This commit is contained in:
3544
CM2005 Object Oriented Programming/Topic 4/4.3.3/20200317.csv
Normal file
3544
CM2005 Object Oriented Programming/Topic 4/4.3.3/20200317.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,85 @@
|
||||
#include "CSVReader.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
CSVReader::CSVReader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::vector<OrderBookEntry> CSVReader::readCSV(std::string csvFilename)
|
||||
{
|
||||
std::vector<OrderBookEntry> entries;
|
||||
unsigned int errors = 0;
|
||||
std::ifstream csvFile{csvFilename};
|
||||
std::string line;
|
||||
std::cout << "Loading data..." << std::endl;
|
||||
if (csvFile.is_open())
|
||||
{
|
||||
while(std::getline(csvFile, line))
|
||||
{
|
||||
try
|
||||
{
|
||||
OrderBookEntry obe = stringsToOBE(tokenise(line, ','));
|
||||
entries.push_back(obe);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
++errors;
|
||||
}
|
||||
}// end of while
|
||||
std::cout << "Success! " << entries.size() << " entries found." << std::endl;
|
||||
if(errors > 0)
|
||||
std::cout << errors << " errors found." << 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)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
OrderBookEntry obe{price,
|
||||
amount,
|
||||
tokens[0],
|
||||
tokens[1],
|
||||
OrderBookEntry::stringToOrderBookType(tokens[2])};
|
||||
|
||||
return obe;
|
||||
}
|
||||
|
||||
18
CM2005 Object Oriented Programming/Topic 4/4.3.3/CSVReader.h
Normal file
18
CM2005 Object Oriented Programming/Topic 4/4.3.3/CSVReader.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "OrderBookEntry.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class CSVReader
|
||||
{
|
||||
public:
|
||||
CSVReader();
|
||||
|
||||
static std::vector<OrderBookEntry> readCSV(std::string csvFile);
|
||||
|
||||
private:
|
||||
static std::vector<std::string> tokenise(std::string csvLine, char separator);
|
||||
static OrderBookEntry stringsToOBE(std::vector<std::string> strings);
|
||||
|
||||
};
|
||||
175
CM2005 Object Oriented Programming/Topic 4/4.3.3/MerkelMain.cpp
Normal file
175
CM2005 Object Oriented Programming/Topic 4/4.3.3/MerkelMain.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
#include "MerkelMain.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "OrderBookEntry.h"
|
||||
#include "CSVReader.h"
|
||||
#include <iomanip>
|
||||
|
||||
MerkelMain::MerkelMain()
|
||||
{
|
||||
std::cout << "================================================================================" << std::endl;
|
||||
}
|
||||
|
||||
void MerkelMain::init()
|
||||
{
|
||||
//if(orderBook.orders.size() == 0)
|
||||
if(! orderBook.getBookSize() > 0)
|
||||
{
|
||||
std::cout << "No entries found! Exiting program :(" << std::endl;
|
||||
return;
|
||||
}
|
||||
int input;
|
||||
currentTime = orderBook.getEarliestTime();
|
||||
while(true)
|
||||
{
|
||||
printMenu();
|
||||
input = getUserOption();
|
||||
processUserOption(input);
|
||||
}
|
||||
}
|
||||
|
||||
void MerkelMain::printMenu()
|
||||
{
|
||||
std::cout << "MENU" << std::endl;
|
||||
// 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 offer " << 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: " << 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 setw(int w)
|
||||
// {
|
||||
// std::cout.width(w);
|
||||
// return;
|
||||
// }
|
||||
|
||||
void MerkelMain::printMarketStats()
|
||||
{
|
||||
/*
|
||||
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;
|
||||
}
|
||||
*/
|
||||
std::string separator = "====================================================================================================";
|
||||
std::cout << separator << std::endl;
|
||||
std::cout << "Current Time: " << currentTime << std::endl;
|
||||
std::cout << separator << std::endl;
|
||||
//std::cout << "PRODUCT LAST CHANGE% CHANGE HIGH LOW MEAN " << std::endl;
|
||||
std::cout << std::left
|
||||
<< std::setw(12) << "PRODUCT" << std::right
|
||||
<< std::setw(12) << "LAST"
|
||||
<< std::setw(12) << "CHANGE%"
|
||||
<< std::setw(12) << "CHANGE"
|
||||
<< std::setw(12) << "HIGH"
|
||||
<< std::setw(12) << "LOW"
|
||||
<< std::setw(12) << "AVERAGE"
|
||||
<< std::setw(12) << "SPREAD" << std::endl;
|
||||
std::cout << "----------------------------------------------------------------------------------------------------" << std::endl;
|
||||
for(std::string const p : orderBook.getKnownProducts())
|
||||
{
|
||||
//std::cout.precision(5);
|
||||
|
||||
std::vector<OrderBookEntry> askEntries = orderBook.getOrders(OrderBookType::ask, p, currentTime);
|
||||
std::vector<OrderBookEntry> bidEntries = orderBook.getOrders(OrderBookType::bid, p, currentTime);
|
||||
|
||||
//std::cout << p << fluff << std::cout.width(4) << orderBook.getHighPrice(askEntries) << std::endl;
|
||||
std::cout.left;
|
||||
std::streamsize pres = std::cout.precision();
|
||||
std::cout << std::left << std::setw(12) << p
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getLastPrice(askEntries)
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getChangePercent(askEntries)
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getChangeNumber(askEntries)
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getHighPrice(askEntries)
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getLowPrice(askEntries)
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getAverage(askEntries)
|
||||
<< std::right << std::fixed << std::setw(12) << orderBook.getSpread(bidEntries, askEntries)
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << separator << std::endl;
|
||||
}
|
||||
|
||||
void MerkelMain::enterOffer()
|
||||
{
|
||||
std::cout << "Mark and offer - enter the amount " << std::endl;
|
||||
}
|
||||
|
||||
void MerkelMain::enterBid()
|
||||
{
|
||||
std::cout << "Make a bid - enter the amount" << 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;
|
||||
currentTime = orderBook.getNextTime(currentTime);
|
||||
}
|
||||
|
||||
int MerkelMain::getUserOption()
|
||||
{
|
||||
int userOption;
|
||||
|
||||
std::cout << "To select, type in 1-6:" << std::endl;
|
||||
std::cin >> userOption;
|
||||
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)
|
||||
{
|
||||
enterOffer();
|
||||
}
|
||||
if (userOption == 4)
|
||||
{
|
||||
enterBid();
|
||||
}
|
||||
if (userOption == 5)
|
||||
{
|
||||
printWallet();
|
||||
}
|
||||
if (userOption == 6)
|
||||
{
|
||||
gotoNextTimeframe();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 enterOffer();
|
||||
void enterBid();
|
||||
void printWallet();
|
||||
void gotoNextTimeframe();
|
||||
int getUserOption();
|
||||
void processUserOption(int userOption);
|
||||
std::string currentTime;
|
||||
OrderBook orderBook{"20200317.csv"};
|
||||
};
|
||||
156
CM2005 Object Oriented Programming/Topic 4/4.3.3/OrderBook.cpp
Normal file
156
CM2005 Object Oriented Programming/Topic 4/4.3.3/OrderBook.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#include "OrderBook.h"
|
||||
#include "CSVReader.h"
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
unsigned int OrderBook::getBookSize()
|
||||
{
|
||||
return orders.size();
|
||||
}
|
||||
|
||||
/* 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 prev_timestamp = "";
|
||||
for(OrderBookEntry& entry : orders)
|
||||
{
|
||||
if(entry.timestamp > timestamp)
|
||||
{
|
||||
prev_timestamp = entry.timestamp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(prev_timestamp == "")
|
||||
{
|
||||
prev_timestamp = orders[0].timestamp;
|
||||
}
|
||||
return prev_timestamp;
|
||||
}
|
||||
|
||||
double OrderBook::getLastPrice(std::vector<OrderBookEntry>& orderList)
|
||||
{
|
||||
//std::cout << std::endl << std::to_string(orderList[orderList.size()-1].price) << std::endl;
|
||||
return orderList[orderList.size()-1].price;
|
||||
}
|
||||
|
||||
double OrderBook::getAverage(std::vector<OrderBookEntry>& orderList)
|
||||
{
|
||||
double sum{};
|
||||
for (const OrderBookEntry& entry : orderList)
|
||||
{
|
||||
sum += entry.price;
|
||||
}
|
||||
return sum/orderList.size();
|
||||
}
|
||||
|
||||
double OrderBook::getSpread(std::vector<OrderBookEntry>& bids, std::vector<OrderBookEntry>& asks)
|
||||
{
|
||||
return getAverage(bids) - getAverage(asks);
|
||||
}
|
||||
double OrderBook::getChangePercent(std::vector<OrderBookEntry>& orderList)
|
||||
{
|
||||
std::string prevTime = getPrevTime(orderList[0].timestamp);
|
||||
if(orderList[0].timestamp == prevTime)
|
||||
return 0.0;
|
||||
std::vector<OrderBookEntry> lastList = getOrders(orderList[0].orderType, orderList[0].product, prevTime);
|
||||
double lastAverage = getAverage(lastList);
|
||||
double thisAverage = getAverage(orderList);
|
||||
return ((lastAverage - thisAverage) / lastAverage) * 100;
|
||||
}
|
||||
|
||||
double OrderBook::getChangeNumber(std::vector<OrderBookEntry>& orderList)
|
||||
{
|
||||
std::string prevTime = getPrevTime(orderList[0].timestamp);
|
||||
if(orderList[0].timestamp == prevTime)
|
||||
return 0.0;
|
||||
std::vector<OrderBookEntry> lastList = getOrders(orderList[0].orderType, orderList[0].product, prevTime);
|
||||
double lastAverage = getAverage(lastList);
|
||||
double thisAverage = getAverage(orderList);
|
||||
return lastAverage - thisAverage;
|
||||
}
|
||||
|
||||
std::string OrderBook::getPrevTime(std::string timestamp)
|
||||
{
|
||||
std::string prev_timestamp = "";
|
||||
for(OrderBookEntry& entry : orders)
|
||||
{
|
||||
if(entry.timestamp == timestamp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev_timestamp = entry.timestamp;
|
||||
}
|
||||
if(prev_timestamp == "")
|
||||
{
|
||||
prev_timestamp = orders[0].timestamp;
|
||||
}
|
||||
return prev_timestamp;
|
||||
}
|
||||
43
CM2005 Object Oriented Programming/Topic 4/4.3.3/OrderBook.h
Normal file
43
CM2005 Object Oriented Programming/Topic 4/4.3.3/OrderBook.h
Normal file
@ -0,0 +1,43 @@
|
||||
#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);
|
||||
std::string getPrevTime(std::string timestamp);
|
||||
unsigned int getBookSize();
|
||||
static double getHighPrice(std::vector<OrderBookEntry>& orderList);
|
||||
static double getLowPrice(std::vector<OrderBookEntry>& orderList);
|
||||
|
||||
static double getLastPrice(std::vector<OrderBookEntry>& orderList);
|
||||
static double getAverage(std::vector<OrderBookEntry>& orderList);
|
||||
static double getSpread(std::vector<OrderBookEntry>& bids, std::vector<OrderBookEntry>& asks);
|
||||
double getChangePercent(std::vector<OrderBookEntry>& orderList);
|
||||
double getChangeNumber(std::vector<OrderBookEntry>& orderList);
|
||||
private:
|
||||
std::vector<OrderBookEntry> orders;
|
||||
};
|
||||
|
||||
/*
|
||||
About the Spread
|
||||
https://www.forex.com/en/markets/forex/
|
||||
https://www.ig.com/en/trading-strategies/what-is-the-spread-in-forex-and-how-do-you-calculate-it-201126
|
||||
|
||||
Percentage variance
|
||||
https://www.tradingview.com/markets/currencies/rates-major/
|
||||
*/
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
enum class OrderBookType{bid, ask, unknown};
|
||||
|
||||
class OrderBookEntry
|
||||
{
|
||||
public:
|
||||
|
||||
OrderBookEntry( double _price,
|
||||
double _amount,
|
||||
std::string _timestamp,
|
||||
std::string _product,
|
||||
OrderBookType _orderType);
|
||||
|
||||
static OrderBookType stringToOrderBookType(std::string s);
|
||||
|
||||
double price;
|
||||
double amount;
|
||||
std::string timestamp;
|
||||
std::string product;
|
||||
OrderBookType orderType;
|
||||
};
|
||||
|
||||
BIN
CM2005 Object Oriented Programming/Topic 4/4.3.3/a.exe
Normal file
BIN
CM2005 Object Oriented Programming/Topic 4/4.3.3/a.exe
Normal file
Binary file not shown.
13
CM2005 Object Oriented Programming/Topic 4/4.3.3/main.cpp
Normal file
13
CM2005 Object Oriented Programming/Topic 4/4.3.3/main.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "OrderBookEntry.h"
|
||||
#include "MerkelMain.h"
|
||||
#include "CSVReader.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
MerkelMain app{};
|
||||
app.init();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user