Update included all implementations for version 0.1

This commit is contained in:
Lev
2021-07-05 21:27:45 -05:00
parent 86fc0d8f78
commit 827b5419b8
9 changed files with 530 additions and 125 deletions

View File

@ -1 +1,5 @@
a.exe a.exe
asks.txt
assets.txt
bids.txt
user-sales.txt

View File

@ -7,6 +7,10 @@
MerkelMain::MerkelMain() MerkelMain::MerkelMain()
{ {
currentTime = orderBook.getEarliestTime(); currentTime = orderBook.getEarliestTime();
wallet.insertCurrency("BTC", 10);
wallet.insertCurrency("ETC", 10);
wallet.insertCurrency("DOGE", 10);
wallet.insertCurrency("USDT", 10);
} }
std::string MerkelMain::getCurrentTime() std::string MerkelMain::getCurrentTime()
@ -86,6 +90,7 @@ void MerkelMain::printMarketStats()
// std::cout << "OrderBook asks: " << asks << " bids:" << bids << std::endl; // std::cout << "OrderBook asks: " << asks << " bids:" << bids << std::endl;
} }
// Enter a new ask
void MerkelMain::enterAsk() void MerkelMain::enterAsk()
{ {
std::cout << "Make an ask - enter the amount: product,price, amount, eg ETH/BTC,200,0.5" << std::endl; std::cout << "Make an ask - enter the amount: product,price, amount, eg ETH/BTC,200,0.5" << std::endl;
@ -125,6 +130,7 @@ void MerkelMain::enterAsk()
} }
} }
// Enter a new bid
void MerkelMain::enterBid() void MerkelMain::enterBid()
{ {
std::cout << "Make an bid - enter the amount: product,price, amount, eg ETH/BTC,200,0.5" << std::endl; std::cout << "Make an bid - enter the amount: product,price, amount, eg ETH/BTC,200,0.5" << std::endl;
@ -165,23 +171,32 @@ void MerkelMain::enterBid()
} }
} }
// Withdraw an order
void MerkelMain::withdrawOrder(OrderBookEntry order)
{
orderBook.removeOrder(order);
}
void MerkelMain::printWallet() void MerkelMain::printWallet()
{ {
std::cout << wallet.toString() << std::endl; std::cout << wallet.toString() << std::endl;
} }
void MerkelMain::gotoNextTimeframe(bool silent) std::vector<OrderBookEntry> MerkelMain::gotoNextTimeframe(bool silent)
{ {
if(!silent) // Sales vector to return
std::vector<OrderBookEntry> sales;
if (!silent)
std::cout << "Going to next time frame. " << std::endl; std::cout << "Going to next time frame. " << std::endl;
// Match ask to bids product by product
for (std::string p : orderBook.getKnownProducts()) for (std::string p : orderBook.getKnownProducts())
{ {
std::cout << "matching " << p << std::endl; std::cout << "Matching.. " << p << std::endl;
std::vector<OrderBookEntry> sales = orderBook.matchAsksToBids(p, currentTime); std::vector<OrderBookEntry> productSales = orderBook.matchAsksToBids(p, currentTime);
std::cout << "Sales: " << sales.size() << std::endl; std::cout << "Number of sales for " << p << ": " << productSales.size() << std::endl;
for (OrderBookEntry &sale : sales) for (OrderBookEntry &sale : sales)
{ {
if(!silent) if (!silent)
std::cout << "Sale price: " << sale.price << " amount " << sale.amount << std::endl; std::cout << "Sale price: " << sale.price << " amount " << sale.amount << std::endl;
if (sale.username == "simuser") if (sale.username == "simuser")
{ {
@ -189,9 +204,34 @@ void MerkelMain::gotoNextTimeframe(bool silent)
wallet.processSale(sale); wallet.processSale(sale);
} }
} }
// Add this product sales to the complete sales list
sales.insert(sales.end(), productSales.begin(), productSales.end());
} }
currentTime = orderBook.getNextTime(currentTime); currentTime = orderBook.getNextTime(currentTime);
return sales;
}
// Enter an ask at the current time
void MerkelMain::enterAsk(double price, double amount, std::string product)
{
OrderBookEntry order = {price, amount, currentTime, product, OrderBookType::ask, "simuser"};
// check if the wallet can afford it
if (wallet.canFulfillOrder(order))
{
orderBook.insertOrder(order);
}
}
// Enter a bid at the current time
void MerkelMain::enterBid(double price, double amount, std::string product)
{
OrderBookEntry order = {price, amount, currentTime, product, OrderBookType::bid, "simuser"};
// check if the wallet can afford it
if (wallet.canFulfillOrder(order))
{
orderBook.insertOrder(order);
}
} }
int MerkelMain::getUserOption() int MerkelMain::getUserOption()
@ -265,3 +305,8 @@ std::vector<OrderBookEntry> MerkelMain::getCurrentBids()
} }
return currentBids; return currentBids;
} }
std::string MerkelMain::returnWallet()
{
return wallet.toString();
}

