Untitled
unknown
plain_text
2 years ago
14 kB
2
Indexable
Never
package com.crio.warmup.stock; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Paths; import java.time.LocalDate; import java.time.Period; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.UUID; import java.util.logging.Logger; import com.crio.warmup.stock.dto.AnnualizedReturn; import com.crio.warmup.stock.dto.Candle; import com.crio.warmup.stock.dto.PortfolioTrade; import com.crio.warmup.stock.dto.TiingoCandle; import com.crio.warmup.stock.dto.TotalReturnsDto; import com.crio.warmup.stock.log.UncaughtExceptionHandler; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.apache.logging.log4j.ThreadContext; import org.springframework.web.client.RestTemplate; public class PortfolioManagerApplication { // TODO: CRIO_TASK_MODULE_JSON_PARSING // Task: // - Read the json file provided in the argument[0], The file is available in // the classpath. // - Go through all of the trades in the given file, // - Prepare the list of all symbols a portfolio has. // - if "trades.json" has trades like // [{ "symbol": "MSFT"}, { "symbol": "AAPL"}, { "symbol": "GOOGL"}] // Then you should return ["MSFT", "AAPL", "GOOGL"] // Hints: // 1. Go through two functions provided - #resolveFileFromResources() and // #getObjectMapper // Check if they are of any help to you. // 2. Return the list of all symbols in the same order as provided in json. // Note: // 1. There can be few unused imports, you will need to fix them to make the // build pass. // 2. You can use "./gradlew build" to check if your code builds successfully. public static List<String> mainReadFile(String[] args) throws IOException, URISyntaxException { // 1. Read the json file provided in the argument[0] File fileName = resolveFileFromResources(args[0]); // - Go through all of the trades in the given file, // 2. get an instance of the ObjectMapper to deserialize the json data to a java // object ObjectMapper om = getObjectMapper(); PortfolioTrade[] portfolioTrades = om.readValue(fileName, PortfolioTrade[].class); // Store symbols in ArrayList and return ArrayList List<String> symbols = new ArrayList<>(); // Iterate over the list of java objects and extract stock symbols for (PortfolioTrade portfolioTrade : portfolioTrades) { symbols.add(portfolioTrade.getSymbol()); } // Then you should return ["MSFT", "AAPL", "GOOGL"] return symbols; } private static void printJsonObject(Object object) throws IOException { Logger logger = Logger.getLogger(PortfolioManagerApplication.class.getCanonicalName()); ObjectMapper mapper = new ObjectMapper(); logger.info(mapper.writeValueAsString(object)); } private static File resolveFileFromResources(String filename) throws URISyntaxException { return Paths.get(Thread.currentThread().getContextClassLoader() .getResource(filename) .toURI()) .toFile(); } private static ObjectMapper getObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); return objectMapper; } // TODO: CRIO_TASK_MODULE_JSON_PARSING // Follow the instructions provided in the task documentation and fill up the // correct values for // the variables provided. First value is provided for your reference. // A. Put a breakpoint on the first line inside mainReadFile() which says // return Collections.emptyList(); // B. Then Debug the test #mainReadFile provided in // PortfoliomanagerApplicationTest.java // following the instructions to run the test. // Once you are able to run the test, perform following tasks and record the // output as a // String in the function below. // Use this link to see how to evaluate expressions - // https://code.visualstudio.com/docs/editor/debugging#_data-inspection // 1. evaluate the value of "args[0]" and set the value // to the variable named valueOfArgument0 (This is implemented for your // reference.) // 2. In the same window, evaluate the value of expression below and set it // to resultOfResolveFilePathArgs0 // expression ==> resolveFileFromResources(args[0]) // 3. In the same window, evaluate the value of expression below and set it // to toStringOfObjectMapper. // You might see some garbage numbers in the output. Dont worry, its expected. // expression ==> getObjectMapper().toString() // 4. Now Go to the debug window and open stack trace. Put the name of the // function you see at // second place from top to variable functionNameFromTestFileInStackTrace // 5. In the same window, you will see the line number of the function in the // stack trace window. // assign the same to lineNumberFromTestFileInStackTrace // Once you are done with above, just run the corresponding test and // make sure its working as expected. use below command to do the same. // ./gradlew test --tests PortfolioManagerApplicationTest.testDebugValues public static List<String> debugOutputs() { String valueOfArgument0 = "trades.json"; String resultOfResolveFilePathArgs0 = ""; String toStringOfObjectMapper = ""; String functionNameFromTestFileInStackTrace = ""; String lineNumberFromTestFileInStackTrace = ""; return Arrays.asList(new String[] { valueOfArgument0, resultOfResolveFilePathArgs0, toStringOfObjectMapper, functionNameFromTestFileInStackTrace, lineNumberFromTestFileInStackTrace }); } // Note: // Remember to confirm that you are getting same results for annualized returns // as in Module 3. // and deserialize the results in List<Candle> // Note: // 1. You may need to copy relevant code from #mainReadQuotes to parse the Json. // 2. Remember to get the latest quotes from Tiingo API. // TODO: CRIO_TASK_MODULE_REST_API // Find out the closing price of each stock on the end_date and return the list // of all symbols in ascending order by its close value on end date. // Note: // 1. You may have to register on Tiingo to get the api_token. // 2. Look at args parameter and the module instructions carefully. // 2. You can copy relevant code from #mainReadFile to parse the Json. // 3. Use RestTemplate#getForObject in order to call the API, // and deserialize the results in List<Candle> public static List<String> mainReadQuotes(String[] args) throws IOException, URISyntaxException, RuntimeException { String token = "6533773c48e117120384519d96e6c41851c72564"; List<PortfolioTrade> trades = readTradesFromJson(args[0]); List<TotalReturnsDto> result = new ArrayList<TotalReturnsDto>(); List<String> finalResult = new ArrayList<String>(); for (PortfolioTrade trade : trades) { String url = prepareUrl(trade, LocalDate.parse(args[1]), token); TiingoCandle[] tiingoCandle = new RestTemplate().getForObject(url, TiingoCandle[].class); List<TiingoCandle> tiingoCandleList = Arrays.asList(tiingoCandle); Collections.sort(tiingoCandleList, new StockComparator()); TiingoCandle item = tiingoCandleList.get(0); result.add(new TotalReturnsDto(trade.getSymbol(), item.getClose())); } Collections.sort(result, new StockLowComparator()); for (TotalReturnsDto item : result) { finalResult.add(item.getSymbol()); } return finalResult; } static class StockComparator implements Comparator<TiingoCandle> { @Override public int compare(TiingoCandle tiingoCandle1, TiingoCandle tiingoCandle2) { if (tiingoCandle1.getDate() == tiingoCandle2.getDate()) return 0; if (tiingoCandle1.getDate().isAfter(tiingoCandle2.getDate())) return 1; return -1; } } static class StockLowComparator implements Comparator<TotalReturnsDto> { @Override public int compare(TotalReturnsDto totalReturnsDto1, TotalReturnsDto totalReturnsDto2) { if (totalReturnsDto1.getClosingPrice() == totalReturnsDto2.getClosingPrice()) return 0; if (totalReturnsDto1.getClosingPrice() > totalReturnsDto2.getClosingPrice()) return 1; return -1; } } // TODO: // After refactor, make sure that the tests pass by using these two commands // ./gradlew test --tests PortfolioManagerApplicationTest.readTradesFromJson // ./gradlew test --tests PortfolioManagerApplicationTest.mainReadFile public static List<PortfolioTrade> readTradesFromJson(String filename) throws IOException, URISyntaxException { ObjectMapper mapper = getObjectMapper(); PortfolioTrade[] portfolioTrade = mapper.readValue(resolveFileFromResources(filename), PortfolioTrade[].class); List<PortfolioTrade> list = Arrays.asList(portfolioTrade); return list; } // TODO: // Build the Url using given parameters and use this function in your code to // cann the API. public static String prepareUrl(PortfolioTrade trade, LocalDate endDate, String token) { String symbol = trade.getSymbol(); LocalDate startDate = trade.getPurchaseDate(); String url = "https://api.tiingo.com/tiingo/daily/" + symbol + "/prices?startDate=" + startDate + "&endDate=" + endDate + "&token=" + token; return url; } // TODO: CRIO_TASK_MODULE_CALCULATIONS // Now that you have the list of PortfolioTrade and their data, calculate annualized returns // for the stocks provided in the Json. // Use the function you just wrote #calculateAnnualizedReturns. // Return the list of AnnualizedReturns sorted by annualizedReturns in descending order. // Note: // 1. You may need to copy relevant code from #mainReadQuotes to parse the Json. // 2. Remember to get the latest quotes from Tiingo API. // TODO: // Ensure all tests are passing using below command // ./gradlew test --tests ModuleThreeRefactorTest static Double getOpeningPriceOnStartDate(List<Candle> candles) { return 0.0; } public static Double getClosingPriceOnEndDate(List<Candle> candles) { return 0.0; } public static List<Candle> fetchCandles(PortfolioTrade trade, LocalDate endDate, String token) { return Collections.emptyList(); } public static List<AnnualizedReturn> mainCalculateSingleReturn(String[] args) throws IOException, URISyntaxException { String token = "6533773c48e117120384519d96e6c41851c72564"; // read the trades.json file List<PortfolioTrade> trades = readTradesFromJson(args[0]); List<TotalReturnsDto> result = new ArrayList<TotalReturnsDto>(); List<String> finalResult = new ArrayList<String>(); // call the tingo api to fetch stock quote data for the symbol in each transaction of the json file for (PortfolioTrade trade : trades) { String url = prepareUrl(trade, LocalDate.parse(args[1]), token); TiingoCandle[] tiingoCandle = new RestTemplate().getForObject(url, TiingoCandle[].class); List<TiingoCandle> tiingoCandleList = Arrays.asList(tiingoCandle); Collections.sort(tiingoCandleList, new StockComparator()); TiingoCandle item = tiingoCandleList.get(0); AnnualizedReturn annualizedReturns = calculateAnnualizedReturns(LocalDate.parse(args[1]), trade, item.getOpen(),item.getClose()); Collections.sort(annualizedReturns,new AnnualizedReturnComparator()); // result.add(new TotalReturnsDto(trade.getSymbol(), item.getClose())); } return Collections.emptyList(); } static class AnnualizedReturnComparator implements Comparator<TotalReturnsDto> { @Override public int compare(TotalReturnsDto totalReturnsDto1, TotalReturnsDto totalReturnsDto2) { if (totalReturnsDto1.getClosingPrice() == totalReturnsDto2.getClosingPrice()) return 0; if (totalReturnsDto1.getClosingPrice() > totalReturnsDto2.getClosingPrice()) return 1; return -1; } } // TODO: CRIO_TASK_MODULE_CALCULATIONS // Return the populated list of AnnualizedReturn for all stocks. // Annualized returns should be calculated in two steps: // 1. Calculate totalReturn = (sell_value - buy_value) / buy_value. // 1.1 Store the same as totalReturns // 2. Calculate extrapolated annualized returns by scaling the same in years span. // The formula is: // annualized_returns = (1 + total_returns) ^ (1 / total_num_years) - 1 // 2.1 Store the same as annualized_returns // Test the same using below specified command. The build should be successful. // ./gradlew test --tests PortfolioManagerApplicationTest.testCalculateAnnualizedReturn public static AnnualizedReturn calculateAnnualizedReturns(LocalDate endDate, PortfolioTrade trade, Double buyPrice, Double sellPrice) { Period diff = Period.between(trade.getPurchaseDate(), endDate); Double totalNumYears = (Double.valueOf(diff.getYears())) ; Double totalReturns = ( sellPrice - buyPrice ) / buyPrice; Double annualizedReturns = Math.pow(( 1 + totalReturns ), ( 1 / totalNumYears ) - 1); return new AnnualizedReturn(trade.getSymbol(), annualizedReturns, totalReturns); } public static void main(String[] args) throws Exception { Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler()); ThreadContext.put("runId", UUID.randomUUID().toString()); printJsonObject(mainReadFile(args)); printJsonObject(mainReadQuotes(args)); printJsonObject(mainCalculateSingleReturn(args)); } }