Skip to content

Commit

Permalink
better exception handling + some unit testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Sten Laane committed Mar 23, 2019
1 parent d5a91d7 commit 44c9da6
Show file tree
Hide file tree
Showing 11 changed files with 423 additions and 141 deletions.
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>Laane.Sten</groupId>
<artifactId>StockTracker</artifactId>
<version>1.1.3</version>
<version>1.2.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Expand Down Expand Up @@ -38,6 +38,12 @@
<artifactId>jmetro</artifactId>
<version>5.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<scm>
<connection>scm:git:https://github.com/StenAL/StockTracker</connection>
Expand Down Expand Up @@ -142,6 +148,7 @@
<fileSet>
<directory>${project.build.directory}</directory>
<includes>
<include>*${project.version}*-dependencies*.jar</include>
<include>*${project.version}*.zip</include>
</includes>
</fileSet>
Expand Down
35 changes: 15 additions & 20 deletions src/main/java/stocktracker/CurrencyRateFetcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,44 +27,39 @@ private CurrencyRateFetcher(String currencyCode) {
this.xmlParser = new XMLParser();
}

public static void main(String[] args) {
writeCurrencyInfo("USD", LocalDate.of(2018, 9, 24));
public static void main(String[] args) throws IOException {
writeCurrencyInfo("USDD", LocalDate.of(2018, 9, 24));
}

static void writeCurrencyInfo(String currencyCode, LocalDate firstDate) {
static void writeCurrencyInfo(String currencyCode, LocalDate firstDate) throws IOException {
CurrencyRateFetcher fetcher = new CurrencyRateFetcher(currencyCode);

String url_str = "https://sdw-wsrest.ecb.europa.eu/service/data/EXR/D." + currencyCode +
".EUR.SP00.A?startPeriod=" + firstDate + "&detail=dataonly";
try {
fetcher.xmlParser.downloadXMLFile(new URL(url_str));
List<String> dataList = fetcher.xmlParser.parse(StockTracker.PATH);
FileManager.writeList(StockTracker.PATH + currencyCode + "_temp.txt", dataList);
System.out.println("Fetching " + currencyCode + " done");
} catch (Exception e) {
e.printStackTrace();
}
fetcher.xmlParser.downloadXMLFile(new URL(url_str));
List<String> dataList = fetcher.xmlParser.parse(StockTracker.PATH);
FileManager.writeList(StockTracker.PATH + currencyCode + "_temp.txt", dataList);
System.out.println("Fetching " + currencyCode + " done");
}

private class XMLParser
{
private void downloadXMLFile(URL url) {
try {
private void downloadXMLFile(URL url) throws IOException {
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "text/xml");

//TODO: Unit testing - assert response code 200
System.out.println("Response code: " + connection.getResponseCode());
String readStream = readStream(connection.getInputStream());
List<String> lines = Arrays.asList(readStream.split("\n"));
Path file = Paths.get(StockTracker.PATH + currencyCode + "_XML_temp.xml");
Files.write(file, lines, Charset.forName("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
try {
List<String> lines = Arrays.asList(readStream.split("\n"));
Path file = Paths.get(StockTracker.PATH + currencyCode + "_XML_temp.xml");
Files.write(file, lines, Charset.forName("UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
}

/**
Expand Down
95 changes: 45 additions & 50 deletions src/main/java/stocktracker/DataAggregator.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
package stocktracker;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class DataAggregator {
// TODO: Padding money and stock decimal places with zeroes
public static void main(String[] args) {
public static void main(String[] args) throws IOException {
test();
}

private static void test() {
private static void test() throws IOException {
ArrayList<String> testList = new ArrayList<>();
testList.add("QQ_USD");
testList.add("IVV_USD");
testList.add("QQQ_USD");
ArrayList<Number> testAmounts = new ArrayList<>();
testAmounts.add(5);
testAmounts.add(10);
calculateMoney(testList, testAmounts);
}

static void calculateMoney(List<String> ticker_currency, List<Number> stockAmounts) {
static void calculateMoney(List<String> ticker_currency, List<Number> stockAmounts) throws IOException {
aggregate(ticker_currency);
List<String> finalData = FileManager.readLines(StockTracker.PATH + "aggregated_temp.txt");
List<String> dateMoney = new ArrayList<>();
Expand All @@ -43,7 +42,7 @@ static void calculateMoney(List<String> ticker_currency, List<Number> stockAmoun
FileManager.writeList(StockTracker.PATH + "money.txt", dateMoney);
}

private static void aggregate(List<String> ticker_currency) {
private static void aggregate(List<String> ticker_currency) throws IOException {
String workingDir = StockTracker.PATH;
for (String combination: ticker_currency) {
aggregate(combination);
Expand Down Expand Up @@ -76,7 +75,7 @@ private static void aggregate(List<String> ticker_currency) {
* on dates with no values. If the first day of the whole file happens to be a market
* holiday then we use the next available day's close value instead.
*/
private static void aggregate(String ticker_currency) {
private static void aggregate(String ticker_currency) throws IOException {
String workingDir = StockTracker.PATH;
String ticker = ticker_currency.split("_")[0];
String currency = ticker_currency.split("_")[1];
Expand All @@ -86,57 +85,53 @@ private static void aggregate(String ticker_currency) {
List<String> missingDates = new ArrayList<>();
List<String> currencyRates = new ArrayList<>();
List<String> stockRates = new ArrayList<>();
try {
for (String line: FileManager.readLines(workingDir + ticker + "_temp.txt")) {
stockDates.add(line.split(" ")[0]);
stockRates.add(line.split(" ")[1]);
}
for (String line: FileManager.readLines(workingDir + ticker + "_temp.txt")) {
stockDates.add(line.split(" ")[0]);
stockRates.add(line.split(" ")[1]);
}

for (String line: FileManager.readLines(workingDir + currency + "_temp.txt")) {
currencyDates.add(line.split(" ")[0]);
currencyRates.add(line.split(" ")[1]);
}
for (String line: FileManager.readLines(workingDir + currency + "_temp.txt")) {
currencyDates.add(line.split(" ")[0]);
currencyRates.add(line.split(" ")[1]);
}

for (String stockDate: stockDates) {
aggregateDates.add(stockDate);
if (!currencyDates.contains(stockDate)) {missingDates.add(stockDate + " C");} // C for currency
}
for (String currencyDate: currencyDates) {
if (!aggregateDates.contains(currencyDate)) {
missingDates.add(currencyDate + " S"); // S for stock
aggregateDates.add(currencyDate);
}
for (String stockDate: stockDates) {
aggregateDates.add(stockDate);
if (!currencyDates.contains(stockDate)) {missingDates.add(stockDate + " C");} // C for currency
}
for (String currencyDate: currencyDates) {
if (!aggregateDates.contains(currencyDate)) {
missingDates.add(currencyDate + " S"); // S for stock
aggregateDates.add(currencyDate);
}
Collections.sort(aggregateDates);
for (String date: missingDates) {
String missing = date.split(" ")[1];
date = date.split(" ")[0];
if (missing.equals("C")) {
fillMissingDates(currencyDates, currencyRates, date);
}
else {
fillMissingDates(stockDates, stockRates, date);
}
//TODO: Add actual logging for this
System.out.println(ticker + ": missing " + missing + " on " + date);
}
Collections.sort(aggregateDates);
for (String date: missingDates) {
String missing = date.split(" ")[1];
date = date.split(" ")[0];
if (missing.equals("C")) {
fillMissingDates(currencyDates, currencyRates, date);
}

if (aggregateDates.size() != currencyRates.size() || aggregateDates.size() != stockRates.size()) {
System.out.println("Something went horrendously wrong :(");
throw new Exception();
else {
fillMissingDates(stockDates, stockRates, date);
}
//TODO: Add actual logging for this
System.out.println(ticker + ": missing " + missing + " on " + date);
}

if (aggregateDates.size() != currencyRates.size() || aggregateDates.size() != stockRates.size()) {
System.out.println("Something went horrendously wrong :(");
throw new IOException();
}

String dest = StockTracker.PATH + ticker + "_" + currency + "_temp.txt";
List<String> writeList = new ArrayList<>();
for (int i = 0; i < aggregateDates.size(); i++) {
writeList.add(aggregateDates.get(i) + " " + stockRates.get(i) + " " + currencyRates.get(i));
}
FileManager.writeList(dest, writeList);

} catch (Exception e) {
e.printStackTrace();
String dest = StockTracker.PATH + ticker + "_" + currency + "_temp.txt";
List<String> writeList = new ArrayList<>();
for (int i = 0; i < aggregateDates.size(); i++) {
writeList.add(aggregateDates.get(i) + " " + stockRates.get(i) + " " + currencyRates.get(i));
}
FileManager.writeList(dest, writeList);

}

private static void fillMissingDates(List<String> datesList, List<String> ratesList, String date) {
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/stocktracker/FileManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -60,7 +58,9 @@ public static List<String> readLines(String dest) {
try {
Files.lines(Paths.get(dest))
.forEach(lines::add);
} catch (Exception e) {
} catch (NoSuchFileException e) {
throw new InvalidPathException("", "No such file exists");
} catch (IOException e) {
e.printStackTrace();
}
return lines;
Expand Down
99 changes: 47 additions & 52 deletions src/main/java/stocktracker/StockInfoFetcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,20 @@
import org.patriques.output.timeseries.DailyAdjusted;
import org.patriques.output.timeseries.data.StockData;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;

class StockInfoFetcher {

private static final String API_KEY = "NZ04YC2MOTE5AN4P";
private static final int TIMEOUT = 3000;
//private static String generated;

public static void main(String[] args) {
test();
}

private static void test() {
//getData("AAPL", LocalDate.now().minusDays(365));
getData("AAPL", LocalDate.now().minusYears(7), 1);
getData("AAPL", LocalDate.now().minusDays(35));
}

static void getData(String ticker, LocalDate startDate, double splitCoefficient) {
Expand All @@ -35,61 +30,61 @@ static void getData(String ticker, LocalDate startDate, double splitCoefficient)
System.out.println("Fetcing " + ticker + " done");
}

static void getData(String ticker, LocalDate startDate) {
Map<String, String> data = fetchData(ticker, startDate, 1);
writeData(data, ticker);
System.out.println("Fetcing " + ticker + " done");
}

private static Map<String, String> fetchData(String ticker, LocalDate startDate, double splitCoefficient)
{
AlphaVantageConnector apiConnector = new AlphaVantageConnector(API_KEY, TIMEOUT);
TimeSeries stockTimeSeries = new TimeSeries(apiConnector);

try {
// Alpha Vantage has two data OutputSizes: COMPACT which returns the first 100
// stock data entries and FULL which returns all available stock data.
// 100 stock market days is equivalent to ~140 calendar days (actually
// a few more because of market holidays)
OutputSize size;
if (LocalDate.now().minusDays(140).isBefore(startDate) ) {
// startDate is in last 140 days
size = OutputSize.COMPACT;
}
else {
size = OutputSize.FULL;
}
HashMap<String, String> dateCloses = new HashMap<>();
DailyAdjusted response = stockTimeSeries.dailyAdjusted(ticker, size);
//Map<String, String> metaData = response.getMetaData();
//generated = metaData.get("3. Last Refreshed");
List<StockData> stockData = response.getStockData();
boolean start = true;
Collections.reverse(stockData);
for (StockData stock: stockData) {
LocalDate entryDate = stock.getDateTime().toLocalDate();
if (entryDate.isAfter(startDate.minusDays(1))) {
if (start) {
splitCoefficient /= stock.getSplitCoefficient();
start = false;
}
if (stock.getSplitCoefficient() != 1) {
splitCoefficient *= stock.getSplitCoefficient();
}
double money = Math.round(stock.getClose()*splitCoefficient*100)/100.0;
dateCloses.put("" + entryDate, "" + money);
// Alpha Vantage has two data OutputSizes: COMPACT which returns the first 100
// stock data entries and FULL which returns all available stock data.
// 100 stock market days is equivalent to ~140 calendar days (actually
// a few more because of market holidays)
OutputSize size;
if (LocalDate.now().minusDays(140).isBefore(startDate) ) {
// startDate is in last 140 days
size = OutputSize.COMPACT;
}
else {
size = OutputSize.FULL;
}
HashMap<String, String> dateCloses = new HashMap<>();
DailyAdjusted response = stockTimeSeries.dailyAdjusted(ticker, size);
//Map<String, String> metaData = response.getMetaData();
//generated = metaData.get("3. Last Refreshed");
List<StockData> stockData = response.getStockData();
boolean start = true;
Collections.reverse(stockData);
for (StockData stock: stockData) {
LocalDate entryDate = stock.getDateTime().toLocalDate();
if (entryDate.isAfter(startDate.minusDays(1))) {
if (start) {
splitCoefficient /= stock.getSplitCoefficient();
start = false;
}
}
List<String> oldConfig = FileManager.readLines(StockTracker.PATH + "save_config.txt");
List<String> newConfig = new ArrayList<>();
for (String line: oldConfig) {
if (line.startsWith(ticker) && splitCoefficient != 1) {
String[] splitLine = line.split(" ");
line = splitLine[0] + " " + splitLine[1] + " " + splitCoefficient;
if (stock.getSplitCoefficient() != 1) {
splitCoefficient *= stock.getSplitCoefficient();
}
newConfig.add(line);
double money = Math.round(stock.getClose()*splitCoefficient*100)/100.0;
dateCloses.put("" + entryDate, "" + money);
}
FileManager.writeList(StockTracker.PATH + "save_config.txt", newConfig);
return dateCloses;

} catch (AlphaVantageException e) {
System.out.println("something went wrong");
return null;
}
List<String> oldConfig = FileManager.readLines(StockTracker.PATH + "save_config.txt");
List<String> newConfig = new ArrayList<>();
for (String line: oldConfig) {
if (line.startsWith(ticker) && splitCoefficient != 1) {
String[] splitLine = line.split(" ");
line = splitLine[0] + " " + splitLine[1] + " " + splitCoefficient;
}
newConfig.add(line);
}
FileManager.writeList(StockTracker.PATH + "save_config.txt", newConfig);
return dateCloses;
}

private static void writeData(Map<String, String> data, String ticker) {
Expand Down
Loading

0 comments on commit 44c9da6

Please sign in to comment.