View File

@ -22,10 +22,21 @@ public:
/** returns a vector of all bids orders for the current time */ /** returns a vector of all bids orders for the current time */
std::vector<OrderBookEntry> getCurrentBids(); std::vector<OrderBookEntry> getCurrentBids();
/** matches bids and asks, proceeds to the next time frame */ /** Matches bids and asks, returns the sales and proceeds to the next time frame */
void gotoNextTimeframe(bool silent); std::vector<OrderBookEntry> gotoNextTimeframe(bool silent);
void enterAsk(OrderBookEntry newAsk);
void enterBid(OrderBookEntry newBid); /** Enter a new ask */
void enterAsk(double price, double amount, std::string product);
/** Enter as new bid */
void enterBid(double price, double amount, std::string product);
/** Withdraw an order */
void withdrawOrder(OrderBookEntry order);
/** Return the wallet information */
std::string returnWallet();
private: private:
void printMenu(); void printMenu();
void printHelp(); void printHelp();
@ -40,8 +51,8 @@ private:
std::string currentTime; std::string currentTime;
OrderBook orderBook{"../../../../111.csv"}; //OrderBook orderBook{"../../../../111.csv"};
//OrderBook orderBook{"20200317.csv"}; OrderBook orderBook{"20200317.csv"};
//OrderBook orderBook{"20200601.csv"}; //OrderBook orderBook{"20200601.csv"};
Wallet wallet; Wallet wallet;
}; };

View File

@ -86,6 +86,11 @@ std::string OrderBook::getNextTime(std::string timestamp)
{ {
next_timestamp = orders[0].timestamp; next_timestamp = orders[0].timestamp;
} }
// break the loop by comparing the argument timestamp with the timestamp found
if (timestamp > next_timestamp)
{
return "END";
}
return next_timestamp; return next_timestamp;
} }
@ -95,6 +100,26 @@ void OrderBook::insertOrder(OrderBookEntry &order)
std::sort(orders.begin(), orders.end(), OrderBookEntry::compareByTimestamp); std::sort(orders.begin(), orders.end(), OrderBookEntry::compareByTimestamp);
} }
// Remove order from the order book
void OrderBook::removeOrder(OrderBookEntry &order)
{
for(int i=0; i<orders.size(); ++i)
{
if (orders[i].username == order.username &&
orders[i].timestamp == order.timestamp &&
orders[i].orderType == order.orderType &&
orders[i].product == order.product &&
orders[i].price == order.price &&
orders[i].amount == order.amount
)
{
orders.erase(orders.begin() + i);
--i;
}
}
return;
}
std::vector<OrderBookEntry> OrderBook::matchAsksToBids(std::string product, std::string timestamp) std::vector<OrderBookEntry> OrderBook::matchAsksToBids(std::string product, std::string timestamp)
{ {
// asks = orderbook.asks // asks = orderbook.asks
@ -201,4 +226,4 @@ std::vector<OrderBookEntry> OrderBook::matchAsksToBids(std::string product, std:
} }
} }
return sales; return sales;
} }

