Tuesday, January 27, 2009

Java API - YFinance

About 3 years ago I wrote a Java package called Technical Analysis Simplifier (TAS) to do a nightly technical analysis (TA) on my securities of interest, but I didn't have a Java API for fetching the security data from financial website such as Yahoo! Finance or Google Finance. I was hoping for a freebie, but didn't find one on the Internet after a few weeks of searching. So I wrote this API and name it YFinance. Below is the source code. Many hours were spend fine tuning TAS, and very little time was spend on the YFinance. Now that the financial market is so crappy, I think it's time I put some effort back into improving YFinance and the core TAS API to ensure my theory and logic implemented into TAS still follow the key fundamental TA and that any new introduce TA concepts get integrated into TAS, which may be very helpful after we come out of this crazy recession.

Source Code: YFinance.java

The javadoc for this API is availalbe at http://www.zutirut.com/API/Finance/YFinance/



/********************************
* A class for fetching security data from public financial website/database.
*
* YFinance.java
*
* @version 0.7.5 12 October 2006
* @author Jay Suttiruttana
*
* Compiler: J2SE v1.6.0.03
* Development Platform: Linux 32 bits Kernel 2.6.22 / X86-64
*
* license: GNU LGPL
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*/

// TODO
// General List
// - add more security data field

package com.zutirut;

import java.net.URL;
import java.net.MalformedURLException;
import java.io.*;
import java.util.regex.*;
import java.text.NumberFormat;

public class YFinance {
//declare member attributes
private final String FINANCE_URL = "http://finance.yahoo.com/";
private String security = null;
private String date = null;
private String time = null;
private float change = 0.0f;
private float open = 0.0f;
private float close = 0.0f;
private float high = 0.0f;
private float low = 0.0f;
private int volume = 0;
private StringBuffer dbURL = new StringBuffer();

//constructor
public YFinance(){
//default DB URL is Yahoo!Finance for v1.0
this.dbURL.append(FINANCE_URL);
}

/************************************************
* Fetch requested security data from Yahoo! Finance and store information into YFinance private members.
* @param stockSymbol the symbol of the publicly traded company
* @return none
* @throws none
************************************************/
public void loadSecurity(String stockSymbol){
//declare local attributes
URL dbData = null;
String getData = null;
BufferedReader dataStream = null;
String regEx = ",";
String stockData[];

//connect to Y!database and extract data per specific field
try {
this.dbURL.append("d/quotes.csv?s=" + stockSymbol + "&f=sl1d1t1c1ohgv&e=.csv");
dbData = new URL(this.dbURL.toString());

Pattern p = Pattern.compile("\"");
Matcher m;

//open DB stream for reading
try {
dataStream = new BufferedReader(
new InputStreamReader(dbData.openStream()));
getData = dataStream. readLine();
stockData = getData.split(regEx);

for(int i =0; i != stockData.length; i++){
m = p.matcher(stockData[i]);
if (m.find()){
stockData[i] = removeQuote(stockData[i]);
}
switch (i){
case 0:{
this.security = stockData[i];
break;
}
case 1:{
this.close = Float.parseFloat(stockData[i]);
break;
}
case 2:{
this.date = stockData[i];
break;
}
case 3:{
this.time = stockData[i];
break;
}
case 4:{
this.change = Float.parseFloat(stockData[i]);
break;
}
case 5:{
this.open = Float.parseFloat(stockData[i]);
break;
}
case 6:{
this.high = Float.parseFloat(stockData[i]);
break;
}
case 7:{
this.low = Float.parseFloat(stockData[i]);
break;
}
case 8:{
this.volume = Integer.parseInt(stockData[i]);
break;
}
}
}
}
catch (Exception e){
System.err.println(e);
}
}
// catching exception thrown from URL()
catch (MalformedURLException e){
System.err.println(e);
}

// Set all objects to null for garbage collector
dbData = null;
getData = null;
dataStream = null;
regEx = null;
stockData = null;

Runtime.getRuntime().gc();
resetDBURL();
}

/************************************************
* Return security name
* @param none
* @return none
* @throws none
************************************************/
public String getSecurityName(){
return this.security;
}

/************************************************
* Return intra-day trade volume
* @param none
* @return none
* @throws none
************************************************/
public int getDayVolume(){
return this.volume;
}

/************************************************
* Return date traded
* @param none
* @return none
* @throws none
************************************************/
public String getTradedDate(){
return this.date;
}

/************************************************
* Return last trade hour
* @param none
* @return none
* @throws none
************************************************/
public String getLastTradedHour(){
return this.time;
}

/************************************************
* Return intra-day open trade value
* @param none
* @return none
* @throws none
************************************************/
public float getDayOpen(){
return this.open;
}

/************************************************
* Return intra-day close trade value
* @param none
* @return none
* @throws none
************************************************/
public float getDayClose(){
return this.close;
}

/************************************************
* Return intra-day high trade value
* @param none
* @return none
* @throws none
************************************************/
public float getDayHigh(){
return this.high;
}

/************************************************
* Return intra-day low trade value
* @param none
* @return none
* @throws none
************************************************/
public float getDayLow(){
return this.low;
}

/************************************************
* Return monetary difference between previous and today close
* @param none
* @return none
* @throws none
************************************************/
public float getChange(){ //change return from String to float
return this.change;
}

/************************************************
* Return percentage difference between previous and today close
* @param none
* @return none
* @throws none
************************************************/
public float getPercentChange(){

float percent = 0.0f;

// negative gained
if (this.change < 0.0f){
percent = ((-this.change)/(this.close+(-this.change))) *100;
}
// positive gained
else {
percent = ((this.change)/(this.close-this.change)) *100;
}
return Float.parseFloat(NumberFormat.getInstance().format(percent));
}

/************************************************
* Reset dbURL back to default Yahoo! Finance DB
* @param none
* @return none
* @throws none
************************************************/
public void resetDBURL(){
//reset dbURL back
int urlYahooDBDefault = 25;
int urlLength = this.dbURL.length();

this.dbURL.delete(urlYahooDBDefault, urlLength);
}

/************************************************
* Clean up quote from recent fetched security data
* @param data the recently fetched security data
* @return none
* @throws none
************************************************/
public static String removeQuote(String data){
data = data.replace('\"', '\u0000');
return data;
}
}

No comments:

Post a Comment