From 2402ca839b33d4c16c59e43575a5791e1c6e7630 Mon Sep 17 00:00:00 2001 From: clarkohw Date: Wed, 31 Mar 2021 21:52:50 -0400 Subject: inital code for profit calculations --- src/main/java/edu/brown/cs/student/term/Main.java | 26 +++-- .../brown/cs/student/term/ProfitCalculation.java | 121 +++++++++++++++++++++ 2 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 src/main/java/edu/brown/cs/student/term/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 c436b2e..e6584f1 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -5,11 +5,15 @@ import edu.brown.cs.student.term.repl.REPL; import joptsimple.OptionParser; import joptsimple.OptionSet; +import java.sql.Connection; +import java.sql.Date; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; import java.util.HashMap; /** * The Main class of our project. This is where execution begins. - * */ public final class Main { @@ -18,8 +22,7 @@ public final class Main { /** * The initial method called when execution begins. * - * @param args - * An array of command line arguments + * @param args An array of command line arguments */ public static void main(String[] args) { new Main(args).run(); @@ -36,7 +39,7 @@ public final class Main { OptionParser parser = new OptionParser(); parser.accepts("gui"); parser.accepts("port").withRequiredArg().ofType(Integer.class) - .defaultsTo(DEFAULT_PORT); + .defaultsTo(DEFAULT_PORT); OptionSet options = parser.parse(args); if (options.has("gui")) { @@ -44,11 +47,18 @@ public final class Main { //runSparkServer((int) options.valueOf("port")); } - HashMap commandHashMap = new HashMap<>(); - /** add commands to map here! */ - REPL repl = new REPL(commandHashMap); - repl.runREPL(); + + ProfitCalculation person = new ProfitCalculation(null, "Vincent", new Date(1615629591000L), new Date(1615507898000L)); + person.setConnection("./data/mock_tradeClarks.sqlite3"); + person.calculateGains(); + +// HashMap commandHashMap = new HashMap<>(); +// /** add commands to map here! */ +// REPL repl = new REPL(commandHashMap); +// repl.runREPL(); // TODO: Process commands in a REPL } + + } \ No newline at end of file diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java new file mode 100644 index 0000000..7c275d2 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java @@ -0,0 +1,121 @@ +package edu.brown.cs.student.term; + +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.List; +import java.util.HashMap; + +public class ProfitCalculation { + private Connection conn; + private String person; + Date startTime; + Date endTime; + + /** + * 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; + } + + /** + * calculate the gains for a given person in a specified time. + * + * @return + */ + public double calculateGains() { + HashMap> buyHistory = new HashMap>(); + HashMap perStockGain = new HashMap(); + double totalGain = 0; + //query for List per person + + try { + PreparedStatement prep; + prep = conn.prepareStatement("SELECT * FROM \'users\' WHERE user_id= ?;"); + //prep.setString(1, id); + ResultSet rs = prep.executeQuery(); + while (rs.next()) { + boolean buy = true; + String ticker = "STOCK"; + //for buy orders, build up buy history + if (buy) { + int sharesBought = 99; + double cost = 420.0; + + //add a buy to the end of a history for a given stock + if (buyHistory.containsKey(ticker)) { + buyHistory.get(ticker).addLast(new BuyTuple(sharesBought, cost)); + } else { + LinkedList tickerHistory = new LinkedList<>(); + tickerHistory.add(new BuyTuple(sharesBought, cost)); + buyHistory.put(ticker, tickerHistory); + } + //for sell orders, calculate realized gains + } else { +// int sharesSold = 99; +// if (buyHistory.containsKey(ticker)) { +// LinkedList = +// } + + } + + } + prep.close(); + } catch (SQLException e) { + System.out.println("ERROR: sql error getting trades"); + } + + + //FOR EACH RESULT in ResultsSet... + //if buy: add to hashmap tuple entry (shares, cost) to hashmap + // - get cost of stock at time of purchase + //if sell: check if we hold this stock. If so use FIFO to sell + + return totalGain; + } + + private class BuyTuple { + private int shares; + private double cost; + + private BuyTuple(int shares, double cost) { + this.shares = shares; + this.cost = cost; + } + + public double getCost() { + return cost; + } + + public int getShares() { + return shares; + } + } + + 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 From d2cb17744211b73080fa5ae476843e5acd52946b Mon Sep 17 00:00:00 2001 From: clarkohw Date: Sat, 3 Apr 2021 19:43:18 -0400 Subject: before restructuring --- data/mock_tradeTesting.sqlite3 | Bin 0 -> 45056 bytes src/main/java/edu/brown/cs/student/term/Main.java | 9 +- .../brown/cs/student/term/ProfitCalculation.java | 115 ++++++++++++++++----- 3 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 data/mock_tradeTesting.sqlite3 (limited to 'src/main/java') diff --git a/data/mock_tradeTesting.sqlite3 b/data/mock_tradeTesting.sqlite3 new file mode 100644 index 0000000..9521fef Binary files /dev/null and b/data/mock_tradeTesting.sqlite3 differ 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 e6584f1..7838dd3 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -48,8 +48,13 @@ public final class Main { } - ProfitCalculation person = new ProfitCalculation(null, "Vincent", new Date(1615629591000L), new Date(1615507898000L)); - person.setConnection("./data/mock_tradeClarks.sqlite3"); + ProfitCalculation person = new ProfitCalculation(null, "Sophie", new Date(1615629591000L), new Date(1615507898000L)); + try { + person.setConnection("./data/mock_tradeClarks.sqlite3"); + } catch(Exception e) { + e.printStackTrace(); + } + person.calculateGains(); // HashMap commandHashMap = new HashMap<>(); diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java index 7c275d2..3975cef 100644 --- a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java +++ b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java @@ -10,12 +10,25 @@ import java.sql.Statement; import java.util.LinkedList; import java.util.List; import java.util.HashMap; +import java.util.Map; public class ProfitCalculation { private Connection conn; private String person; - Date startTime; - Date endTime; + private Date startTime; + private Date endTime; + + //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; /** * constructor for ProfitCalculation. @@ -38,38 +51,66 @@ public class ProfitCalculation { * @return */ public double calculateGains() { - HashMap> buyHistory = new HashMap>(); + HashMap> buyHistory = new HashMap>(); HashMap perStockGain = new HashMap(); - double totalGain = 0; - //query for List per person + double realizedGain = 0; + double netWorthGain = 0; + //get a list of trades for a person to consider try { PreparedStatement prep; - prep = conn.prepareStatement("SELECT * FROM \'users\' WHERE user_id= ?;"); - //prep.setString(1, id); + // TODO: add start and end time + prep = + conn.prepareStatement("SELECT * FROM \'trades\' WHERE holder_name= ? " + + "order by trade_timestamp asc;"); + prep.setString(1, this.person); + //prep.setString(2, "NVDA"); ResultSet rs = prep.executeQuery(); + while (rs.next()) { - boolean buy = true; - String ticker = "STOCK"; + String ticker = rs.getString("stock_name"); + //for buy orders, build up buy history - if (buy) { - int sharesBought = 99; - double cost = 420.0; + if (rs.getInt("is_buy") != 0) { + int sharesBought = rs.getInt("number_of_shares"); + double cost = rs.getDouble("trade_amount") / sharesBought; //add a buy to the end of a history for a given stock if (buyHistory.containsKey(ticker)) { - buyHistory.get(ticker).addLast(new BuyTuple(sharesBought, cost)); + buyHistory.get(ticker).addLast(new OrderTuple(sharesBought, cost)); } else { - LinkedList tickerHistory = new LinkedList<>(); - tickerHistory.add(new BuyTuple(sharesBought, cost)); + LinkedList tickerHistory = new LinkedList<>(); + tickerHistory.add(new OrderTuple(sharesBought, cost)); buyHistory.put(ticker, tickerHistory); } //for sell orders, calculate realized gains } else { -// int sharesSold = 99; -// if (buyHistory.containsKey(ticker)) { -// LinkedList = -// } + int sharesSold = rs.getInt("number_of_shares"); + double shareSellPrice = rs.getDouble("trade_amount") / sharesSold; + if (buyHistory.containsKey(ticker)) { + LinkedList stockHistory = buyHistory.get(ticker); + + //use FIFO sell off to realize gains + while (sharesSold > 0 && !stockHistory.isEmpty()) { + OrderTuple buyBundle = stockHistory.removeFirst(); + int sharesAtBundlePrice; + if (buyBundle.getShares() > sharesSold) { + sharesAtBundlePrice = sharesSold; + sharesSold = 0; + //add back the holdings that were not sold + stockHistory + .addFirst( + new OrderTuple(buyBundle.getShares() - sharesAtBundlePrice, + buyBundle.getCost())); + } else { + sharesSold -= buyBundle.getShares(); + sharesAtBundlePrice = buyBundle.getShares(); + } + realizedGain += sharesAtBundlePrice * (shareSellPrice - buyBundle.getCost()); + + } + + } } @@ -80,19 +121,23 @@ public class ProfitCalculation { } - //FOR EACH RESULT in ResultsSet... - //if buy: add to hashmap tuple entry (shares, cost) to hashmap - // - get cost of stock at time of purchase - //if sell: check if we hold this stock. If so use FIFO to sell - - return totalGain; + //calculate change in value of holdings + for (String ticker : buyHistory.keySet()) { + double currentPrice = getCurrentPrice(ticker); + LinkedList stockHistory = buyHistory.get(ticker); + for (OrderTuple order : stockHistory) { + netWorthGain += order.getShares() * (currentPrice - order.getCost()); + } + } + System.out.println(realizedGain + netWorthGain); + return realizedGain + netWorthGain; } - private class BuyTuple { + private class OrderTuple { private int shares; private double cost; - private BuyTuple(int shares, double cost) { + private OrderTuple(int shares, double cost) { this.shares = shares; this.cost = cost; } @@ -106,6 +151,15 @@ public class ProfitCalculation { } } + public double getCurrentPrice(String ticker) { + return 100.0; + } + + public double getPriceAtTime(String ticker, Date sellTime) { + return 100.0; + //shuold be able ot use amount + } + public void setConnection(String filename) throws SQLException, ClassNotFoundException { // Initialize the database connection, turn foreign keys on @@ -118,4 +172,11 @@ public class ProfitCalculation { } + + //TODO: HELPER METHODS + //organizeOrders() + //getRealizedGains() + //getUnrealizedGains() + + } -- cgit v1.2.3-70-g09d2 From cc40a75c75de80383f931d5b853db52d90d3ff72 Mon Sep 17 00:00:00 2001 From: clarkohw Date: Sat, 3 Apr 2021 20:51:02 -0400 Subject: important methods are implemented --- data/mock_tradeTesting.sqlite3 | Bin 45056 -> 45056 bytes src/main/java/edu/brown/cs/student/term/Main.java | 4 +- .../brown/cs/student/term/ProfitCalculation.java | 153 +++++++++++++-------- 3 files changed, 99 insertions(+), 58 deletions(-) (limited to 'src/main/java') diff --git a/data/mock_tradeTesting.sqlite3 b/data/mock_tradeTesting.sqlite3 index 9521fef..d8515fe 100644 Binary files a/data/mock_tradeTesting.sqlite3 and b/data/mock_tradeTesting.sqlite3 differ 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 7838dd3..3800837 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -55,7 +55,9 @@ public final class Main { e.printStackTrace(); } - person.calculateGains(); + person.organizeOrders(); + + System.out.println("hello"); // HashMap commandHashMap = new HashMap<>(); // /** add commands to map here! */ diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java index 3975cef..66891ce 100644 --- a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java +++ b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java @@ -30,6 +30,8 @@ public class ProfitCalculation { //map of stock to gains from increases in value of holdings private Map unrealizedGainsMap; + private double moneyInput; + /** * constructor for ProfitCalculation. * @@ -43,19 +45,16 @@ public class ProfitCalculation { this.person = person; this.startTime = startTime; this.endTime = endTime; + buyHistoryMap = new HashMap<>(); + sellHistoryMap = new HashMap<>(); + realizedGainsMap = new HashMap<>(); + unrealizedGainsMap = new HashMap<>(); } /** - * calculate the gains for a given person in a specified time. - * - * @return + * This method fills the maps of sell and buy orders with lists of oldest - new trades */ - public double calculateGains() { - HashMap> buyHistory = new HashMap>(); - HashMap perStockGain = new HashMap(); - double realizedGain = 0; - double netWorthGain = 0; - + public void organizeOrders() { //get a list of trades for a person to consider try { PreparedStatement prep; @@ -69,49 +68,33 @@ public class ProfitCalculation { while (rs.next()) { String ticker = rs.getString("stock_name"); + int shares = rs.getInt("number_of_shares"); + double price = rs.getDouble("trade_amount") / shares; + 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) { - int sharesBought = rs.getInt("number_of_shares"); - double cost = rs.getDouble("trade_amount") / sharesBought; - - //add a buy to the end of a history for a given stock - if (buyHistory.containsKey(ticker)) { - buyHistory.get(ticker).addLast(new OrderTuple(sharesBought, cost)); + moneyInput += shares * price; + if (buyHistoryMap.containsKey(ticker)) { + buyHistoryMap.get(ticker).addLast(order); } else { - LinkedList tickerHistory = new LinkedList<>(); - tickerHistory.add(new OrderTuple(sharesBought, cost)); - buyHistory.put(ticker, tickerHistory); + buyHistoryMap.put(ticker, oneElement); } - //for sell orders, calculate realized gains - } else { - int sharesSold = rs.getInt("number_of_shares"); - double shareSellPrice = rs.getDouble("trade_amount") / sharesSold; - if (buyHistory.containsKey(ticker)) { - LinkedList stockHistory = buyHistory.get(ticker); - - //use FIFO sell off to realize gains - while (sharesSold > 0 && !stockHistory.isEmpty()) { - OrderTuple buyBundle = stockHistory.removeFirst(); - int sharesAtBundlePrice; - if (buyBundle.getShares() > sharesSold) { - sharesAtBundlePrice = sharesSold; - sharesSold = 0; - //add back the holdings that were not sold - stockHistory - .addFirst( - new OrderTuple(buyBundle.getShares() - sharesAtBundlePrice, - buyBundle.getCost())); - } else { - sharesSold -= buyBundle.getShares(); - sharesAtBundlePrice = buyBundle.getShares(); - } - realizedGain += sharesAtBundlePrice * (shareSellPrice - buyBundle.getCost()); - + } + //for sell orders build up sell history + 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); } - } - } } @@ -119,27 +102,81 @@ public class ProfitCalculation { } catch (SQLException e) { System.out.println("ERROR: sql error getting trades"); } + } + + /** + * This method processes the sell orders in the sellHistoryMap to get realized gains + */ + public 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() && + !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()); + } + } + + realizedGainsMap.put(ticker, realizedGain); + } + } + /** + * get the change in value of stocks which are still held + */ + public void getUnrealizedGains() { //calculate change in value of holdings - for (String ticker : buyHistory.keySet()) { + for (String ticker : buyHistoryMap.keySet()) { + double unrealizedGains = 0; + double currentPrice = getCurrentPrice(ticker); - LinkedList stockHistory = buyHistory.get(ticker); + LinkedList stockHistory = buyHistoryMap.get(ticker); for (OrderTuple order : stockHistory) { - netWorthGain += order.getShares() * (currentPrice - order.getCost()); + unrealizedGains += order.getShares() * (currentPrice - order.getCost()); } + + unrealizedGainsMap.put(ticker, unrealizedGains); } - System.out.println(realizedGain + netWorthGain); - return realizedGain + netWorthGain; } + private class OrderTuple { private int shares; private double cost; + private Date date; - private OrderTuple(int shares, double cost) { + private OrderTuple(int shares, double cost, Date date) { this.shares = shares; this.cost = cost; + this.date = date; } public double getCost() { @@ -149,15 +186,18 @@ public class ProfitCalculation { public int getShares() { return shares; } - } - public double getCurrentPrice(String ticker) { - return 100.0; + public Date getDate() { + return date; + } + + public void setShares(int shares) { + this.shares = shares; + } } - public double getPriceAtTime(String ticker, Date sellTime) { + public double getCurrentPrice(String ticker) { return 100.0; - //shuold be able ot use amount } public void setConnection(String filename) throws SQLException, ClassNotFoundException { @@ -172,7 +212,6 @@ public class ProfitCalculation { } - //TODO: HELPER METHODS //organizeOrders() //getRealizedGains() -- cgit v1.2.3-70-g09d2 From 1ace13266306f534182622387c249f1728780603 Mon Sep 17 00:00:00 2001 From: clarkohw Date: Sun, 4 Apr 2021 15:40:14 -0400 Subject: price works, but api limits calls --- ...rm-project-cohwille-jmccaul3-mfoiani-rhunt2.iml | 34 +--------- pom.xml | 5 ++ src/main/java/edu/brown/cs/student/term/Main.java | 4 +- .../brown/cs/student/term/ProfitCalculation.java | 75 ++++++++++++++++++++-- 4 files changed, 77 insertions(+), 41 deletions(-) (limited to 'src/main/java') diff --git a/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml b/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml index ec06211..415cd3d 100644 --- a/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml +++ b/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml @@ -48,38 +48,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index a2bd1a7..7172753 100644 --- a/pom.xml +++ b/pom.xml @@ -116,6 +116,11 @@ sqlite-jdbc 3.30.1 + + org.json + json + 20201115 + 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 3800837..7838dd3 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -55,9 +55,7 @@ public final class Main { e.printStackTrace(); } - person.organizeOrders(); - - System.out.println("hello"); + person.calculateGains(); // HashMap commandHashMap = new HashMap<>(); // /** add commands to map here! */ diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java index 66891ce..998ea26 100644 --- a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java +++ b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java @@ -1,5 +1,20 @@ package edu.brown.cs.student.term; + +import org.json.JSONObject; + + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URI; +import java.net.URL; +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; @@ -54,7 +69,7 @@ public class ProfitCalculation { /** * This method fills the maps of sell and buy orders with lists of oldest - new trades */ - public void organizeOrders() { + private void organizeOrders() { //get a list of trades for a person to consider try { PreparedStatement prep; @@ -107,7 +122,7 @@ public class ProfitCalculation { /** * This method processes the sell orders in the sellHistoryMap to get realized gains */ - public void getRealizedGains() { + private void getRealizedGains() { for (String ticker : sellHistoryMap.keySet()) { //use FIFO selling LinkedList sells = sellHistoryMap.get(ticker); @@ -151,7 +166,7 @@ public class ProfitCalculation { /** * get the change in value of stocks which are still held */ - public void getUnrealizedGains() { + private void getUnrealizedGains() { //calculate change in value of holdings for (String ticker : buyHistoryMap.keySet()) { @@ -167,7 +182,6 @@ public class ProfitCalculation { } } - private class OrderTuple { private int shares; private double cost; @@ -197,9 +211,60 @@ public class ProfitCalculation { } public double getCurrentPrice(String ticker) { - return 100.0; + //get request for body string + //convert body to JSONObject + //object.getDouble("price") + + String API_KEY = "NW169NGWKDG9UGXO"; + String url = "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=" + + ticker + + "&apikey=" + + API_KEY; + + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)) + .build(); + + HttpResponse response = null; + try { + response = client.send(request, + HttpResponse.BodyHandlers.ofString()); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + System.out.println(response.body()); + JSONObject object = new JSONObject(response.body()); + return object.getJSONObject("Global Quote").getDouble("05. price"); + } + + public void calculateGains() { + organizeOrders(); + getRealizedGains(); + getUnrealizedGains(); + double totalGains = 0; + double realizedGains = 0; + double unrealizedGains = 0; + + for (double value : realizedGainsMap.values()) { + realizedGains += value; + } + + for (double value : unrealizedGainsMap.values()) { + unrealizedGains += value; + } + + totalGains = unrealizedGains + realizedGains; + + System.out.println( + "Total: " + totalGains + "| unrealized: " + unrealizedGains + " | realized: " + + realizedGains); } + public void setConnection(String filename) throws SQLException, ClassNotFoundException { // Initialize the database connection, turn foreign keys on -- cgit v1.2.3-70-g09d2 From 4d64de29117c7999d5770ab6fb0992c09e878f90 Mon Sep 17 00:00:00 2001 From: clarkohw Date: Sun, 4 Apr 2021 16:05:35 -0400 Subject: added price gettin function --- src/main/java/edu/brown/cs/student/term/Main.java | 2 +- .../brown/cs/student/term/ProfitCalculation.java | 25 ++++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) (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 7838dd3..fd352f7 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -48,7 +48,7 @@ public final class Main { } - ProfitCalculation person = new ProfitCalculation(null, "Sophie", new Date(1615629591000L), new Date(1615507898000L)); + ProfitCalculation person = new ProfitCalculation(null, "Vincent", new Date(1515629591000L), new Date(1715507898000L)); try { person.setConnection("./data/mock_tradeClarks.sqlite3"); } catch(Exception e) { diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java index 998ea26..021e48b 100644 --- a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java +++ b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java @@ -76,9 +76,11 @@ public class ProfitCalculation { // TODO: add start and end time 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.setString(2, "NVDA"); + prep.setDate(2, startTime); + prep.setDate(3, endTime); ResultSet rs = prep.executeQuery(); while (rs.next()) { @@ -215,15 +217,17 @@ public class ProfitCalculation { //convert body to JSONObject //object.getDouble("price") - String API_KEY = "NW169NGWKDG9UGXO"; - String url = "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=" - + ticker - + "&apikey=" - + API_KEY; + String BASE_URL = "https://data.alpaca.markets/v1"; + String PRICE_URL = BASE_URL + "/last/stocks/" + ticker; + + + String API_KEY = "PKT53Z9QW0TMSSC9XNPQ"; + String SECRET_KEY = "udvetWCvwyVmZgrjgCPfX3W0nprKBrbunh5wNnCv"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)) + .uri(URI.create(PRICE_URL)).setHeader("APCA-API-KEY-ID", API_KEY) + .setHeader("APCA-API-SECRET-KEY", SECRET_KEY) .build(); HttpResponse response = null; @@ -236,16 +240,15 @@ public class ProfitCalculation { e.printStackTrace(); } - System.out.println(response.body()); + JSONObject object = new JSONObject(response.body()); - return object.getJSONObject("Global Quote").getDouble("05. price"); + return object.getJSONObject("last").getDouble("price"); } public void calculateGains() { organizeOrders(); getRealizedGains(); getUnrealizedGains(); - double totalGains = 0; double realizedGains = 0; double unrealizedGains = 0; @@ -257,7 +260,7 @@ public class ProfitCalculation { unrealizedGains += value; } - totalGains = unrealizedGains + realizedGains; + double totalGains = unrealizedGains + realizedGains; System.out.println( "Total: " + totalGains + "| unrealized: " + unrealizedGains + " | realized: " + -- cgit v1.2.3-70-g09d2 From 32f6f0e6f9d9beb8476f00417f68276fa2247d4e Mon Sep 17 00:00:00 2001 From: clarkohw Date: Sun, 4 Apr 2021 20:44:11 -0400 Subject: added compare to market feature' --- src/main/java/edu/brown/cs/student/term/Main.java | 3 +- .../brown/cs/student/term/ProfitCalculation.java | 96 +++++++++++++++------- 2 files changed, 67 insertions(+), 32 deletions(-) (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 fd352f7..3124ea4 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -48,7 +48,7 @@ public final class Main { } - ProfitCalculation person = new ProfitCalculation(null, "Vincent", new Date(1515629591000L), new Date(1715507898000L)); + ProfitCalculation person = new ProfitCalculation(null, "Sophie", new Date(1515629591000L), new Date(1715507898000L)); try { person.setConnection("./data/mock_tradeClarks.sqlite3"); } catch(Exception e) { @@ -56,6 +56,7 @@ public final class Main { } person.calculateGains(); + person.compareToNASDAQ(); // HashMap commandHashMap = new HashMap<>(); // /** add commands to map here! */ diff --git a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java index 021e48b..6510194 100644 --- a/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java +++ b/src/main/java/edu/brown/cs/student/term/ProfitCalculation.java @@ -1,6 +1,7 @@ package edu.brown.cs.student.term; +import org.json.JSONArray; import org.json.JSONObject; @@ -33,6 +34,11 @@ public class ProfitCalculation { private Date startTime; private Date endTime; + 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; @@ -141,23 +147,28 @@ public class ProfitCalculation { int sharesToSell = sell.getShares(); //sell off through list of buys - while (sharesToSell > 0 && !buys.isEmpty() && - !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); + 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 { - sharesToSell -= buyBundle.getShares(); - sharesAtBundlePrice = buyBundle.getShares(); + break; } - realizedGain += sharesAtBundlePrice * (sell.getCost() - buyBundle.getCost()); + + } } @@ -213,17 +224,8 @@ public class ProfitCalculation { } public double getCurrentPrice(String ticker) { - //get request for body string - //convert body to JSONObject - //object.getDouble("price") - - String BASE_URL = "https://data.alpaca.markets/v1"; String PRICE_URL = BASE_URL + "/last/stocks/" + ticker; - - String API_KEY = "PKT53Z9QW0TMSSC9XNPQ"; - String SECRET_KEY = "udvetWCvwyVmZgrjgCPfX3W0nprKBrbunh5wNnCv"; - HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(PRICE_URL)).setHeader("APCA-API-KEY-ID", API_KEY) @@ -262,11 +264,50 @@ public class ProfitCalculation { double totalGains = unrealizedGains + realizedGains; + System.out.println("Money In: " + moneyInput); + System.out.println("Money Out: " + (moneyInput + totalGains)); + System.out.println("NASDAQ on money In: " + (moneyInput * compareToSP500())); System.out.println( "Total: " + totalGains + "| unrealized: " + unrealizedGains + " | realized: " + realizedGains); } + /** + * 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 1 + ((endPrice - startPrice) /startPrice); + + } public void setConnection(String filename) throws SQLException, ClassNotFoundException { @@ -279,11 +320,4 @@ public class ProfitCalculation { stat.executeUpdate("PRAGMA foreign_keys=ON;"); } - - //TODO: HELPER METHODS - //organizeOrders() - //getRealizedGains() - //getUnrealizedGains() - - } -- cgit v1.2.3-70-g09d2