All Downloads are FREE. Search and download functionalities are using the official Maven repository.

quant.fans.provider.DailyDataProvider Maven / Gradle / Ivy

The newest version!
package quant.fans.provider;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import quant.fans.common.Constants;

import quant.fans.common.StockConstants;
import quant.fans.common.Utils;
import quant.fans.downloader.Downloader;
import quant.fans.model.StockData;
import quant.fans.model.Symbol;

import java.util.*;

import static quant.fans.common.StockConstants.*;
/**
 * author: eryk
 * mail: [email protected]
 * date: 15-8-4.
 * 注意:复权只对开盘价,收盘价,最高价,最低价复权
 * 昨日收盘价,
 */
public class DailyDataProvider {
    private static final Logger LOG = LoggerFactory.getLogger(DailyDataProvider.class);

    public static final String DAILY_DATA_URL = "http://quotes.money.163.com/service/chddata.html?code=%s&start=%s&end=%s&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP";

    public static final String DAILY_PRICE_HFQ_URl = "http://vip.stock.finance.sina.com.cn/api/json.php/BasicStockSrv.getStockFuQuanData?symbol=%s&type=hfq";

    public static final String DAILY_HFQ_URL = "http://vip.stock.finance.sina.com.cn/corp/go.php/vMS_FuQuanMarketHistory/stockid/%s.phtml"; //?year=%s&jidu=%s

    /**
     * 参数1:6位代码
     * year:年份
     * jidu:季度,1,2,3,4
     */
    public static final String DAILY_HFQ_PARAM_URL = "http://vip.stock.finance.sina.com.cn/corp/go.php/vMS_FuQuanMarketHistory/stockid/%s.phtml?year=%s&jidu=%s";