View File

@ -22,7 +22,10 @@ public:
* */ * */
std::string getNextTime(std::string timestamp); std::string getNextTime(std::string timestamp);
void insertOrder(OrderBookEntry &order); void insertOrder(OrderBookEntry& order);
// Remove order from the order book
void removeOrder(OrderBookEntry& order);
std::vector<OrderBookEntry> matchAsksToBids(std::string product, std::string timestamp); std::vector<OrderBookEntry> matchAsksToBids(std::string product, std::string timestamp);

View File

@ -3,6 +3,11 @@
TradingBot::TradingBot(MerkelMain *merkel) TradingBot::TradingBot(MerkelMain *merkel)
{ {
this->merkel = merkel; this->merkel = merkel;
products = merkel->getKnownProducts();
// We create the log files
logAssets(merkel->returnWallet(), merkel->getCurrentTime(), "start");
logBidsAsks(OrderBookEntry{1.0, 1.0, "", "", OrderBookType::ask, "simuser"}, "start");
logUserSales(lastSales, "start");
} }
void TradingBot::startBot() void TradingBot::startBot()
@ -26,21 +31,15 @@ void TradingBot::printMenu()
// 1 print help // 1 print help
std::cout << "1: Retrieve current orders" << std::endl; std::cout << "1: Retrieve current orders" << std::endl;
std::cout << "2: Predict ask and bid rates" << std::endl; std::cout << "2: Predict ask and bid rates" << std::endl;
std::cout << "3: Print predictions" << std::endl;; std::cout << "3: Print predictions" << std::endl;
std::cout << "4: Make automatic bids and asks for the current time" << std::endl;
std::cout << "5: Process bids and asks and go to next time slot" << std::endl;
std::cout << "6: Fully automate this time slot" << std::endl;
std::cout << "7: Fully automate all remaining time slots" << std::endl;
std::cout << "8: Exit bot" << std::endl; std::cout << "8: Exit bot" << std::endl;
std::cout << spacer << std::endl; std::cout << spacer << std::endl;
std::cout << "Enter an option: "; std::cout << "Enter an option: ";
return; return;
// 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;
} }
int TradingBot::getUserOption() int TradingBot::getUserOption()
@ -63,12 +62,14 @@ void TradingBot::processUserOption(int userOption)
{ {
if (userOption == 0) if (userOption == 0)
return; return;
// Retrieve bids and asks for current time slot
if (userOption == 1) if (userOption == 1)
{ {
retrieveOrders(); retrieveOrders();
if (bookAsks.size() > 0 && bookBids.size() > 0) if (bookAsks.size() > 0 && bookBids.size() > 0)
std::cout << "Bids and Asks loaded successfully for the current time." << std::endl; std::cout << "Bids and Asks loaded successfully for the current time." << std::endl;
} }
// User linear regression to predict future rates
if (userOption == 2) if (userOption == 2)
{ {
predictRates(); predictRates();
@ -77,25 +78,77 @@ void TradingBot::processUserOption(int userOption)
std::cout << "New predicitons have been created" << std::endl; std::cout << "New predicitons have been created" << std::endl;
} }
} }
// Create new bids or asks if they are predicted to make a profit
if (userOption == 3) if (userOption == 3)
{ {
if(predictedAsks.size() == 0 || predictedBids.size() == 0)
{
std::cout << "No predictions to print" << std::endl;
return;
}
printPredictions(); printPredictions();
} }
// Based on predicted rates, make new bids or asks
if (userOption == 4)
{
makeAutoBids();
makeAutoAsks();
}
// Have Merkel process bids, asks and go to the new time slot
if (userOption == 5)
{
processBidsAsks();
}
// Automate by pulling orders, predicting rates, making new asks/bids, withdrawing bids/asks
if (userOption == 6)
{
retrieveOrders();
predictRates();
makeAutoBids();
makeAutoAsks();
processBidsAsks();
}
// Automate all remaining time slots
if (userOption == 7) if (userOption == 7)
{ {
testFunc(); do
{
retrieveOrders();
predictRates();
makeAutoBids();
makeAutoAsks();
processBidsAsks();
}
while (merkel->getCurrentTime() != "END");
std::cout << "Finished all time slots and made " << salesHistory.size() << " sales" << std::endl;
} }
} }
// R1A
// Retrieve orders for the current time slot
void TradingBot::retrieveOrders() void TradingBot::retrieveOrders()
{ {
bookAsks.clear(); bookAsks.clear();
bookAsks = merkel->getCurrentAsks(); bookAsks = merkel->getCurrentAsks();
bookBids.clear(); bookBids.clear();
bookBids = merkel->getCurrentBids(); bookBids = merkel->getCurrentBids();
// We'll go through all products and get the mean
// Get the mean ask and bid price and store in history
std::map<std::string, double> askMap;
std::map<std::string, double> bidMap;
for (const std::string &product : products)
{
askMap[product] = getMean(bookAsks, product);
bidMap[product] = getMean(bookBids, product);
}
askHistory.push_back(askMap);
bidHistory.push_back(bidMap);
return;
} }
// R1B
// Predict the next rates for all products // Predict the next rates for all products
// Also calculates the mean ask and bid prices per product and saves them to history
void TradingBot::predictRates() void TradingBot::predictRates()
{ {
if (bookAsks.size() == 0 || bookBids.size() == 0) if (bookAsks.size() == 0 || bookBids.size() == 0)
@ -104,41 +157,249 @@ void TradingBot::predictRates()
return; return;
} }
// We'll go through all products and get the mean
std::vector<std::string> products = merkel->getKnownProducts();
// Get all asks and store the mean
std::map<std::string, double> askMap;
for (const std::string &product : products)
{
askMap[product] = getMean(bookAsks, product);
std::cout << askMap[product] << std::endl;
}
askHistory.push_back(askMap);
// Get all bids and store the mean
std::map<std::string, double> bidMap;
for (const std::string &product : products)
{
bidMap[product] = getMean(bookBids, product);
}
bidHistory.push_back(bidMap);
// If the history vectors only have 1 element, then we're at the first time slot // If the history vectors only have 1 element, then we're at the first time slot
// Our prediction will be half way between the mean ask and bid // We can only predict a future price thorugh regression when there are at least 2 entries in the history vectors
if (bidHistory.size() == 1) if (bidHistory.size() >= 2 && askHistory.size() >= 2)
{ {
for (std::string &product : products) for (const std::string &product : products)
{ {
predictedAsks[product] = (bidHistory[0][product] + askHistory[0][product]) / 2; // We want to find an equation of type Y = a + bX where
predictedBids[product] = predictedAsks[product]; // Y is the predicted value
// X is the point in time index
// We need to calculate a and b
// The regression needs to be calculated every time slot because it may change due to the new data
// ASKS //
std::vector<double> askRegression = regressionFromHistory(askHistory, product);
double &askIntercept = askRegression[0];
double &askSlope = askRegression[1];
// We calculate the current askRegression value (1-indexed)
// The formula is Y = Y-intercept + Slope * X or regressionValue = askntercept + askSlope * timeIndex
currentAsks[product] = askIntercept + askSlope * bidHistory.size();
predictedAsks[product] = askIntercept + askSlope * (bidHistory.size() + 1);
// BIDS //
std::vector<double> bidRegression = regressionFromHistory(bidHistory, product);
double &bidIntercept = bidRegression[0];
double &bidSlope = bidRegression[1];
// We calculate the current bidRegression value (1-indexed)
// The formula is Y = Y-intercept + Slope * X or regressionValue = bidIntercept + bidSlope * timeIndex
currentBids[product] = bidIntercept + bidSlope * bidHistory.size();
predictedBids[product] = bidIntercept + bidSlope * (bidHistory.size() + 1);
} }
} }
return;
}
//std::map<std::string, std::vector<double>> provMap; // R2A
// R2B
// R2D
// Make bids automatically
void TradingBot::makeAutoBids()
{
// The bid history has one or no entries, auto bids are skipped
if (bidHistory.size() < 2)
return;
//askHistory.push_back(getMean(bookAsks)); // We use the regression values to determine if we should make bids for the different products
//bidHistory.push_back(getMean(bookBids)); for (std::string &product : products)
{
// We'll make a bid (buy) the product if the predicted price is higher than the current mean stored in bidHistory
if (bidHistory.back()[product] < predictedBids[product])
{
// The price we'll offer to buy will be half way between the current and predicted regression values
double price = (currentBids[product] + predictedBids[product]) / 2.0;
// To determine how much to offer to buy, we'll use the last saved list of sales to get an idea of the traded volume
double amount = 0.0;
if (lastSales.size() > 0)
{
for(int i=0; i<lastSales.size(); ++i)
{
if(lastSales[i].product == product)
amount += lastSales[i].amount;
}
}
// We will trade up to 20 percent of the last traded volume
amount = amount * 0.20;
// If amount still 0, we use the current orders' volume
if(amount == 0.0)
{
for (const OrderBookEntry &bid : bookBids)
{
if (bid.product == product)
amount += bid.amount;
}
amount = amount * 0.20;
}
// R2D
// Check our bids and withdraw them if the price is higher than our calculated price
for (const OrderBookEntry &bid : bookBids)
{
if(bid.username == "simuser" && bid.product == product && bid.price > price)
{
merkel->withdrawOrder(bid);
}
}
// We now make a bid
// R2B
merkel->enterBid(price, amount, product);
// We log the bid
// R4B
logBidsAsks(OrderBookEntry{price, amount, merkel->getCurrentTime(), product, OrderBookType::bid, "simuser"}, "append");
}
}
}
// R3A
// R3B
// R3D
// Make asks automatically
void TradingBot::makeAutoAsks()
{
// The ask history has one or no entries, auto asks are skipped
if (askHistory.size() < 2)
return;
// We use the regression values to determine if we should make asks for the different products
for (std::string &product : products)
{
// We'll make an ask (sell) the product if the predicted price is lower than the current mean stored in askHistory
if (askHistory.back()[product] > predictedAsks[product])
{
// The price we'll offer to sell will be half way between the current and predicted regression values
double price = (currentAsks[product] + predictedAsks[product]) / 2.0;
// To determine how much to offer to sell, we'll use the last saved list of sales to get an idea of the traded volume
double amount = 0.0;
if (lastSales.size() > 0)
{
for(int i=0; i<lastSales.size(); ++i)
{
if(lastSales[i].product == product)
amount += lastSales[i].amount;
}
}
// We will trade up to 20 percent of the last traded volume
amount = amount * 0.20;
// If amount still 0, we use the current orders' volume
if(amount == 0.0)
{
for (const OrderBookEntry &ask : bookAsks)
{
if (ask.product == product)
amount += ask.amount;
}
amount = amount * 0.20;
}
// R3D
// Check our asks and withdraw them if the price is higher than our calculated price
for (const OrderBookEntry &ask : bookAsks)
{
if(ask.username == "simuser" && ask.product == product && ask.price < price)
{
merkel->withdrawOrder(ask);
}
}
// We now make an ask
// R3B
merkel->enterAsk(price, amount, product);
// We log the ask
// R4B
logBidsAsks(OrderBookEntry{price, amount, merkel->getCurrentTime(), product, OrderBookType::ask, "simuser"}, "append");
}
}
}
// R2C & R3C
// Ask Merkel to process all bids and asks for the current time slot
void TradingBot::processBidsAsks()
{
lastSales.clear();
// R2C & R3C
lastSales = merkel->gotoNextTimeframe(true);
salesHistory.insert(salesHistory.end(), lastSales.begin(), lastSales.end());
logAssets(merkel->returnWallet(), merkel->getCurrentTime(), "append");
logUserSales(lastSales, "append");
return;
}
// Calculate and Return the Y intercept and slope from a vector of map objects
std::vector<double> TradingBot::regressionFromHistory(std::vector<std::map<std::string, double>> history, std::string product)
{
// Check if enough data points are present
if (history.size() < 2)
return std::vector<double>{0.0, 0.0};
// number of history entries
int hisSize = history.size();
// Build a vector of history prices for this product
std::vector<double> priceHistory;
for (const std::map<std::string, double> &historyEntry : history)
{
priceHistory.push_back(historyEntry.at(product));
}
// Find the mean of the independent variables
// 1-indexed sum
double sumX = (hisSize * (hisSize + 1)) / 2;
double meanX = sumX / ((double)hisSize);
// Find the mean of the dependent variables
double sumY = 0.0;
double meanY = 0.0;
for (const double &price : priceHistory)
{
sumY += price;
}
meanY = sumY / ((double)hisSize);
// We calculate the distances to the mean lines
// X distances
std::vector<double> distanceX;
for (int i = 1; i <= hisSize; ++i)
{
distanceX.push_back(((double)i) - meanX);
}
// Y distances
std::vector<double> distanceY;
for (const double &price : priceHistory)
{
distanceY.push_back(price - meanY);
}
// We square X distances
std::vector<double> distanceSquareX;
for (int i = 0; i < distanceX.size(); ++i)
{
distanceSquareX.push_back(distanceX[i] * distanceX[i]);
}
// We find the product of the distances
std::vector<double> distanceProducts;
for (int i = 0; i < distanceX.size(); ++i)
{
distanceProducts.push_back(distanceX[i] * distanceY[i]);
}
// We add up the X distance squares
double squareSum = 0.0;
for (const double &square : distanceSquareX)
{
squareSum += square;
}
// We add up the distance products
double productSum = 0.0;
for (const double &distanceP : distanceProducts)
{
productSum += distanceP;
}
// We calculate the slope of the regression line
double slope = productSum / squareSum;
// We calculate interception with the Y axis
// We know the regression line will go through the (meanX, meanY) point
// We have: meanY = yIntercept + slope * meanX
// So we solve for Y
double yIntercept = meanY - slope * meanX;
return std::vector<double>{yIntercept, slope};
} }
// return the mean price from the vector // return the mean price from the vector
@ -154,7 +415,8 @@ double TradingBot::getMean(std::vector<OrderBookEntry> orders, std::string produ
++count; ++count;
} }
} }
if (count == 0) return 0.0; if (count == 0)
return 0.0;
return sum / count; return sum / count;
} }
@ -179,73 +441,116 @@ void TradingBot::printPredictions()
} }
} }
void TradingBot::testFunc() // R4A
// Print assets from wallet
void TradingBot::logAssets(std::string Wallet, std::string timestamp, std::string mode)
{ {
std::cout << "Asks" << std::endl; std::fstream assetStream;
for (int i = 0; i < bookAsks.size(); ++i) if(mode == "start")
{ assetStream.open("assets.txt", std::ios::out);
std::cout << "Entry: " << bookAsks[i].timestamp << " - " else
<< bookAsks[i].product << " - " assetStream.open("assets.txt", std::ios_base::app);
<< OrderBookEntry::OrderBookTypeToString(bookAsks[i].orderType) << " - "
<< std::fixed << bookAsks[i].price << " - " // Check the file was created properly
<< std::fixed << bookAsks[i].amount << " - " if(!assetStream)
<< bookAsks[i].username << std::endl;
}
std::cout << "Bids" << std::endl;
for (int i = 0; i < bookBids.size(); ++i)
{
std::cout << "Entry: " << bookBids[i].timestamp << " - "
<< bookBids[i].product << " - "
<< OrderBookEntry::OrderBookTypeToString(bookBids[i].orderType) << " - "
<< std::fixed << bookBids[i].price << " - "
<< std::fixed << bookBids[i].amount << " - "
<< bookBids[i].username << std::endl;
}
return;
std::cout << "Asks" << std::endl;
for (auto const &ask : predictedAsks)
{
std::cout << ask.first << " - " << ask.second << std::endl;
}
std::cout << "Bids" << std::endl;
for (auto const &bid : predictedBids)
{
std::cout << bid.first << " - " << bid.second << std::endl;
}
//std::cout << "Ask: " << askHistory[0] << std::endl;
return;
std::vector<OrderBookEntry> currentAsks = merkel->getCurrentAsks();
std::cout.precision(8);
for (int i = 0; i < currentAsks.size(); ++i)
{
//std::cout << merkel->getCurrentTime() << std::endl;
if (currentAsks[i].product == "DOGE/BTC")
{ {
//std::cout.precision(14); // We couldn't open/create the file
std::cout << "Entry: " << currentAsks[i].timestamp << " - " return;
<< currentAsks[i].product << " - " }
<< OrderBookEntry::OrderBookTypeToString(currentAsks[i].orderType) << " - " else
<< std::fixed << currentAsks[i].price << " - " {
<< std::fixed << currentAsks[i].amount << " - " assetStream << "Time: " << timestamp << std::endl;
<< currentAsks[i].username << std::endl; assetStream << Wallet << std::endl;
assetStream.close();
}
}
// R4B
// Print bids and offers that have been created
void TradingBot::logBidsAsks(OrderBookEntry order, std::string mode)
{
std::fstream askStream;
std::fstream bidStream;
if(mode == "start")
{
// create the files overwriting anything there
askStream.open("asks.txt", std::ios::out);
bidStream.open("bids.txt", std::ios::out);
askStream.close();
bidStream.close();
return;
}
else if(order.orderType == OrderBookType::ask)
{
askStream.open("asks.txt", std::ios_base::app);
// Check the file was created properly
if(!askStream)
{
// We couldn't open/create the file
return;
}
else
{
askStream << order.timestamp << ","
<< order.product << ","
<< OrderBookEntry::OrderBookTypeToString(order.orderType) << ","
<< order.price << ","
<< order.amount << std::endl;
askStream.close();
} }
} }
else if(order.orderType == OrderBookType::bid)
return;
std::vector<std::string> prods = merkel->getKnownProducts();
for (int i = 0; i < prods.size(); ++i)
{ {
std::cout << prods[i] << std::endl; bidStream.open("bids.txt", std::ios_base::app);
// Check the file was created properly
if(!bidStream)
{
// We couldn't open/create the file
return;
}
else
{
bidStream << order.timestamp << ","
<< order.product << ","
<< OrderBookEntry::OrderBookTypeToString(order.orderType) << ","
<< order.price << ","
<< order.amount << std::endl;
bidStream.close();
}
} }
return; }
std::string test1 = OrderBookEntry::OrderBookTypeToString(OrderBookType::bid); // R4C
std::cout << test1 << std::endl; // Print successful asks and bids
return; void TradingBot::logUserSales(std::vector<OrderBookEntry> sales, std::string mode)
{
std::fstream saleStream;
if(mode == "start")
saleStream.open("user-sales.txt", std::ios::out);
else
saleStream.open("user-sales.txt", std::ios_base::app);
// Check the file was created properly
if(!saleStream)
{
// We couldn't open/create the file
return;
}
else
{
// We loop though the sales vector and check the type username
for(const OrderBookEntry &sale : sales)
{
// this means the sale was created from a user ask or sale.
if(sale.username == "simuser")
{
saleStream << sale.timestamp << ","
<< sale.product << ","
<< OrderBookEntry::OrderBookTypeToString(sale.orderType) << ","
<< sale.price << ","
<< sale.amount << std::endl;
}
}
saleStream.close();
}
} }

