/* ===========================================================
* TradeManager : a application to trade strategies for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2011-2011, by Simon Allen and Contributors.
*
* Project Info: org.trade
*
* 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.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Oracle, Inc.
* in the United States and other countries.]
*
* (C) Copyright 2011-2011, by Simon Allen and Contributors.
*
* Original Author: Simon Allen;
* Contributor(s): -;
*
* Changes
* -------
*
*/
package org.trade.broker.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.ParseException;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.trade.core.util.TradingCalendar;
import org.trade.dictionary.valuetype.BarSize;
import org.trade.dictionary.valuetype.ChartDays;
import org.trade.persistent.dao.Candle;
import org.trade.persistent.dao.Contract;
import org.trade.strategy.data.candle.CandlePeriod;
/**
*/
public class YahooBroker extends Broker {
private final static Logger _log = LoggerFactory.getLogger(YahooBroker.class);
private Integer reqId = null;
private Contract contract = null;
private String durationStr = null;
private String barSizeSetting = null;
private String endDateTime = null;
private ClientWrapper brokerModel = null;
/**
* Constructor for YahooBroker.
*
* @param contract
* Contract
* @param endDateTime
* String
* @param durationStr
* String
* @param barSizeSetting
* String
* @param brokerModel
* ClientWrapper
*
*/
public YahooBroker(Integer reqId, Contract contract, String endDateTime, String durationStr, String barSizeSetting,
ClientWrapper brokerModel) {
this.reqId = reqId;
this.contract = contract;
this.barSizeSetting = barSizeSetting;
this.durationStr = durationStr;
this.endDateTime = endDateTime;
this.brokerModel = brokerModel;
}
/**
* Method doInBackground.
*
* @return Void
*/
public Void doInBackground() {
try {
setYahooContractDetails(contract);
this.brokerModel.contractDetails(contract.getId(), contract);
this.brokerModel.contractDetailsEnd(contract.getId());
ZonedDateTime endDate = TradingCalendar.getZonedDateTimeFromDateTimeString(this.endDateTime,
"yyyyMMdd HH:mm:ss");
ChartDays chartDays = ChartDays.newInstance();
chartDays.setDisplayName(this.durationStr);
BarSize barSize = BarSize.newInstance();
barSize.setDisplayName(this.barSizeSetting);
ZonedDateTime startDate = endDate.minusDays((Integer.parseInt(chartDays.getCode()) - 1));
startDate = TradingCalendar.getPrevTradingDay(startDate);
startDate = TradingCalendar.getDateAtTime(startDate, 0, 0, 0);
if (BarSize.DAY == Integer.parseInt(barSize.getCode())) {
this.setYahooPriceDataDay(this.reqId, this.contract.getSymbol(), startDate, endDate);
} else {
this.setYahooPriceDataIntraday(this.reqId, this.contract.getSymbol(),
Integer.parseInt(chartDays.getCode()), startDate, endDate);
}
_log.debug("YahooBroker.doInBackground finished ReqId: " + this.reqId + " Symbol: "
+ this.contract.getSymbol() + " Start Date: " + startDate + " End Date: " + endDate + " BarSize: "
+ barSize.getCode() + " ChartDays: " + chartDays.getCode());
this.brokerModel.historicalData(this.reqId, "finished- at yyyyMMdd HH:mm:ss", 0, 0, 0, 0, 0, 0, 0, false);
} catch (Exception ex) {
_log.error("Error YahooBroker Symbol: " + contract.getSymbol() + " Msg: " + ex.getMessage(), ex);
}
return null;
}
public void done() {
_log.debug("YahooBroker done for: " + contract.getSymbol());
}
/**
* Method getYahooContractDetails.
*
* @param reqId
* int
* @param symbol
* String
* @return ContractDetails
* @throws IOException
*/
private void setYahooContractDetails(Contract contract) throws IOException {
/*
* Yahoo finance http://finance.yahoo.com/d/quotes.csv?s=XOM&f=n
*/
String strUrl = "http://finance.yahoo.com/d/quotes.csv?s=" + contract.getSymbol() + "&f=n";
// _log.info("URL : " + strUrl);
URL url = new URL(strUrl);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
contract.setLongName(inputLine.replaceAll("\"", ""));
break;
}
in.close();
}
/**
* Method getYahooPriceDataIntraday.
*
* @param reqId
* int
* @param symbol
* String
* @param chartDays
* int
* @param startDate
* ZonedDateTime
* @param endDate
* ZonedDateTime
* @throws IOException
*/
private void setYahooPriceDataIntraday(int reqId, String symbol, int chartDays, ZonedDateTime startDate,
ZonedDateTime endDate) throws IOException {
/*
* Yahoo finance http://chartapi.finance.yahoo.com/instrument/1.0/IBM
* /chartdata;type=quote;range=1d/csv/
*/
long days = (TradingCalendar.getDurationInDays(startDate,
TradingCalendar.getDateTimeNowMarketTimeZone().plusDays(1)));
String strUrl = "http://chartapi.finance.yahoo.com/instrument/1.0/" + symbol + "/chartdata;type=quote;range="
+ days + "d/csv/";
_log.debug("URL : " + strUrl);
URL url = new URL(strUrl);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine;
in.readLine();
while ((inputLine = in.readLine()) != null) {
if (inputLine.indexOf(":") == -1) {
StringTokenizer scanLine = new StringTokenizer(inputLine, ",");
while (scanLine.hasMoreTokens()) {
String dateString = scanLine.nextToken();
ZonedDateTime time = TradingCalendar.getZonedDateTimeFromMilli((Long.parseLong(dateString) * 1000));
// values:Timestamp,close,high,low,open,volume
double close = Double.parseDouble(scanLine.nextToken());
double high = Double.parseDouble(scanLine.nextToken());
double low = Double.parseDouble(scanLine.nextToken());
double open = Double.parseDouble(scanLine.nextToken());
long volume = Long.parseLong(scanLine.nextToken());
// _log.info("Time : " + time + " Open: " + open + " High: "
// + high + " Low: " + low + " Close: " + close
// + " Volume: " + volume);
if ((time.isAfter(startDate) || time.equals(startDate)) && time.isBefore(endDate)) {
this.brokerModel.historicalData(reqId, dateString, open, high, low, close, ((int) volume / 100),
((int) volume / 100), (open + close) / 2, false);
}
}
}
}
in.close();
}
/**
* Method getYahooPriceDataDay.
*
* @param reqId
* int
* @param symbol
* String
* @param startDate
* ZonedDateTime
* @param endDate
* ZonedDateTime
* @throws IOException
* @throws ParseException
*/
private void setYahooPriceDataDay(int reqId, String symbol, ZonedDateTime startDate, ZonedDateTime endDate)
throws IOException, ParseException {
/*
* Yahoo finance So IBM form 1/1/2012 thru 06/30/2012
* http://ichart.finance .yahoo.com/table.csv?s=IBM&a=0&b=1&c=2012&d=5
* &e=30&f=2012&ignore=.csv"
*/
List<Candle> candles = new ArrayList<Candle>();
String strUrl = "http://ichart.finance.yahoo.com/table.csv?s=" + symbol + "&a=" + startDate.getMonthValue()
+ "&b=" + startDate.getDayOfMonth() + "&c=" + startDate.getYear() + "&d=" + endDate.getMonth() + "&e="
+ endDate.getDayOfMonth() + "&f=" + endDate.getYear() + "&ignore=.csv";
// _log.info(strUrl);
URL url = new URL(strUrl);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine;
in.readLine();
while ((inputLine = in.readLine()) != null) {
StringTokenizer st = new StringTokenizer(inputLine, ",");
ZonedDateTime candleDate = TradingCalendar.getZonedDateTimeFromDateString(st.nextToken(), "y-M-d",
TradingCalendar.MKT_TIMEZONE);
ZonedDateTime time = TradingCalendar.getDateAtTime(candleDate, startDate);
double open = Double.parseDouble(st.nextToken());
double high = Double.parseDouble(st.nextToken());
double low = Double.parseDouble(st.nextToken());
double close = Double.parseDouble(st.nextToken());
long volume = Long.parseLong(st.nextToken());
// double adjClose = Double.parseDouble( st.nextToken() );
// _log.info("Time : " + time + " Open: " + open + " High: "
// + high + " Low: " + low + " Close: " + close
// + " Volume: " + volume);
CandlePeriod period = new CandlePeriod(time, TradingCalendar.getDateAtTime(time, endDate).minusSeconds(1));
Candle candle = new Candle(null, period, open, high, low, close, (volume / 100), (open + close) / 2,
((int) volume / 100), TradingCalendar.getDateTimeNowMarketTimeZone());
candle.setLastUpdateDate(time);
candles.add(candle);
}
in.close();
Collections.reverse(candles);
for (Candle candle : candles) {
long millis = TradingCalendar.geMillisFromZonedDateTime(candle.getStartPeriod());
this.brokerModel.historicalData(reqId, String.valueOf(millis / 1000), candle.getOpen().doubleValue(),
candle.getHigh().doubleValue(), candle.getLow().doubleValue(), candle.getClose().doubleValue(),
candle.getVolume().intValue(), candle.getTradeCount(), candle.getVwap().doubleValue(), false);
}
}
}