📄 cimbstockhistoryserver.java
字号:
/*
* CIMBStockHistoryServer.java
*
* Created on April 22, 2007, 1:20 AM
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) 2007 Cheok YanCheng <yccheok@yahoo.com>
*/
package org.yccheok.jstock.engine;
import java.io.*;
import java.util.*;
import java.math.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* @author yccheok
*/
public class CIMBStockHistoryServer implements StockHistoryServer {
/** Creates a new instance of CIMBStockHistoryServer */
public CIMBStockHistoryServer(Code code) throws StockHistoryNotFoundException {
this("", "", code);
}
public CIMBStockHistoryServer(String username, String password, Code code) throws StockHistoryNotFoundException {
this.username = username;
this.password = password;
this.code = Utils.toCIMBFormat(code, Country.Malaysia);
this.historyDatabase = new HashMap<SimpleDate, Stock>();
byte data[] = new byte[1024];
Thread currentThread = Thread.currentThread();
for(String server : servers) {
if(currentThread.isInterrupted()) {
throw new StockHistoryNotFoundException("Thread has been interrupted");
}
HttpMethod method = new GetMethod(server + "java/jar/data/" + code + ".dat.gz");
StringBuffer s = new StringBuffer(data.length);
final HttpClient httpClient = new HttpClient();
try {
Utils.setHttpClientProxyFromSystemProperties(httpClient);
httpClient.executeMethod(method);
InputStream inputStream = method.getResponseBodyAsStream();
java.util.zip.GZIPInputStream gZipInputStream = new java.util.zip.GZIPInputStream(inputStream);
int n = 0;
while((n = gZipInputStream.read(data, 0, data.length)) != -1) {
s.append(new String(data, 0, n));
}
gZipInputStream.close();
inputStream.close();
HistoryDatabaseResult historyDatebaseResult = this.getHistoryDatabase(s.toString());
if(historyDatebaseResult != null) {
historyDatabase.putAll(historyDatebaseResult.database);
SimpleDate latestDate = historyDatebaseResult.lastestDate;
// Should we stop here?
long days = Utils.getDifferenceInDays(latestDate.getCalendar(), Calendar.getInstance());
// As long as the history is less than or equal to MAX_DAY_DIFFERENCE_AMONG_TODAY_AND_LATEST_HISTORY,
// we will not continue to search for the history.
if(days <= MAX_DAY_DIFFERENCE_AMONG_TODAY_AND_LATEST_HISTORY) {
break;
}
}
}
catch(HttpException exp) {
log.error("code=" + code, exp);
// Continue to try other servers.
continue;
}
catch(IOException exp) {
log.error("code=" + code, exp);
// Continue to try other servers.
continue;
}
finally {
method.releaseConnection();
}
}
if(historyDatabase.size() == 0) {
throw new StockHistoryNotFoundException("code=" + code);
}
else {
simpleDates = new ArrayList<SimpleDate>(this.historyDatabase.keySet());
Collections.sort(simpleDates);
}
}
// Helper class.
private static class HistoryDatabaseResult {
public HistoryDatabaseResult(java.util.Map<SimpleDate, Stock> database, SimpleDate latestDate) {
this.database = database;
this.lastestDate = latestDate;
}
public java.util.Map<SimpleDate, Stock> database;
public SimpleDate lastestDate;
}
// Return null if not success.
private HistoryDatabaseResult getHistoryDatabase(String source) {
String[] stockDatas = source.split("\\r\\n");
// There must be at least two lines : header information and history information.
if(stockDatas.length <= 1) return null;
String[] fields = stockDatas[0].split("\\|");
// Header information as below :
// 1295|PBBANK|PUBLIC BANK BHD|Active|KLCI,Emas|Main|FINANCE|0100|3492545323|33179180569
if(fields.length < 10) return null;
final String code = fields[0];
final String symbol = fields[1];
final String name = fields[2];
final Stock.Board board = stringToBoardMap.get(fields[5]) != null ? stringToBoardMap.get(fields[5]) : Stock.Board.Unknown;
final Stock.Industry industry = stringToIndustryMap.get(fields[6]) != null ? stringToIndustryMap.get(fields[6]) : Stock.Industry.Unknown;
long _sharesIssued = 0;
long _marketCapital = 0;
try {
_sharesIssued = Long.parseLong(fields[8]);
_marketCapital = Long.parseLong(fields[9]);
}
catch(java.lang.NumberFormatException exp) {
log.debug(exp);
return null;
}
sharesIssued = _sharesIssued;
marketCapital = _marketCapital;
final java.text.SimpleDateFormat dateFormat = (java.text.SimpleDateFormat)java.text.DateFormat.getInstance();
dateFormat.applyPattern("yyMMdd");
java.util.Map<SimpleDate, Stock> map = new java.util.HashMap<SimpleDate, Stock>();
SimpleDate latestDate = null;
for(int i = 1; i < stockDatas.length; i++) {
final String stockData = stockDatas[i];
String[] stockFields = stockData.split("\\|");
java.util.Date date = null;
try {
date = dateFormat.parse(stockFields[0]);
}
catch(java.text.ParseException exp) {
log.error(stockFields[0], exp);
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
try {
final SimpleDate simpleDate = new SimpleDate(calendar);
final double openPrice = Double.parseDouble(stockFields[1]);
final double highPrice = Double.parseDouble(stockFields[2]);
final double lowPrice = Double.parseDouble(stockFields[3]);
final double lastPrice = Double.parseDouble(stockFields[4]);
/* Our system will use 100 units as 1 lot. Our system are in lot unit. */
final int volume = Integer.parseInt(stockFields[5]) / 100;
java.math.BigDecimal _openPrice = new java.math.BigDecimal("" + openPrice);
java.math.BigDecimal _lastPrice = new java.math.BigDecimal("" + lastPrice);
java.math.BigDecimal _changePrice = _lastPrice.subtract(_openPrice);
final double changePrice = _changePrice.round(new MathContext(2)).doubleValue();
BigDecimal _changePricePercentage = (_openPrice.compareTo(BigDecimal.ZERO) == 1) ? (_changePrice.multiply(new BigDecimal(100.0)).divide(_openPrice, BigDecimal.ROUND_HALF_UP)) : BigDecimal.ZERO;
final double changePricePercentage = _changePricePercentage.round(new MathContext(2)).doubleValue();
Stock stock = new Stock(
Code.newInstance(code),
Symbol.newInstance(symbol),
name,
board,
industry,
openPrice,
lastPrice,
highPrice,
lowPrice,
volume,
changePrice,
changePricePercentage,
0,
0.0,
0,
0.0,
0,
0.0,
0,
0.0,
0,
0.0,
0,
0.0,
0,
simpleDate.getCalendar()
);
map.put(simpleDate, stock);
if(latestDate == null) {
latestDate = simpleDate;
}
else {
if(simpleDate.getCalendar().after(latestDate.getCalendar())) {
latestDate = simpleDate;
}
}
}
catch(NumberFormatException exp) {
log.debug(exp);
return null;
}
}
return new HistoryDatabaseResult(map, latestDate);
}
public Stock getStock(java.util.Calendar calendar)
{
SimpleDate simpleDate = new SimpleDate(calendar);
return historyDatabase.get(simpleDate);
}
public java.util.Calendar getCalendar(int index)
{
SimpleDate simpleDate = simpleDates.get(index);
return simpleDate.getCalendar();
}
public int getNumOfCalendar()
{
return simpleDates.size();
}
private final String username;
private final String password;
private final Code code;
private final java.util.Map<SimpleDate, Stock> historyDatabase;
private final java.util.List<SimpleDate> simpleDates;
private static final int MAX_DAY_DIFFERENCE_AMONG_TODAY_AND_LATEST_HISTORY = 30;
// Not available since 15 December. Reason unknown. We switch to a much more
// robust Yahoo server.
//
private final String[] servers = new String[] {
// "http://n2ntbfd02.itradecimb.com/",
};
// Too slow, customer not happy. We will only use one server. May facing
// risk getting inaccurate data.
/*
private final String[] servers = new String[] {
"http://n2ntbfd01.itradecimb.com/",
"http://n2ntbfd02.itradecimb.com/",
"http://n2ntbfd03.itradecimb.com/",
"http://n2ntbfd04.itradecimb.com/",
"http://n2ntbfd05.itradecimb.com/",
"http://n2ntbfd06.itradecimb.com/",
"http://n2ntbfd07.itradecimb.com/",
"http://n2ntbfd08.itradecimb.com/",
"http://n2ntbfd09.itradecimb.com/",
"http://n2ntbfd10.itradecimb.com/"
};
*/
public long getSharesIssued()
{
return sharesIssued;
}
public long getMarketCapital()
{
return marketCapital;
}
private static final java.util.Map<String, Stock.Board> stringToBoardMap = new HashMap<String, Stock.Board>();
private static final java.util.Map<String, Stock.Industry> stringToIndustryMap = new HashMap<String, Stock.Industry>();
private long sharesIssued = 0;
private long marketCapital = 0;
static {
stringToBoardMap.put("Main", Stock.Board.Main);
stringToBoardMap.put("2nd", Stock.Board.Second);
// stringToBoardMap.put(??, Stock.Board.CallWarrant);
stringToBoardMap.put("MESDAQ", Stock.Board.Mesdaq);
stringToIndustryMap.put("00", Stock.Industry.Unknown);
stringToIndustryMap.put("CONSUMER", Stock.Industry.ConsumerProducts);
stringToIndustryMap.put("IND-PROD", Stock.Industry.IndustrialProducts);
stringToIndustryMap.put("CONSTRUCTN", Stock.Industry.Construction);
stringToIndustryMap.put("TRAD/SERV", Stock.Industry.TradingServices);
stringToIndustryMap.put("TECHNOLOGY", Stock.Industry.Technology);
stringToIndustryMap.put("IPC", Stock.Industry.Infrastructure);
stringToIndustryMap.put("FINANCE", Stock.Industry.Finance);
stringToIndustryMap.put("HOTELS", Stock.Industry.Hotels);
stringToIndustryMap.put("PROPERTIES", Stock.Industry.Properties);
stringToIndustryMap.put("PLANTATION", Stock.Industry.Plantation);
stringToIndustryMap.put("MINING", Stock.Industry.Mining);
stringToIndustryMap.put("REITS", Stock.Industry.Trusts);
stringToIndustryMap.put("CLOSED/FUND", Stock.Industry.CloseEndFund);
stringToIndustryMap.put("ETF", Stock.Industry.ETF);
stringToIndustryMap.put("LOANS", Stock.Industry.Loans);
stringToIndustryMap.put("CALL-WARR", Stock.Industry.CallWarrant);
}
private static final Log log = LogFactory.getLog(CIMBStockServer.class);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -