Tuesday, November 9, 2010

HW6 Solution

Below is my solution to HW6:
public class FileTooBigException extends Exception {
 public FileTooBigException(String msg) {
  super(msg);
 }
}

public class NotEnoughDataException extends Exception { 
 public NotEnoughDataException(String msg) {
  super(msg);
 }
}

import java.util.Scanner;
public class Day {
 private String date;
 private double open;
 private double high;
 private double low;
 private double close;
 private long volume;
 
 public double getClose() {
  return close;
 }
 
 public double getVolume() {
  return volume;
 }
 
 /**
  * Creates a new Day object by reading values from istream:
  *   date, open, high, log, close, volume: in that order.
  * We assume the delimiter has been correctly set on istream so values can be read
  *   by calling nextX()
  * @param istream
  */
 public Day (Scanner istream) {
  date = istream.next();
  open = istream.nextDouble();
  high = istream.nextDouble();
  low = istream.nextDouble();
  close = istream.nextDouble();
  volume = istream.nextLong();
 }

 public String toString() {
  return date + " " + close + " " + volume;
 }
}


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;

public class Security {

 private Day[] day;

 private int lastDay;

 private static final int DAY_ARRAY_SIZE = 1000;

 /**
  * Add day d to the history, but only if its volume > 0.
  * @param d
  * @throws FileTooBigException 
  */
 public void addDay(Day d) throws FileTooBigException {
  if (d.getVolume() > 0) {
   if (lastDay >= DAY_ARRAY_SIZE) {
    throw new FileTooBigException("You cannot have more than " + DAY_ARRAY_SIZE + " days.");
   }
   day[lastDay++] = d;
  }
 }

 public Security () {
  day = new Day[DAY_ARRAY_SIZE];
  lastDay = 0;
 }

 /** Read historical values for this security from a csv stream.
  * 
  * @param file
  * @throws FileTooBigException 
  */
 public void readFromStream(Scanner istream) throws FileTooBigException {
  istream.useDelimiter("[,\\s]"); //separate on , or on whitespace
  if (istream.hasNext()) {
   istream.nextLine(); //ignore first line
  }
  String w = null;
  while (istream.hasNext()) {
   //System.out.println("----" + istream.next());
   Day nextDay = new Day(istream);
   addDay(nextDay);
  }
 }

 public double getVolatility(int numDays) throws NotEnoughDataException {
  if (numDays > lastDay) {
   throw new NotEnoughDataException("Need more historical data");
  }
  double average = getAverageClose(numDays);
  double squareDifference = 0;
  for (int i=0; i < numDays; i++) {
   squareDifference += Math.pow(day[i].getClose() - average, 2);
  }
  double deviation = squareDifference / (double) numDays;
  return Math.sqrt(deviation);
 }

 public double getAverageClose(int numDays) {
  double sum = 0;
  for (int i=0; i< numDays;i++) {
   sum += day[i].getClose();
  }
  return sum / (double)numDays;
 }

 public String toString() {
  String result = "";
  for (int i= 0; i < lastDay; i++) {
   result += day[i] + "\n";
  }
  return result;
 }

 public double getMinClose(int numDays) {
  double min = Double.MAX_VALUE; //assume no stock price is ever this high
  for (int i = 0; i < numDays; i++) {
   if (day[i].getClose() < min)
    min = day[i].getClose();
  }
  return min;
 }

 public double getMaxClose(int numDays) {
  double max = -1;
  for (int i = 0; i < numDays; i++) {
   if (day[i].getClose() > max)
    max = day[i].getClose();
  }
  return max;
 }
 /**
  * Returns a price distribution array, where the index of the array is the price - getMinClose(numDays)
  * whose contents are the number of days we closed at that price within the last numDays.
  * @param numDays
  * @return array with getMaxClose(numDays) - getMinClose(numDays) + 1 values 
  */

 public int[] getPriceDistribution(int numDays) {
  int min = (int) getMinClose(numDays);
  int max = (int) getMaxClose(numDays);
  int[] result = new int[max-min + 1];
  for (int i =0; i < numDays; i++) {
   result[(int)day[i].getClose() - min]++;
  }
  return result;
 }

 public void savePriceDistribution(String outFile,int numDays) throws FileNotFoundException {
  PrintWriter out = new PrintWriter(new FileOutputStream(outFile, true));
  int min = (int) getMinClose(numDays);
  int[] distribution = getPriceDistribution(numDays);
  for (int i =0; i < distribution.length; i++) {
   int p = min + i;
   out.write(p + "," + distribution[i] + "\n");
  }
  out.close();
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  Scanner istream = null;
  String inputFile = "/Users/jmvidal/data.csv";
  try {
   istream = new Scanner(new File(inputFile));
  } catch (FileNotFoundException e) {
   System.out.println("Ooops, no such input file:" + inputFile);
   System.exit(1);
  }

  Security s = new Security(); //Security class will hold all the data
  try {
   s.readFromStream(istream); //read the contents from istream
  } catch (FileTooBigException e1) { //file is to big to read
   System.out.println(e1.getMessage());
   System.exit(1);
  }

  System.out.println(s); //print out all the contents. Note: no days with 0 volume.

  try {
   System.out.println("Volatility in the last 10 days = " + s.getVolatility(10));
   System.out.println("Volatility in the last 1000 days = " + s.getVolatility(1000));

  } catch (NotEnoughDataException e) {
   System.out.println("Sorry, not enough data." + e.getMessage());
  }

  System.out.println("Price Distribution for the last 10 days.");
  System.out.println("price\tnumber of days");
  int[] priceDistribution = s.getPriceDistribution(10); //get the distribution array
  int minClose = (int)s.getMinClose(10);
  for (int i=0; i < priceDistribution.length; i++) { //we need this loop to print it out
   int p = minClose + i;
   System.out.println(p + "\t" + priceDistribution[i]);
  }

  try {
   //now, save the distribtion for the last 20 days to a file.
   s.savePriceDistribution("/Users/jmvidal/distribution-20.csv",20); 
  } catch (FileNotFoundException e) {
   System.out.println("Ooops, bad output file name.");
   System.exit(1);
  }
 }
}

No comments: