From 57a91b6f728e0c2f4325690a5c8d58a3ef5332bf Mon Sep 17 00:00:00 2001 From: clarkohw Date: Fri, 16 Apr 2021 01:22:35 -0400 Subject: zero gains are recorded as 0% --- src/main/java/edu/brown/cs/student/term/Main.java | 6 +- .../brown/cs/student/term/ProfitCalculation.java | 393 --------------------- .../brown/cs/student/term/hub/SuspicionRanker.java | 13 +- .../cs/student/term/profit/ProfitCalculation.java | 393 +++++++++++++++++++++ 4 files changed, 403 insertions(+), 402 deletions(-) delete mode 100644 src/main/java/edu/brown/cs/student/term/ProfitCalculation.java create mode 100644 src/main/java/edu/brown/cs/student/term/profit/ProfitCalculation.java (limited to 'src/main/java') diff --git a/src/main/java/edu/brown/cs/student/term/Main.java b/src/main/java/edu/brown/cs/student/term/Main.java index 5ca40e8..3b0a258 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -2,8 +2,7 @@ package edu.brown.cs.student.term; import com.google.common.collect.ImmutableMap; import edu.brown.cs.student.term.hub.Holder; -import edu.brown.cs.student.term.hub.HubSearch; -import edu.brown.cs.student.term.hub.LinkMapper; +import edu.brown.cs.student.term.profit.ProfitCalculation; import edu.brown.cs.student.term.profit.StockHolding; import edu.brown.cs.student.term.hub.SuspicionRanker; import edu.brown.cs.student.term.repl.Command; @@ -27,6 +26,7 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -124,7 +124,7 @@ public final class Main { } /** - * Gets the list of holders with id, name, and suspicion rank + * Gets the list of holders with id, name, and suspicion rank. */ private static class SuspicionRankHandler implements Route { @Override diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java deleted file mode 100644 index 88b4b04..0000000 --- a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java +++ /dev/null @@ -1,393 +0,0 @@ -package edu.brown.cs.student.term; - - -import edu.brown.cs.student.term.profit.StockHolding; -import org.eclipse.jetty.util.DecoratedObjectFactory; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - - -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.sql.Connection; -import java.sql.Date; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.LinkedList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ProfitCalculation { - private Connection conn; - private String person; - private Date startTime; - private Date endTime; - private boolean tablesFilled; - - private String BASE_URL = "https://data.alpaca.markets/v1"; - - private String API_KEY = "PKT53Z9QW0TMSSC9XNPQ"; - private String SECRET_KEY = "udvetWCvwyVmZgrjgCPfX3W0nprKBrbunh5wNnCv"; - - //map of stock to list of buy orders, first element in list is oldest - private Map> buyHistoryMap; - - //map of stock to list of buy orders, first element in list is oldest - private Map> sellHistoryMap; - - //map of stock to gains from sell orders - private Map realizedGainsMap; - - //map of stock to gains from increases in value of holdings - private Map unrealizedGainsMap; - - //map to store current prices of stocks -- to avoid repeated api calls - private Map currentStockPrices; - - private double moneyInput; - - /** - * constructor for ProfitCalculation. - * - * @param conn - database connection, with trade data. - * @param person - person of interest to calculate profit for. - * @param startTime - start of period to look at. - * @param endTime - end of period to look at. - */ - public ProfitCalculation(Connection conn, String person, Date startTime, Date endTime) { - this.conn = conn; - this.person = person; - this.startTime = startTime; - this.endTime = endTime; - buyHistoryMap = new HashMap<>(); - sellHistoryMap = new HashMap<>(); - realizedGainsMap = new HashMap<>(); - unrealizedGainsMap = new HashMap<>(); - currentStockPrices = new HashMap<>(); - tablesFilled = false; - } - - /** - * This method fills the maps of sell and buy orders with lists of oldest - new trades. - */ - private void organizeOrders() { - //get a list of trades for a person to consider - try { - PreparedStatement prep; - prep = - conn.prepareStatement("SELECT * FROM \'trades\' WHERE holder_name= ? " - + " AND trade_timestamp BETWEEN ? AND ?" - + "order by trade_timestamp asc;"); - prep.setString(1, this.person); - prep.setDate(2, startTime); - prep.setDate(3, endTime); - ResultSet rs = prep.executeQuery(); - - while (rs.next()) { - String ticker = rs.getString("stock_name"); - int shares = rs.getInt("number_of_shares"); - double price = rs.getDouble("share_price"); - OrderTuple order = new OrderTuple(shares, price, rs.getDate("trade_timestamp")); - - //one element list for first time ticker is seen. - LinkedList oneElement = new LinkedList(); - oneElement.addLast(order); - - //for buy orders, build up buy history - if (rs.getInt("is_buy") != 0) { - moneyInput += shares * price; - if (buyHistoryMap.containsKey(ticker)) { - buyHistoryMap.get(ticker).addLast(order); - } else { - buyHistoryMap.put(ticker, oneElement); - } - } else { - //ignore sell orders for which we do not have buys for - if (buyHistoryMap.containsKey(ticker)) { - if (sellHistoryMap.containsKey(ticker)) { - sellHistoryMap.get(ticker).addLast(order); - } else { - sellHistoryMap.put(ticker, oneElement); - } - } - } - - } - prep.close(); - } catch (SQLException e) { - System.out.println("ERROR: sql error getting trades"); - } - } - - /** - * This method processes the sell orders in the sellHistoryMap to get realized gains. - */ - private void getRealizedGains() { - for (String ticker : sellHistoryMap.keySet()) { - //use FIFO selling - LinkedList sells = sellHistoryMap.get(ticker); - LinkedList buys = buyHistoryMap.get(ticker); - double realizedGain = 0; - - //process each sell order (unless all buy orders are "drained" - for (OrderTuple sell : sells) { - //stop if buys are empty, stop if buy happened after sell - if (buys.isEmpty()) { - break; - } - - int sharesToSell = sell.getShares(); - - //sell off through list of buys - while (sharesToSell > 0 && !buys.isEmpty()) { - //dont sell from buys which didn't exist at the time. - if (sell.getDate().after(buys.getFirst().getDate())) { - OrderTuple buyBundle = buys.removeFirst(); - int sharesAtBundlePrice; - //the buy has more shares than we want to sell - if (buyBundle.getShares() > sharesToSell) { - sharesAtBundlePrice = sharesToSell; - sharesToSell = 0; - //add back the holdings that were not sold - buyBundle.setShares(buyBundle.getShares() - sharesAtBundlePrice); - buys.addFirst(buyBundle); - } else { - sharesToSell -= buyBundle.getShares(); - sharesAtBundlePrice = buyBundle.getShares(); - } - realizedGain += sharesAtBundlePrice * (sell.getCost() - buyBundle.getCost()); - } else { - break; - } - - - } - } - - realizedGainsMap.put(ticker, realizedGain); - } - } - - /** - * get the change in value of stocks which are still held. - */ - private void getUnrealizedGains() { - - //calculate change in value of holdings - for (String ticker : buyHistoryMap.keySet()) { - double unrealizedGains = 0; - - double currentPrice = getCurrentPrice(ticker); - if (currentPrice != -1) { - LinkedList stockHistory = buyHistoryMap.get(ticker); - for (OrderTuple order : stockHistory) { - unrealizedGains += order.getShares() * (currentPrice - order.getCost()); - } - } - unrealizedGainsMap.put(ticker, unrealizedGains); - } - } - - private final class OrderTuple { - private int shares; - private double cost; - private Date date; - - private OrderTuple(int shares, double cost, Date date) { - this.shares = shares; - this.cost = cost; - this.date = date; - } - - public double getCost() { - return cost; - } - - public int getShares() { - return shares; - } - - public Date getDate() { - return date; - } - - public void setShares(int shares) { - this.shares = shares; - } - } - - private double getCurrentPrice(String ticker) { - if (currentStockPrices.containsKey(ticker)) { - return currentStockPrices.get(ticker); - } else { - String PRICE_URL = BASE_URL + "/last/stocks/" + ticker; - - HttpClient client = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(PRICE_URL)).setHeader("APCA-API-KEY-ID", API_KEY) - .setHeader("APCA-API-SECRET-KEY", SECRET_KEY) - .build(); - - HttpResponse response = null; - try { - response = client.send(request, - HttpResponse.BodyHandlers.ofString()); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - - JSONObject object = new JSONObject(response.body()); - try { - double price = object.getJSONObject("last").getDouble("price"); - currentStockPrices.put(ticker, price); - return price; - } catch (JSONException e) { - currentStockPrices.put(ticker, -1.0); - return -1.0; - } - } - - - } - - public double calculateGains() { - if (!tablesFilled) { - organizeOrders(); - getRealizedGains(); - getUnrealizedGains(); - tablesFilled = true; - } - double realizedGains = 0; - double unrealizedGains = 0; - - for (double value : realizedGainsMap.values()) { - realizedGains += value; - } - - for (double value : unrealizedGainsMap.values()) { - unrealizedGains += value; - } - return unrealizedGains + realizedGains; - } - - public List getHoldingsList() { - if (!tablesFilled) { - organizeOrders(); - getRealizedGains(); - getUnrealizedGains(); - tablesFilled = true; - } - - List holdings = new LinkedList<>(); - - for (String key : buyHistoryMap.keySet()) { - double realizedGains = 0; - double unrealizedGains = 0; - if (unrealizedGainsMap.containsKey(key)) { - unrealizedGains = unrealizedGainsMap.get(key); - } - if (realizedGainsMap.containsKey(key)) { - realizedGains = realizedGainsMap.get(key); - } - - int shares = 0; - for (OrderTuple order : buyHistoryMap.get(key)) { - shares += order.getShares(); - } - holdings.add(new StockHolding(key, realizedGains, unrealizedGains, shares)); - } - return holdings; - } - - /** - * return percent change in SPY (SP 500) over the time period. - */ - public double compareToSP500() { - String url = "https://data.alpaca.markets/v1/bars/" - + "day?" - + "symbols=SPY" - + "&start=" + startTime - + "&end=" + endTime; - - HttpClient client = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)).setHeader("APCA-API-KEY-ID", API_KEY) - .setHeader("APCA-API-SECRET-KEY", SECRET_KEY) - .build(); - - HttpResponse response = null; - try { - response = client.send(request, - HttpResponse.BodyHandlers.ofString()); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - JSONArray object = new JSONObject(response.body()).getJSONArray("SPY"); - - //get close price of start SPY at start time - double startPrice = object.getJSONObject(0).getDouble("c"); - double endPrice = object.getJSONObject(object.length() - 1).getDouble("c"); - //get percent change - //end - start /start - return ((endPrice - startPrice) / startPrice); - - } - - /** - * get a map for all people in the timeframe of holder_id to percent gain. - * - * @return a map of holder_id to percent gain - */ - public Map getProfitMap() { - Map profitMap = new HashMap<>(); - try { - PreparedStatement prep; - prep = - conn.prepareStatement("SELECT * from trades group by holder_name;"); - ResultSet rs = prep.executeQuery(); - while (rs.next()) { - int id = rs.getInt("holder_id"); - this.person = rs.getString("holder_name"); - //TODO: Temporary fix for the moneyinput divide by 0 error - if(moneyInput == 0){ - moneyInput = 1; - } - profitMap.put(id, this.calculateGains() / moneyInput); - } - } catch (SQLException throwables) { - System.out.println("ERROR: SQl error in profit calculation"); - } - System.out.println(profitMap.toString()); - return profitMap; - } - - public double getMoneyInput() { - return this.moneyInput; - } - - public void setConnection(String filename) throws SQLException, ClassNotFoundException { - - // Initialize the database connection, turn foreign keys on - Class.forName("org.sqlite.JDBC"); - String urlToDB = "jdbc:sqlite:" + filename; - conn = DriverManager.getConnection(urlToDB); - - Statement stat = conn.createStatement(); - stat.executeUpdate("PRAGMA foreign_keys=ON;"); - } - -} diff --git a/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java b/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java index dd959f0..9f5f9c1 100644 --- a/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java +++ b/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java @@ -1,7 +1,7 @@ package edu.brown.cs.student.term.hub; import edu.brown.cs.student.term.DatabaseQuerier; -import edu.brown.cs.student.term.ProfitCalculation; +import edu.brown.cs.student.term.profit.ProfitCalculation; import java.time.Instant; import java.sql.Date; @@ -10,7 +10,8 @@ import java.util.*; public class SuspicionRanker { DatabaseQuerier querier; - public SuspicionRanker(DatabaseQuerier db){ + + public SuspicionRanker(DatabaseQuerier db) { this.querier = db; } @@ -21,7 +22,7 @@ public class SuspicionRanker { return maxEntry.getValue(); } - public List getSuspicionScoreList(Instant start, Instant end){ + public List getSuspicionScoreList(Instant start, Instant end) { List suspicionList = new ArrayList<>(); try { LinkMapper lm = new LinkMapper(querier); @@ -29,8 +30,8 @@ public class SuspicionRanker { Map holderToHubScore = hub.runHubSearch(start, end); ProfitCalculation pc = new ProfitCalculation(DatabaseQuerier.getConn(), "", - new Date(start.toEpochMilli()), - new Date(end.toEpochMilli())); + new Date(start.toEpochMilli()), + new Date(end.toEpochMilli())); Map profitMap = pc.getProfitMap(); @@ -38,7 +39,7 @@ public class SuspicionRanker { double hubMax = getMaxOfMap(holderToHubScore); - for(Holder guy: holderToHubScore.keySet()){ + for (Holder guy : holderToHubScore.keySet()) { double normalizedProfitScore = profitMap.get(guy.getId()) / profitMax; double normalizedHubScore = holderToHubScore.get(guy) / hubMax; double suspicionScore = normalizedHubScore * 0.6 + normalizedProfitScore * 0.4; diff --git a/src/main/java/edu/brown/cs/student/term/profit/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/profit/ProfitCalculation.java new file mode 100644 index 0000000..85b2a9a --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/profit/ProfitCalculation.java @@ -0,0 +1,393 @@ +package edu.brown.cs.student.term.profit; + + +import edu.brown.cs.student.term.profit.StockHolding; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.sql.Connection; +import java.sql.Date; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.LinkedList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ProfitCalculation { + private Connection conn; + private String person; + private Date startTime; + private Date endTime; + private boolean tablesFilled; + + private String BASE_URL = "https://data.alpaca.markets/v1"; + + private String API_KEY = "PKT53Z9QW0TMSSC9XNPQ"; + private String SECRET_KEY = "udvetWCvwyVmZgrjgCPfX3W0nprKBrbunh5wNnCv"; + + //map of stock to list of buy orders, first element in list is oldest + private Map> buyHistoryMap; + + //map of stock to list of buy orders, first element in list is oldest + private Map> sellHistoryMap; + + //map of stock to gains from sell orders + private Map realizedGainsMap; + + //map of stock to gains from increases in value of holdings + private Map unrealizedGainsMap; + + //map to store current prices of stocks -- to avoid repeated api calls + private Map currentStockPrices; + + private double moneyInput; + + /** + * constructor for ProfitCalculation. + * + * @param conn - database connection, with trade data. + * @param person - person of interest to calculate profit for. + * @param startTime - start of period to look at. + * @param endTime - end of period to look at. + */ + public ProfitCalculation(Connection conn, String person, Date startTime, Date endTime) { + this.conn = conn; + this.person = person; + this.startTime = startTime; + this.endTime = endTime; + buyHistoryMap = new HashMap<>(); + sellHistoryMap = new HashMap<>(); + realizedGainsMap = new HashMap<>(); + unrealizedGainsMap = new HashMap<>(); + currentStockPrices = new HashMap<>(); + tablesFilled = false; + } + + /** + * This method fills the maps of sell and buy orders with lists of oldest - new trades. + */ + private void organizeOrders() { + //get a list of trades for a person to consider + try { + PreparedStatement prep; + prep = + conn.prepareStatement("SELECT * FROM \'trades\' WHERE holder_name= ? " + + " AND trade_timestamp BETWEEN ? AND ?" + + "order by trade_timestamp asc;"); + prep.setString(1, this.person); + prep.setDate(2, startTime); + prep.setDate(3, endTime); + ResultSet rs = prep.executeQuery(); + + while (rs.next()) { + String ticker = rs.getString("stock_name"); + int shares = rs.getInt("number_of_shares"); + double price = rs.getDouble("share_price"); + OrderTuple order = new OrderTuple(shares, price, rs.getDate("trade_timestamp")); + + //one element list for first time ticker is seen. + LinkedList oneElement = new LinkedList(); + oneElement.addLast(order); + + //for buy orders, build up buy history + if (rs.getInt("is_buy") != 0) { + moneyInput += shares * price; + if (buyHistoryMap.containsKey(ticker)) { + buyHistoryMap.get(ticker).addLast(order); + } else { + buyHistoryMap.put(ticker, oneElement); + } + } else { + //ignore sell orders for which we do not have buys for + if (buyHistoryMap.containsKey(ticker)) { + if (sellHistoryMap.containsKey(ticker)) { + sellHistoryMap.get(ticker).addLast(order); + } else { + sellHistoryMap.put(ticker, oneElement); + } + } + } + + } + prep.close(); + } catch (SQLException e) { + System.out.println("ERROR: sql error getting trades"); + } + } + + /** + * This method processes the sell orders in the sellHistoryMap to get realized gains. + */ + private void getRealizedGains() { + for (String ticker : sellHistoryMap.keySet()) { + //use FIFO selling + LinkedList sells = sellHistoryMap.get(ticker); + LinkedList buys = buyHistoryMap.get(ticker); + double realizedGain = 0; + + //process each sell order (unless all buy orders are "drained" + for (OrderTuple sell : sells) { + //stop if buys are empty, stop if buy happened after sell + if (buys.isEmpty()) { + break; + } + + int sharesToSell = sell.getShares(); + + //sell off through list of buys + while (sharesToSell > 0 && !buys.isEmpty()) { + //dont sell from buys which didn't exist at the time. + if (sell.getDate().after(buys.getFirst().getDate())) { + OrderTuple buyBundle = buys.removeFirst(); + int sharesAtBundlePrice; + //the buy has more shares than we want to sell + if (buyBundle.getShares() > sharesToSell) { + sharesAtBundlePrice = sharesToSell; + sharesToSell = 0; + //add back the holdings that were not sold + buyBundle.setShares(buyBundle.getShares() - sharesAtBundlePrice); + buys.addFirst(buyBundle); + } else { + sharesToSell -= buyBundle.getShares(); + sharesAtBundlePrice = buyBundle.getShares(); + } + realizedGain += sharesAtBundlePrice * (sell.getCost() - buyBundle.getCost()); + } else { + break; + } + + + } + } + + realizedGainsMap.put(ticker, realizedGain); + } + } + + /** + * get the change in value of stocks which are still held. + */ + private void getUnrealizedGains() { + + //calculate change in value of holdings + for (String ticker : buyHistoryMap.keySet()) { + double unrealizedGains = 0; + + double currentPrice = getCurrentPrice(ticker); + if (currentPrice != -1) { + LinkedList stockHistory = buyHistoryMap.get(ticker); + for (OrderTuple order : stockHistory) { + unrealizedGains += order.getShares() * (currentPrice - order.getCost()); + } + } + unrealizedGainsMap.put(ticker, unrealizedGains); + } + } + + private final class OrderTuple { + private int shares; + private double cost; + private Date date; + + private OrderTuple(int shares, double cost, Date date) { + this.shares = shares; + this.cost = cost; + this.date = date; + } + + public double getCost() { + return cost; + } + + public int getShares() { + return shares; + } + + public Date getDate() { + return date; + } + + public void setShares(int shares) { + this.shares = shares; + } + } + + private double getCurrentPrice(String ticker) { + if (currentStockPrices.containsKey(ticker)) { + return currentStockPrices.get(ticker); + } else { + String PRICE_URL = BASE_URL + "/last/stocks/" + ticker; + + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(PRICE_URL)).setHeader("APCA-API-KEY-ID", API_KEY) + .setHeader("APCA-API-SECRET-KEY", SECRET_KEY) + .build(); + + HttpResponse response = null; + try { + response = client.send(request, + HttpResponse.BodyHandlers.ofString()); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + JSONObject object = new JSONObject(response.body()); + try { + double price = object.getJSONObject("last").getDouble("price"); + currentStockPrices.put(ticker, price); + return price; + } catch (JSONException e) { + currentStockPrices.put(ticker, -1.0); + return -1.0; + } + } + + + } + + public double calculateGains() { + if (!tablesFilled) { + organizeOrders(); + getRealizedGains(); + getUnrealizedGains(); + tablesFilled = true; + } + double realizedGains = 0; + double unrealizedGains = 0; + + for (double value : realizedGainsMap.values()) { + realizedGains += value; + } + + for (double value : unrealizedGainsMap.values()) { + unrealizedGains += value; + } + return unrealizedGains + realizedGains; + } + + public List getHoldingsList() { + if (!tablesFilled) { + organizeOrders(); + getRealizedGains(); + getUnrealizedGains(); + tablesFilled = true; + } + + List holdings = new LinkedList<>(); + + for (String key : buyHistoryMap.keySet()) { + double realizedGains = 0; + double unrealizedGains = 0; + if (unrealizedGainsMap.containsKey(key)) { + unrealizedGains = unrealizedGainsMap.get(key); + } + if (realizedGainsMap.containsKey(key)) { + realizedGains = realizedGainsMap.get(key); + } + + int shares = 0; + for (OrderTuple order : buyHistoryMap.get(key)) { + shares += order.getShares(); + } + holdings.add(new StockHolding(key, realizedGains, unrealizedGains, shares)); + } + return holdings; + } + + /** + * return percent change in SPY (SP 500) over the time period. + */ + public double compareToSP500() { + String url = "https://data.alpaca.markets/v1/bars/" + + "day?" + + "symbols=SPY" + + "&start=" + startTime + + "&end=" + endTime; + + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)).setHeader("APCA-API-KEY-ID", API_KEY) + .setHeader("APCA-API-SECRET-KEY", SECRET_KEY) + .build(); + + HttpResponse response = null; + try { + response = client.send(request, + HttpResponse.BodyHandlers.ofString()); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + JSONArray object = new JSONObject(response.body()).getJSONArray("SPY"); + + //get close price of start SPY at start time + double startPrice = object.getJSONObject(0).getDouble("c"); + double endPrice = object.getJSONObject(object.length() - 1).getDouble("c"); + //get percent change + //end - start /start + return ((endPrice - startPrice) / startPrice); + + } + + /** + * get a map for all people in the timeframe of holder_id to percent gain. + * + * @return a map of holder_id to percent gain + */ + public Map getProfitMap() { + Map profitMap = new HashMap<>(); + try { + PreparedStatement prep; + prep = + conn.prepareStatement("SELECT * from trades group by holder_name;"); + ResultSet rs = prep.executeQuery(); + while (rs.next()) { + int id = rs.getInt("holder_id"); + this.person = rs.getString("holder_name"); + if (moneyInput == 0) { + profitMap.put(id, 0.0); + } else { + profitMap.put(id, this.calculateGains() / moneyInput); + } + + } + } catch (SQLException throwables) { + System.out.println("ERROR: SQl error in profit calculation"); + } + System.out.println(profitMap.toString()); + return profitMap; + } + + public double getMoneyInput() { + return this.moneyInput; + } + + public void setConnection(String filename) throws SQLException, ClassNotFoundException { + + // Initialize the database connection, turn foreign keys on + Class.forName("org.sqlite.JDBC"); + String urlToDB = "jdbc:sqlite:" + filename; + conn = DriverManager.getConnection(urlToDB); + + Statement stat = conn.createStatement(); + stat.executeUpdate("PRAGMA foreign_keys=ON;"); + } + +} -- cgit v1.2.3-70-g09d2