    /**
     * 获取前复权数据
     */
    private static Map qfqData(String symbol, String startDate, String stopDate) {
        Map stockDataMap = Maps.newHashMap();

        String hfqURL = String.format(DAILY_HFQ_URL, symbol);
        String data = Downloader.download(hfqURL, "gb2312");
        try {
            Elements select = Jsoup.parse(data).getElementById("con02-4").getElementsByTag("select").get(0).getElementsByTag("option");
            List pages = Lists.newArrayListWithCapacity(50);
            for (Element option : select) {
                pages.add(option.text() + "" + "1231");
                pages.add(option.text() + "" + "0930");
                pages.add(option.text() + "" + "0630");
                pages.add(option.text() + "" + "0331");
            }
            Collections.reverse(pages);


            for (String page : pages) {
                Date date = Utils.str2Date(page, "yyyyMMdd");
                //TODO date < stop
                if (date.getTime() > Utils.str2Date(startDate, "yyyyMMdd").getTime() /*&& date.getTime() < Utils.str2Date(stopDate,"yyyyMMdd").getTime()*/) {
                    String url = String.format(DAILY_HFQ_PARAM_URL, symbol, Utils.formatDate(date, "yyyy"), getQuarter(date));
                    data = Downloader.download(url, "gb2312");
                    Elements tr = Jsoup.parse(data).getElementById("FundHoldSharesTable").getElementsByTag("tbody").get(0).getElementsByTag("tr");
                    for (int i = 1; i < tr.size(); i++) {
                        Elements td = tr.get(i).getElementsByTag("td");
                        Date stockDate = Utils.str2Date(td.get(0).text(), "yyyy-MM-dd");
                        if (stockDate.getTime() >= Utils.str2Date(startDate, "yyyyMMdd").getTime() && stockDate.getTime() <= Utils.str2Date(stopDate, "yyyyMMdd").getTime()) {
                            StockData stockData = new StockData(symbol);

                            stockData.date = Utils.str2Date(td.get(0).text(), "yyyy-MM-dd");
                            stockData.put(OPEN, Double.parseDouble(td.get(1).text()));
                            stockData.put(HIGH, Double.parseDouble(td.get(2).text()));
                            stockData.put(StockConstants.CLOSE, Double.parseDouble(td.get(3).text()));
                            stockData.put(StockConstants.LOW, Double.parseDouble(td.get(4).text()));
                            stockData.put(StockConstants.VOLUME, Double.parseDouble(td.get(5).text()) / 100);  //单位:手
                            stockData.put(StockConstants.AMOUNT, Double.parseDouble(td.get(6).text()) / 10000);//单位:万
                            stockData.put(StockConstants.FACTOR, Double.parseDouble(td.get(7).text()));
                            stockDataMap.put(td.get(0).text().replaceAll("-", ""), stockData);
                        }
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("fail to get from url " + hfqURL);
        }

        return stockDataMap;
    }

    /**
     * 根据时间获取季度
     * @param date date
     * @return quarter
     */
    public static int getQuarter(Date date) {
        return (date.getMonth() / 3) + 1;
    }

    private static List getDailyDataWithURL(String symbol,String url){
        List stocks = Lists.newLinkedList();
        try {
            String data = Downloader.download(url, "gb2312");
            String[] lines = data.split("\n");

            for (int i = 1; i < lines.length; i++) {    //第一行是标题,跳过
                String[] line = lines[i].split(",");
                //股票数据15列,指数数据13列,少最后两列
                if ((line.length == 15 || line.length == 13) && !lines[i].contains("None")) {
                    try {
                        StockData stock = new StockData(line[1].replace("'", ""));

                        stock.date = Utils.str2Date(line[0], Constants.NETEASE_DATE_STYLE);
                        stock.name = line[2];
                        for (int j = 0; j < StockConstants.DAILY.size() - 1; j++) {
                            if(line.length>j+3){
                                stock.put(StockConstants.DAILY.get(j), Utils.str2Double(line[j + 3]));
                            }
                        }
                        stock.put("amplitude", Utils.formatDouble((stock.get("high") - stock.get("low")) / stock.get("lastClose")));
                        changeUnit(stock);
                        stocks.add(stock);
                    } catch (Exception e) {
                        LOG.warn(String.format("stock %s convert error %s", symbol,lines[i]),e);
                    }
                }
            }

        } catch (Exception e) {
            LOG.error(String.format("stock %s collect error", symbol), e);
        }
        //按照时间从最早到最新
        return Lists.reverse(stocks);
    }

    private static List getDailyDataWithOutFQ(String symbol, String startDate, String stopDate) {
        String url = getPath(symbol, startDate, stopDate);
        return getDailyDataWithURL(symbol,url);
    }

    /**
     * 获取指数日线数据
     * 上证综指:0000001
     * 深证成指:1399001
     * 深证综指:1399106
     * 沪深300:0000300
     * 创业板指:1399006
     * 创业板综:1399102
     * 中小板指:1399005
     * 中小板综:1399101
     * @param symbol stock symbol
     * @param startDate yyyyMMdd
     * @param stopDate yyyyMMdd
     * @return data list
     */
    public static List getZS(String symbol,String startDate,String stopDate){
        String url;
        if(symbol.startsWith("3")){
            url = getPath(symbol,startDate,stopDate);
        }else{
            url = String.format(DAILY_DATA_URL,"0"+symbol,startDate,stopDate);
        }
        return getDailyDataWithURL(symbol,url);
    }

    /**
     * 获取未复权数据
     * @param symbol stock symbol
     * @param startDate yyyyMMdd
     * @param stopDate yyyyMMdd
     * @return data list
     */
    public static List get(String symbol,String startDate,String stopDate){
        return getDailyDataWithOutFQ(symbol, startDate, stopDate);
    }

    //http://d.10jqka.com.cn/v2/line/hs_600133/01/2015.js
    public static String FQ_URL = "http://d.10jqka.com.cn/v2/line/hs_%s/01/%s.js";
    /**
     * 获取前复权数据
     * @param symbol stock symbol
     * @param startDate yyyyMMdd
     * @param stopDate yyyyMMdd
     * @return fq data list
     */
    public static List getFQ(String symbol, String startDate, String stopDate){
        List stockDataList = Lists.newLinkedList();
        List years = Utils.getYearBetween(startDate,stopDate);
        for(String year:years){
            String url = String.format(FQ_URL, symbol, year);
            String data = Downloader.download(url);
            if(Strings.isNullOrEmpty(data)){
               continue;
            }
            String[] records = data.substring(47, data.length() - 3).split(";");
            for(int i =0;i0){
                            stockData.put(LAST_CLOSE,stockDataList.get(i-1).get(CLOSE));
                            stockData.put(CHANGE_AMOUNT,stockData.get(CLOSE) - stockDataList.get(i-1).get(CLOSE));
                            stockData.put(AMPLITUDE, Utils.formatDouble((stockData.get(HIGH) - stockData.get(LOW)) / stockData.get(LAST_CLOSE))*100);
                            stockData.put(CHANGE, Utils.formatDouble((stockData.get(CHANGE_AMOUNT)) / stockData.get(LAST_CLOSE))*100);
                        }
                    }catch(Exception e){
                        //TODO CHECK
                    }
                    stockDataList.add(stockData);
                }else{
                    LOG.error(Joiner.on(",").join(record));
                }
            }
        }
        return stockDataList;
    }

    private static void changeUnit(StockData stockData) {
        stockData.put(VOLUME, stockData.get(VOLUME) / 100);    //成交量,单位:手
        stockData.put(AMOUNT, stockData.get(AMOUNT) / 10000);  //成交金额,单位:万
        //指数数据没有下面两项
        if(stockData.get(TOTAL_VALUE)!=null){
            stockData.put(TOTAL_VALUE, stockData.get(TOTAL_VALUE) / 100000000);    //总市值,单位:亿
        }
        if(stockData.get(MARKET_VALUE)!=null){
            stockData.put(MARKET_VALUE, stockData.get(MARKET_VALUE) / 100000000);   //流通市值,单位:亿
        }
    }

    /**
     * @param symbol stock symbol
     * @param startDate yyyyMMdd
     * @param stopDate  yyyyMMdd
     * @return url path with start and stop date
     */
    public static String getPath(String symbol, String startDate, String stopDate) {
        return String.format(DAILY_DATA_URL, Symbol.getSymbol(symbol, DAILY_DATA_URL), startDate, stopDate);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy