package com.rhc.stock;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Red Hat Consulting
*
* Public class Stock holds information on a given stock listing, as well as the most recent quote
* for the given stock. The Stock class also holds a map with a history of days,
* which include day's highs, lows, etc. Stock is the central reference object for the day-trader example.
*
*/
public class Stock{
private String name;
private String ticker;
private StockQuote quote;
private Map<Date, StockDay> history = new HashMap<Date, StockDay>();
public Map<Date, StockDay> getHistory() {
return history;
}
public void setHistory(Map<Date, StockDay> history) {
this.history = history;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public StockQuote getQuote() {
return quote;
}
public void setQuote(StockQuote quote) {
this.quote = quote;
}
/**
* Populates the history with trading information from the
* past 30 calendar days from Yahoo Finance.
* Creates a URL to access Yahoo Finance and get information in .csv format.
* Parses .csv file and loads information into an instance of StockDay for each line.
* Each day is then loaded into history.
*
* @throws IOException
* @throws ParseException
* @throws MalformedURLException
*/
public void populateHistory() throws IOException, ParseException, MalformedURLException {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// Set up a connection to the Yahoo Finance CSV url
URL url = new URL(getHistoryUrl());
URLConnection urlConn = url.openConnection();
InputStreamReader inStream = new InputStreamReader(urlConn.getInputStream());
BufferedReader buff = new BufferedReader(inStream);
// Spreadsheet Header (1st row) is ommitted
buff.readLine();
// Prepare each line of spreadsheet data and assign values to POJOs
String data;
String [] line;
while((data = buff.readLine()) != null){
line = data.split(",");
date = sdf.parse(line[0]);
StockDay stockDay = new StockDay();
stockDay.setDay(date);
stockDay.setDayOpen((float) Double.parseDouble(line[1]));
stockDay.setDayHigh((float) Double.parseDouble(line[2]));
stockDay.setDayLow((float) Double.parseDouble(line[3]));
stockDay.setDayClose((float) Double.parseDouble(line[4]));
this.getHistory().put(date, stockDay);
}
inStream.close();
this.updateQuote();
}
/**
* Updates the quote with information from the most recent day in history.
*
*/
public void updateQuote() {
StockQuote quote = new StockQuote();
quote.setStock(this);
List<Date> dates = new ArrayList<Date>();
dates.addAll(getHistory().keySet());
Collections.sort(dates);
Collections.reverse(dates);
StockDay stockDay = new StockDay();
stockDay = getHistory().get(dates.get(0));
quote.setPrice(stockDay.getDayClose());
setQuote(quote);
}
/**
* Creates the URL to access Yahoo Finance historical information from last 30 calendar days.
* Uses the current date to get the day for a month earlier.
* Creates a URL of format needed to access Yahoo Finance.
*
* @return URL to access Yahoo Finance data for last 30 days.
*/
private String getHistoryUrl(){
String url = new String();
StringBuffer sb = new StringBuffer();
//Yahoo Finance requires the month field in the URL to be the current month - 1 (ex: October would be 9 instead of 10)
Integer startMonth = Calendar.getInstance().get(Calendar.MONTH) - 1;
Integer startDay = Calendar.getInstance().get(Calendar.DATE);
Integer startYear = Calendar.getInstance().get(Calendar.YEAR);
Integer endMonth = Calendar.getInstance().get(Calendar.MONTH);
Integer endDay = Calendar.getInstance().get(Calendar.DATE);
Integer endYear = Calendar.getInstance().get(Calendar.YEAR);
sb.append("http://ichart.yahoo.com/table.csv?s=");
sb.append(getTicker());
sb.append("&a=");
sb.append( startMonth );
sb.append("&b=");
sb.append(startDay);
sb.append("&c=");
sb.append(startYear);
sb.append("&d=");
sb.append( endMonth );
sb.append("&e=");
sb.append(endDay);
sb.append("&f=");
sb.append(endYear);
url = sb.toString();
return url;
}
/**
* Populates Bollinger bands of a specific day
* Based on availability of history, Bollinger Band information is calculated.
* The middle band is the average of the close price of days used for data.
* The upper band is the middle band + (2 * standard deviation of middle band).
* The lower band is the middle band - (2 * standard deviation of middle band).
*
*/
// public void populateBollingerBands(StockDay day) {
// //If there is not enough history, the band for that day will not be created
// //If there is enough history, the band will be created using all historical information available
// if(!history.isEmpty() && history.size() > BOLLINGER_LENGTH) {
// float middleBand = new Float(0);
// float upperBand = new Float(0);
// float lowerBand = new Float(0);
//
// // Determine the middle Bollinger Band
// for (Date date : getHistory().keySet()){
// middleBand += history.get(date).getDayClose() ;
//
// }
// middleBand /= history.size();
// day.setMiddleBand(middleBand);
//
// float sd = standardDeviation(middleBand);
//
// // Determine the bands based on the standard deviation
// upperBand = middleBand + 2*sd;
// lowerBand = middleBand - 2*sd;
// day.setUpperBand(upperBand);
// day.setLowerBand(lowerBand);
//
// System.out.println(day.getDay().toString() + "--MB--" + middleBand + "--SD--" + sd + "--LB--" + lowerBand + "--UB--" + upperBand);
// }
// }
//
/**
* Finds the standard deviation of the history given the average
*/
// private float standardDeviation(float average) {
// // Determine the std deviation for the Upper & Lower Bands
// float sd = new Float(0.0);
// for (Date date : getHistory().keySet()){
// sd = (float) (sd + Math.pow(history.get(date).getDayClose() - average, 2));
// }
//
// sd = (float) Math.sqrt(sd/(history.size()-1));
// return sd;
// }
}