package com.activequant.archive.basic;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import com.activequant.archive.MultiValueTimeSeriesIterator;
import com.activequant.archive.TSContainer;
import com.activequant.archive.TimeSeriesIterator;
import com.activequant.domainmodel.TimeFrame;
import com.activequant.domainmodel.TimeStamp;
import com.activequant.domainmodel.Tuple;
import com.activequant.interfaces.archive.IArchiveReader;
/**
*
* Fetches data from an AQ Master Server
*
* @author GhostRider
*
*/
public class AQMSArchiveReader implements IArchiveReader {
private TimeFrame timeFrame;
private String baseUrl;
private Logger log = Logger.getLogger(AQMSArchiveReader.class);
public AQMSArchiveReader(String baseUrl, TimeFrame timeFrame) {
this.timeFrame = timeFrame;
this.baseUrl = baseUrl;
}
@Override
public TSContainer getTimeSeries(String streamId, String key,
TimeStamp startTimeStamp) throws Exception {
return null;
}
@Override
public TSContainer getTimeSeries(String streamId, String key,
TimeStamp startTimeStamp, TimeStamp stopTimeStamp) throws Exception {
// TODO Auto-generated method stub
return null;
}
@Override
public TimeSeriesIterator getTimeSeriesStream(String streamId, String key,
TimeStamp startTimeStamp, TimeStamp stopTimeStamp) throws Exception {
return null;
}
/**
* dirty hack, just takes open, high,low,close for now. Need to think about a
* way to link AQMS and this piece together. Maybe through some additional parameter
* that tells AQMS to always include field names for every row ... or something like that.
*
*/
@Override
public MultiValueTimeSeriesIterator getMultiValueStream(String streamId,
TimeStamp startTimeStamp, TimeStamp stopTimeStamp) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
final String url = baseUrl + "?SERIESID="+streamId+"&FREQ=" + timeFrame.toString()+"&FIELD=OPEN,HIGH,LOW,CLOSE&STARTDATE="+sdf.format(startTimeStamp.getCalendar().getTime())+"&ENDDATE="+sdf.format(stopTimeStamp.getCalendar().getTime());
log.info("Using url: " + url);
// let's read from this url ...
URL u = new URL(url);
InputStream inStream = u.openStream();
final BufferedReader br = new BufferedReader(new InputStreamReader(inStream));
// skip the header.
br.readLine();
class LocalIter extends MultiValueTimeSeriesIterator{
String nextLine = null;
@Override
public boolean hasNext() {
return nextLine!=null;
}
@Override
public Tuple<TimeStamp, Map<String, Double>> next() {
if(nextLine!=null){
// let's parse the line.
String[] s = nextLine.split(",");
//
Double open = s[2]==null?Double.NaN:Double.parseDouble(s[2]);
Double high = s[3]==null?Double.NaN:Double.parseDouble(s[3]);
Double low = s[4]==null?Double.NaN:Double.parseDouble(s[4]);
Double close = s[5]==null?Double.NaN:Double.parseDouble(s[5]);
//
TimeStamp ts = new TimeStamp(Long.parseLong(s[0]));
Map<String,Double> m = new HashMap<String, Double>();
m.put("OPEN", open);
m.put("HIGH", high);
m.put("LOW", low);
m.put("CLOSE", close);
Tuple<TimeStamp, Map<String, Double>> t = new Tuple<TimeStamp, Map<String, Double>>();
t.setA(ts);
t.setB(m);
//
try {
nextLine = br.readLine();
} catch (IOException e) {
nextLine = null;
e.printStackTrace();
}
return t;
}
return null;
}
};
//
LocalIter li = new LocalIter();
// read the first line.
final String firstDataLine = br.readLine();
li.nextLine = firstDataLine;
return li;
}
@Override
public void close() throws IOException {
// TODO Auto-generated method stub
}
}