View File

@ -6,6 +6,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <fstream>
class TradingBot class TradingBot
{ {
@ -13,7 +14,6 @@ public:
TradingBot(MerkelMain *merkel); TradingBot(MerkelMain *merkel);
/** start the Trading Bot interface */ /** start the Trading Bot interface */
void startBot(); void startBot();
void testFunc();
private: private:
// ===== Functions ===== // ===== Functions =====
@ -22,17 +22,29 @@ private:
int getUserOption(); int getUserOption();
void processUserOption(int userOption); void processUserOption(int userOption);
void printPredictions(); void printPredictions();
// Exchange functions // ==== Exchange functions ====
void retrieveOrders(); // Retrieves current orders from Merkel and stores them in bookBids and BookAsks void retrieveOrders();
void predictRates(); void predictRates();
// Helper functions void makeAutoBids();
void makeAutoAsks();
void processBidsAsks();
// ==== Helper functions ====
static std::vector<double> regressionFromHistory(std::vector<std::map<std::string, double>> history, std::string product);
static double getMean(std::vector<OrderBookEntry> orders, std::string product); static double getMean(std::vector<OrderBookEntry> orders, std::string product);
static void logAssets(std::string wallet, std::string timestamp, std::string mode);
static void logBidsAsks(OrderBookEntry order, std::string mode);
static void logUserSales(std::vector<OrderBookEntry> sales, std::string mode);
// ===== Variables ===== // ===== Variables =====
MerkelMain *merkel; MerkelMain *merkel;
std::vector<std::string> products;
std::vector<OrderBookEntry> bookBids; std::vector<OrderBookEntry> bookBids;
std::vector<OrderBookEntry> bookAsks; std::vector<OrderBookEntry> bookAsks;
std::vector<OrderBookEntry> lastSales;
std::vector<std::map<std::string, double>> bidHistory; std::vector<std::map<std::string, double>> bidHistory;
std::vector<std::map<std::string, double>> askHistory; std::vector<std::map<std::string, double>> askHistory;
std::vector<OrderBookEntry> salesHistory;
std::map<std::string, double> predictedBids; std::map<std::string, double> predictedBids;
std::map<std::string, double> predictedAsks; std::map<std::string, double> predictedAsks;
std::map<std::string, double> currentBids;
std::map<std::string, double> currentAsks;
}; };

View File

@ -78,7 +78,7 @@ bool Wallet::canFulfillOrder(OrderBookEntry order)
{ {
double amount = order.amount; double amount = order.amount;
std::string currency = currs[0]; std::string currency = currs[0];
std::cout << "Wallet::canFulfillOrder " << currency << " : " << amount << std::endl; //std::cout << "Wallet::canFulfillOrder " << currency << " : " << amount << std::endl;
return containsCurrency(currency, amount); return containsCurrency(currency, amount);
} }
@ -87,7 +87,7 @@ bool Wallet::canFulfillOrder(OrderBookEntry order)
{ {
double amount = order.amount * order.price; double amount = order.amount * order.price;
std::string currency = currs[1]; std::string currency = currs[1];
std::cout << "Wallet::canFulfillOrder " << currency << " : " << amount << std::endl; //std::cout << "Wallet::canFulfillOrder " << currency << " : " << amount << std::endl;
return containsCurrency(currency, amount); return containsCurrency(currency, amount);
} }

View File

@ -7,5 +7,5 @@ int main()
{ {
MerkelMain app{}; MerkelMain app{};
TradingBot bot{&app}; TradingBot bot{&app};
app.init(); bot.startBot();
} }