diff --git a/.gitignore b/.gitignore index 07bdb9e..409a3c2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ */target/** .classpath .project -.settings/idea \ No newline at end of file +.settings/idea +target/ \ No newline at end of file diff --git a/pom.xml b/pom.xml index 22d934e..ac4e77e 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,48 @@ org.example untitled1 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + + com.konghq + unirest-java + 3.4.01 + + + junit + junit + 4.12 + test + + + junit + junit + 4.12 + test + + + org.postgresql + postgresql + 42.2.11 + + + org.decimal4j + decimal4j + 1.0.3 + + diff --git a/src/main/java/account/Portfolio.java b/src/main/java/account/Portfolio.java new file mode 100644 index 0000000..3c7dda6 --- /dev/null +++ b/src/main/java/account/Portfolio.java @@ -0,0 +1,108 @@ +package account; + +import org.decimal4j.util.DoubleRounder; +import stocks.StockEnum; + +import java.util.HashMap; +import java.util.Map; + +public class Portfolio { + private Map portfolio; + private Double buyingPower; + private Double currentPortfolioValue; + + public Portfolio() { + this.portfolio = new HashMap<>(); + this.buyingPower = 2500.00; + this.currentPortfolioValue = 0.00; + } + + public Double getBuyingPower() { + return buyingPower; + } + + public Double getCurrentPortfolioValue() { + return currentPortfolioValue + buyingPower; + } + + public boolean addStockToBasePortfolio(StockEnum stock, Integer numberOfShares){ + double costOfShares = stock.getOpen() * numberOfShares; + if (costOfShares < buyingPower){ + if(portfolio.containsKey(stock)){ + portfolio.replace(stock, portfolio.get(stock),portfolio.get(stock) + numberOfShares); + } else { + portfolio.put(stock,numberOfShares); + } + currentPortfolioValue = currentPortfolioValue + DoubleRounder.round((costOfShares),2); + buyingPower = DoubleRounder.round((buyingPower - costOfShares),2); + return true; + } else { + return false; + } + } + + public Double getEquityOfShare(String stock){ + for (Map.Entry s : portfolio.entrySet()) { + if (stock.equalsIgnoreCase(String.valueOf(s.getKey()))){ + return DoubleRounder.round((s.getKey().getOpen() * s.getValue()),2); + } + } + return null; + } + + public Integer getNumberOfShares(String stock){ + for(Map.Entry s : portfolio.entrySet()){ + if (stock.equalsIgnoreCase(String.valueOf(s.getKey()))){ + return s.getValue(); + } + } + return null; + } + + public Double getPortfolioDiversityOfShare(String stock){ + Double result = 0.00; + Double equityOfShare = getEquityOfShare(stock); + if(!stock.equalsIgnoreCase("cash")){ + result = DoubleRounder.round ((equityOfShare/getCurrentPortfolioValue()),2); + }else{ + result = DoubleRounder.round ((getBuyingPower()/getCurrentPortfolioValue()),2); + } + + return result; + } + + public Double getDiversityPercentage(String stock){ + return (getPortfolioDiversityOfShare(stock)*100); + } + + + public String getPositionOfShare(String stock){ + StockEnum currentStock = getStock(stock); + StringBuilder builder = new StringBuilder(); + builder.append("****YOUR POSITION****") + .append(String.format("\nSymbol = %s\nShares = %d\nEquity = %.2f\nDiversity = %.2f", + currentStock.getSymbol(), getNumberOfShares(stock),getEquityOfShare(stock),getDiversityPercentage(stock))); + builder.append("%"); + return builder.toString(); + } + + private StockEnum getStock(String stock){ + for (Map.Entry s: portfolio.entrySet()){ + if (String.valueOf(s.getKey()).equalsIgnoreCase(stock)){ + return s.getKey(); + } + } + return null; + } + + public String getAllPositions(){ + StringBuilder builder = new StringBuilder(); + for (Map.Entry s: portfolio.entrySet()) { + builder.append(getPositionOfShare(String.valueOf(s.getKey()))) + .append("\n"); + } + return builder.toString(); + } + + +} diff --git a/src/main/java/account/User.java b/src/main/java/account/User.java new file mode 100644 index 0000000..61c3ef3 --- /dev/null +++ b/src/main/java/account/User.java @@ -0,0 +1,4 @@ +package account; + +public class User { +} diff --git a/src/main/java/controller/ApiController.java b/src/main/java/controller/ApiController.java new file mode 100644 index 0000000..e48d2a2 --- /dev/null +++ b/src/main/java/controller/ApiController.java @@ -0,0 +1,27 @@ +package controller; + +import kong.unirest.HttpResponse; +import kong.unirest.Unirest; + +public class ApiController { + + public static String createApiQuery(String symbol){ + StringBuilder builder = new StringBuilder(); + //beginning part of the get() method + builder.append("https://alpha-vantage.p.rapidapi.com/query?datatype=json&symbol=") + .append(symbol.toUpperCase()) + .append("&function=TIME_SERIES_MONTHLY"); + + return builder.toString(); + } + + public static String fetchApiQuery(String yourQuery){ + HttpResponse response = Unirest.get(yourQuery) + .header("x-rapidapi-host", "alpha-vantage.p.rapidapi.com") + .header("x-rapidapi-key", "9c88018860msh40e297080f45ec6p13b769jsnc02453b1e456") + .asString(); + response.getBody(); + return response.getBody(); + } + +} diff --git a/src/main/java/sql/SqlController.java b/src/main/java/sql/SqlController.java new file mode 100644 index 0000000..5c92b05 --- /dev/null +++ b/src/main/java/sql/SqlController.java @@ -0,0 +1,60 @@ +package sql; + +import java.sql.*; + +public class SqlController { + private static Connection connection = null; + + public static void connectSqlServer(){ + try{ + Class.forName("org.postgresql.Driver"); + connection = DriverManager + .getConnection("jdbc:postgresql://localhost:5432/stocks"); + connection.setAutoCommit(false); + } catch (Exception e) { + e.printStackTrace(); + System.err.println(e.getClass().getName() + ": " + e.getMessage()); + System.exit(0); + } + System.out.println("Opened database successfully"); + + } + + public static void insertStock(){ + try { + Statement insert = connection.createStatement(); + String sql = "INSERT INTO _2020_03 (TICKER, OPEN, HIGH, LOW, CLOSE, VOLUME) " + + "VALUES ('MSFT', 165.3100, 175.0000, 138.5800, 145.7000, 636200296);"; + insert.executeUpdate(sql); + insert.close(); + connection.commit(); + connection.close(); + } catch (SQLException e) { + System.err.println( e.getClass().getName()+": "+ e.getMessage() ); + System.exit(0); + } + System.out.println("Records created successfully"); + } + + public static void getStock(String stock, String month){ + try{ + Statement insert = connection.createStatement(); + String sql = "SELECT * FROM " + month + + " WHERE TICKER = '" + stock.toUpperCase() + "';"; + ResultSet rs = insert.executeQuery(sql); + while (rs.next()){ + Double open = rs.getDouble("open"); + Double high = rs.getDouble("high"); + Double low = rs.getDouble("low"); + Double close = rs.getDouble("close"); + Integer volume = rs.getInt("volume"); + System.out.println(new StringBuilder().append(open + " ").append(high + " ") + .append(low + " ").append(close + " ").append(volume)); + } + } catch (SQLException e) { + System.err.println( e.getClass().getName()+": "+ e.getMessage() ); + System.exit(0); + } + System.out.println("Records created successfully"); + } +} diff --git a/src/main/java/stocks/Stock.java b/src/main/java/stocks/Stock.java new file mode 100644 index 0000000..7affe18 --- /dev/null +++ b/src/main/java/stocks/Stock.java @@ -0,0 +1,4 @@ +package stocks; + +public class Stock { +} diff --git a/src/main/java/stocks/StockEnum.java b/src/main/java/stocks/StockEnum.java new file mode 100644 index 0000000..6a45724 --- /dev/null +++ b/src/main/java/stocks/StockEnum.java @@ -0,0 +1,81 @@ +package stocks; + +import java.util.Date; + +public enum StockEnum { + + //------------------------------------STOCK INFO FOR 2008-12-31--------------------------------------- + + MICROSOFT("MSFT", 19.87, 21.25, 18.47, 19.44, 1546943400), + APPLE("AAPL", 91.30, 103.60, 84.55, 85.35, 721923100), + VISA("V", 51.00, 57.67, 47.53, 52.45, 141021400), + JPMORGANCHASE("JPM", 30.67, 37.70, 24.61, 31.53, 1154247300), + JOHNSONJOHNSON("JNJ", 57.66, 60.25, 54.95, 59.83, 315194900), + COCACOLA("COKE", 42.65, 46.00, 38.51, 45.96, 425300), + CHEVRON("CVX", 76.50, 81.92, 68.22, 73.97, 392060500), + BRITISHPETROLEUM("BP", 45.96, 50.10, 41.54, 46.74, 149495200), + EXXON("XOM", 77.89, 83.64, 72.68, 79.83, 996412900); + + //AAPL,V,JNJ,COKE,CVX,BP,XOM,JPM,MSFT + private String symbol; + private Double open; + private Double high; + private Double low; + private Double close; + private Integer volume; + + StockEnum(String symbol, Double open, Double high, Double low, Double close, Integer volume) { + this.symbol = symbol; + this.open = open; + this.high = high; + this.low = low; + this.close = close; + this.volume = volume; + } + + public String getSymbol() { + return symbol; + } + + public Double getOpen() { + return open; + } + + public Double getHigh() { + return high; + } + + public Double getLow() { + return low; + } + + public Double getClose() { + return close; + } + + public Integer getVolume() { + return volume; + } + + public void setNewPrice(Double newPrice){ + open = newPrice; + } + + public String getAllInfo() { + StringBuilder builder = new StringBuilder(); + String space = " "; + builder.append(getSymbol()) + .append(space) + .append(getOpen()) + .append(space) + .append(getHigh()) + .append(space) + .append(getLow()) + .append(space) + .append(getClose()) + .append(space) + .append(getVolume()); + return builder.toString(); + } + +} diff --git a/src/main/java/utilities/Console.java b/src/main/java/utilities/Console.java new file mode 100644 index 0000000..ec423ec --- /dev/null +++ b/src/main/java/utilities/Console.java @@ -0,0 +1,83 @@ +package utilities; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Scanner; + +public class Console { + + private final Scanner input; + private final PrintStream output; + + public Console(InputStream in, PrintStream out) { + this.input = new Scanner(in); + this.output = out; + } + + public void print(String val, Object... args) { + output.format(val, args); + } + + public void println(String val, Object... vals) { + print(val + "\n", vals); + } + + public void printlnS(String val, Object... vals) { + System.out.println(val); + } + + + public String getStringInput(String prompt, Object... args) { + println(prompt, args); + return input.nextLine(); + } + + public String getStringInputWithoutln(String prompt, Object... args) { + print(prompt, args); + return input.nextLine(); + } + + public Double getDoubleInput(String prompt, Object... args) { + String stringInput = getStringInput(prompt, args); + try { + Double doubleInput = Double.parseDouble(stringInput); + return doubleInput; + } catch (NumberFormatException nfe) { // TODO - Eliminate recursive nature + println("[ %s ] is an invalid user input!", stringInput); + println("Try inputting a numeric value!"); + return getDoubleInput(prompt, args); + } + } + + public Long getLongInput(String prompt, Object... args) { + String stringInput = getStringInput(prompt, args); + try { + Long longInput = Long.parseLong(stringInput); + return longInput; + } catch (NumberFormatException nfe) { // TODO - Eliminate recursive nature + println("[ %s ] is an invalid user input!", stringInput); + println("Try inputting an integer value!"); + return getLongInput(prompt, args); + } + } + + public Integer getIntegerInput(String prompt, Object... args) { + return getLongInput(prompt, args).intValue(); + } + + public Integer getIntegerInputWithoutln(String prompt, Object... args) { + while(true) { + print(prompt, args); + String stringInput = input.nextLine(); + try { + return Integer.parseInt(stringInput); + } catch (NumberFormatException nfe) { + println("Invalid Input! Try again."); + } + } + } + + public void pressEnterToCount(){ + getStringInputWithoutln("press enter to continue"); + } +} diff --git a/src/main/java/utilities/Messages.java b/src/main/java/utilities/Messages.java new file mode 100644 index 0000000..0bd1674 --- /dev/null +++ b/src/main/java/utilities/Messages.java @@ -0,0 +1,4 @@ +package utilities; + +public class Messages { +} diff --git a/src/test/java/Test.java b/src/test/java/Test.java index 092c751..7f8c0cc 100644 --- a/src/test/java/Test.java +++ b/src/test/java/Test.java @@ -1,4 +1,4 @@ -package java; public class Test { + } diff --git a/src/test/java/account/PortfolioTest.java b/src/test/java/account/PortfolioTest.java new file mode 100644 index 0000000..9a1286c --- /dev/null +++ b/src/test/java/account/PortfolioTest.java @@ -0,0 +1,108 @@ +package account; + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; +import stocks.StockEnum; +import stocks.StockEnumTest; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class PortfolioTest { + Portfolio portfolio; + + Logger logger = Logger.getLogger(PortfolioTest.class.getName()); + + @Before + public void setUP(){ + portfolio = new Portfolio(); + } + + @Test + public void addSingleStockTest(){ + assertTrue(portfolio.addStockToBasePortfolio(StockEnum.APPLE,4)); + assertEquals(2500.00, portfolio.getCurrentPortfolioValue(), 0.00); + assertEquals(2134.80, portfolio.getBuyingPower(), 0.00); + } + + @Test + public void addStockFailTest(){ + assertFalse(portfolio.addStockToBasePortfolio(StockEnum.APPLE,900)); + } + + @Test + public void addMultipleStocks(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,5); + Double expected = 2500.00; + Double actual = portfolio.getCurrentPortfolioValue(); + assertEquals(expected,actual); + assertEquals(1790.80, portfolio.getBuyingPower(), 0.0); + } + + @Test + public void getEquityOfShareTest(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,5); + Double expected = 153.35; + Double actual = portfolio.getEquityOfShare("jpmorganchase"); + assertEquals(expected,actual); + } + + @Test + public void numberOfSharesTest(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,10); + Integer expected = 10; + Integer actual = portfolio.getNumberOfShares("jpmorganchase"); + assertEquals(expected,actual); + } + + @Test + public void currentPortfolioValueTest(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,10); + Double expected = 2500.00; + Double actual = portfolio.getCurrentPortfolioValue(); + assertEquals(expected,actual); + } + + + @Test + public void portfolioDiversityOfShareTest(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,5); + assertEquals(0.06, portfolio.getPortfolioDiversityOfShare("jpmorganchase"), 0.00); + assertEquals(0.04, portfolio.getPortfolioDiversityOfShare("microsoft"), 0.00); + assertEquals(0.18, portfolio.getPortfolioDiversityOfShare("Apple"), 0.00); + assertEquals(0.72, portfolio.getPortfolioDiversityOfShare("cash"), 0.00); + logger.log(Level.INFO, portfolio.getPositionOfShare("Apple")); + } + + @Test + public void diversityPercentageTest(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,5); + assertEquals(18.0, portfolio.getDiversityPercentage("Apple"),0.00); + } + + @Test + public void getAllPositionsTest(){ + portfolio.addStockToBasePortfolio(StockEnum.MICROSOFT,5); + portfolio.addStockToBasePortfolio(StockEnum.APPLE,5); + portfolio.addStockToBasePortfolio(StockEnum.JPMORGANCHASE,5); + logger.log(Level.INFO, portfolio.getAllPositions()); + } + + + + + +} diff --git a/src/test/java/account/UserTest.java b/src/test/java/account/UserTest.java new file mode 100644 index 0000000..faf3395 --- /dev/null +++ b/src/test/java/account/UserTest.java @@ -0,0 +1,4 @@ +package account; + +public class UserTest { +} diff --git a/src/test/java/controller/ApiControllerTest.java b/src/test/java/controller/ApiControllerTest.java new file mode 100644 index 0000000..e3d67c4 --- /dev/null +++ b/src/test/java/controller/ApiControllerTest.java @@ -0,0 +1,25 @@ +package controller; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ApiControllerTest { + + @Test + public void testCreateApiQuery(){ + String symbol = "msft"; + String actual = ApiController.createApiQuery(symbol); + String expected = "https://alpha-vantage.p.rapidapi.com/query?datatype=json&symbol=MSFT&function=TIME_SERIES_MONTHLY"; + assertEquals(expected,actual); + } + + + // IMPORTANT! This test makes calls to the API, change the symbol to retrieve different stock tickers! + @Test + public void testFetchApiQuery(){ + String symbol = "bp"; + String resultOfCall = ApiController.fetchApiQuery(ApiController.createApiQuery(symbol)); + System.out.println(resultOfCall); + } +} diff --git a/src/test/java/sql/SqlControllerTest.java b/src/test/java/sql/SqlControllerTest.java new file mode 100644 index 0000000..c310bc6 --- /dev/null +++ b/src/test/java/sql/SqlControllerTest.java @@ -0,0 +1,20 @@ +package sql; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SqlControllerTest { + + @Test + public void connectionTest(){ + SqlController.connectSqlServer(); + } + + @Test + public void getStockTest(){ + SqlController.connectSqlServer(); + SqlController.getStock("msft", "_2020_03"); + } + +} \ No newline at end of file diff --git a/src/test/java/stocks/StockEnumTest.java b/src/test/java/stocks/StockEnumTest.java new file mode 100644 index 0000000..53cdf87 --- /dev/null +++ b/src/test/java/stocks/StockEnumTest.java @@ -0,0 +1,21 @@ +package stocks; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class StockEnumTest { + + Logger logger = Logger.getLogger(StockEnumTest.class.getName()); + + @Test + public void classTest(){ + for (StockEnum stock : StockEnum.values()) { + logger.log(Level.INFO,stock.toString() + " " + stock.getAllInfo()); + //For concise view + //System.out.println(stock.toString() + " " + stock.getAllInfo()); + } + } +} diff --git a/src/test/java/stocks/StockTest.java b/src/test/java/stocks/StockTest.java new file mode 100644 index 0000000..c4aa04c --- /dev/null +++ b/src/test/java/stocks/StockTest.java @@ -0,0 +1,4 @@ +package stocks; + +public class StockTest { +}