Untitled

mail@pastecode.io avatar
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));
  }

}