fundvaluation2/src/com/pingan/rbpfunval/Process

package com.pingan.rbpfundval2;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pingan.rbpfundval2.dao.fundDao;
import com.pingan.rbpfundval2.model.DatasourceStatus;
import com.pingan.rbpfundval2.model.FundDeviError;
import com.pingan.rbpfundval2.model.FundDividend;
import com.pingan.rbpfundval2.model.FundTop10Config;
import com.pingan.rbpfundval2.model.FundTop10Qualification;
import com.pingan.rbpfundval2.model.FundValDeviation;
import com.pingan.rbpfundval2.model.FundValError;
import com.pingan.rbpfundval2.model.FundValGlobalError;
import com.pingan.rbpfundval2.model.FundValuation;
import com.pingan.rbpfundval2.model.StockRealtime;

public class Process {

private static Logger logger = LoggerFactory.getLogger(Process.class);
private static SqlSession session;
private static fundDao fd;

private static String resource = "mybatis-config.xml";
private static String datasource = "PA";

private static String version = "";
private static String currentDate = "";
private static String preTradeday = "";

// 滿足條件的TOP10基金列表
private static List<FundTop10Qualification> fundTop10QualifiedList = null;
// 全部股混型基金前十股票配置
private static List<FundTop10Config> fundTop10ConfigList = null;
// 全部股混型基金前十股票配置, 按基金代號歸類
private static Map<String, List<FundTop10Config>> fundTop10ConfigMap = null;
//基金分紅信息
private static Map<String, FundDividend> fundDividendMap = null;

private static String loggerPrefix = "";

static {
    try {
        Properties properties = new Properties();
        //測試
         String userPath = System.getProperty("user.home");
         userPath = userPath + "/java/fundvaluation2/";
         String appFilePath = userPath + "application.properties";
        //本地
        //userPath = "D:\\work\\fundValuation2_WS\\fundValuation2\\src";
        //appFilePath = userPath + "\\application.properties";
        logger.info("user.home:" + userPath);           
        logger.info("appFilePath:" + appFilePath);
        BufferedReader bufferedReader = new BufferedReader(new FileReader(appFilePath));
        properties.load(bufferedReader);            
        version = properties.getProperty("version");
        logger.info("version:" + properties.getProperty("version"));

    } catch (IOException e) {
        logger.error(e.getMessage());
    }

}

public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub

    boolean isSupplemented = false;
    int iprocessType = 0;
    // 0-正常流程, 計算當前時間兩分鐘前估值
    // 1-補算缺失的top10實時估值數據
    // 2-全局補算top10估值數據, 和全局補算基金實時偏離度
    // 3-補算錯誤表中基金實時偏離度

    if (args.length > 0) {
        if (args[0].equals("0")) {
            iprocessType = 0;
            isSupplemented = false;
        } else if (args[0].equals("1")) {
            iprocessType = 1;
            isSupplemented = true;
        } else if (args[0].equals("2")) {
            iprocessType = 2;
            isSupplemented = true;
        } else if (args[0].equals("3")) {
            iprocessType = 3;
            isSupplemented = true;
        } 
        else if (args[0].equals("9")) { // 測試流程
            iprocessType = 9;
        }
    } else {
        logger.info("Lack of parameters! ");
        return;
    }
    loggerPrefix = "[process " + iprocessType + "] - ";

    init();

// currentDate = "20180928";
// 如果當前時間是交易日,則返回當前時間,否則返回空
String currentTradeDay = fd.getTradeDay(currentDate);

    if (currentTradeDay == null) {
        logger.info(loggerPrefix + "Current day is not trade day! ");
        releaseResource();
        return;
    }

    // 獲取當前時間的2分鐘前的時間
    long time = 2 * 60 * 1000;// 2分鐘
    Date beforeDate = new Date(new Date().getTime() - time);// 2分鐘前的時間
    String valuationTime = new SimpleDateFormat("yyyyMMddHHmm").format(beforeDate);
//valuationTime = "201810101430";
    // 獲取前一個交易日
    preTradeday = fd.getPreTradeDay(currentDate);
    logger.info(loggerPrefix + "preTradeday: " + preTradeday);
    logger.info(loggerPrefix + "valuationTime: " + valuationTime);
    logger.info(loggerPrefix + " time1: " + new Date());
    fundTop10QualifiedList = fd.getFundTop10Qualification(currentDate, preTradeday);
    logger.info(loggerPrefix + "fundTop10QualifiedList size: " + fundTop10QualifiedList.size());
    fundTop10ConfigList = fd.getFundTop10Config(currentDate);
    logger.info(loggerPrefix + "fundTop10ConfigList size: " + fundTop10ConfigList.size());

    logger.info(loggerPrefix + " time2: " + new Date());
    if (fundTop10QualifiedList == null || fundTop10QualifiedList.size() == 0 || fundTop10ConfigList == null
            || fundTop10ConfigList.size() == 0) {

        logger.info(loggerPrefix + "Fund config information is empty!");
        // 如果走正常流程基金配置表沒數據,寫入全局錯誤表
        if (iprocessType == 0) {
            fd.insertFundValGlobalError(new FundValGlobalError(currentDate, valuationTime, "01", "TOP10基金配置表無數據",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
            session.commit();
        }
        releaseResource();
        return;
    }

    fundTop10ConfigMap = new HashMap<String, List<FundTop10Config>>();
    for (FundTop10Config ftc : fundTop10ConfigList) {
        String fundId = ftc.getSymbolOf();
        if (fundTop10ConfigMap.containsKey(fundId)) {
            List<FundTop10Config> fundList = fundTop10ConfigMap.get(fundId);
            fundList.add(ftc);
        } else {
            List<FundTop10Config> fundList = new ArrayList<FundTop10Config>();
            fundList.add(ftc);
            fundTop10ConfigMap.put(fundId, fundList);
        }

    }
    logger.info(loggerPrefix + " time3: " + new Date());
    logger.info(loggerPrefix + "fundTop10ConfigMap size: " + fundTop10ConfigMap.size());

    // List<FundValuation> valuationList = new ArrayList<>();

    // 獲取當前數據源的狀態
    DatasourceStatus ds = fd.getDatasourceStatus(currentDate);
    if (ds == null)
        datasource = "PA";
    else if (ds.getJqStatus().equals("1") && ds.getPaStatus().equals("0"))
        datasource = "JQ";
    else
        datasource = "PA";
    // datasource = "JQ";
    logger.info(loggerPrefix + "當前數據源: " + datasource);

    //初始化基金分紅信息
    initFundDividendMap(currentDate);

    if (iprocessType == 0) {        
        logger.info(loggerPrefix + "start process 0...");
        boolean result = produceValuationData(valuationTime, isSupplemented, iprocessType);
        if(result){
            try{
                Thread.sleep(10000);
            }catch(InterruptedException e){
                logger.error(e.getMessage());
            }               
            produceDeviationData(valuationTime, isSupplemented, iprocessType);              
        }
        logger.info(loggerPrefix + "end process 0...");

    } else if (iprocessType == 1) {
        logger.info(loggerPrefix + "start process 1...");

        List<String> timeList = fd.getDistinctErrorTimeList(currentDate);
        if (timeList != null && timeList.size() > 0) {
            logger.info(loggerPrefix + " There are errors in fund_realtime_valuation_error table.");
            logger.info(loggerPrefix + " total timeList size: " + timeList.size());

            List<String> shortTimeList = timeList.subList(0, timeList.size()>8?8:timeList.size());
            fd.markErrorProcessing(shortTimeList);
            session.commit();
            logger.info(loggerPrefix + "markErrorProcessing "+shortTimeList);
            try {
                for (String strTime : shortTimeList) {                      
                    if (strTime.trim().length() > 12)
                        strTime = strTime.substring(0, 12);
                    logger.info(loggerPrefix + " current time: " + strTime);
                    logger.info(loggerPrefix + " processing timeList: "+shortTimeList);                     
                    boolean result = addValuationData(strTime);
                    logger.info(loggerPrefix + "addValuationData result is " + result);                 

                }

            } catch (Exception e) {                 
                logger.error(e.getMessage());
                logger.info(loggerPrefix +"error message: "+e.toString());                  
                return;
            } finally {
                logger.info(loggerPrefix + "releaseErrorProcessing " + shortTimeList);                  
                fd.releaseErrorProcessing(shortTimeList);
                session.commit();
                releaseResource();
            }

        } else {
            logger.info(loggerPrefix + " There is no new error in fund_realtime_valuation_error table.");
        }

        logger.info(loggerPrefix + "end process 1...");
    }       
    else if (iprocessType == 2) {
        logger.info(loggerPrefix + "start process 2...");
        List<FundValGlobalError> fvgeList = fd.getFundValGlobalErrorList(currentDate);
        if (fvgeList == null || fvgeList.size() == 0) {
            releaseResource();
            logger.info(loggerPrefix + "There is no error in fund_realtime_valuation_global_error_top10.");
            return;
        }
        List<String> idList = fvgeList.stream().map(f -> f.getErrorId()).collect(Collectors.toList());
        // 狀態加鎖
        fd.markGlobalErrorProcessing(idList);
        session.commit();
        logger.info(loggerPrefix + "markGlobalErrorProcessing");
        try {
            // 循環取錯誤信息
            for (FundValGlobalError fvge : fvgeList) {
                String valtime = fvge.getValuationTime().trim();                    
                boolean result = produceValuationData(valtime, isSupplemented, iprocessType);
                if (result) {                       
                    fvge.setProcessCount(fvge.getProcessCount() + 1);
                    fvge.setReprocessOk("1");
                    fd.updateGlobalError(fvge);
                    session.commit();

                    try{
                        Thread.sleep(5000);
                    }catch(InterruptedException e){
                        logger.error(e.getMessage());
                    }                       
                    produceDeviationData(valtime, isSupplemented, iprocessType);
                }
            }

        } catch (Exception e) {
            logger.error(loggerPrefix+"raise process 2 exception...");
            logger.error(e.getMessage());               
            return;
        } finally {
            // 狀態解鎖
            logger.info(loggerPrefix + "releaseGlobalErrorProcessing");
            fd.releaseGlobalErrorProcessing(idList);
            session.commit();
            releaseResource();
        }

        logger.info(loggerPrefix + "end process 2...");
    }else if (iprocessType == 3){
        logger.info(loggerPrefix + "start process 3...");   
        List<String> timeList = fd.getDistinctDeviErrorTimeList(currentDate);
        if (timeList != null && timeList.size() > 0) {
            logger.info(loggerPrefix + " There are errors in fund_realtime_valuation_devi_error_top10 table.");
            logger.info(loggerPrefix + " total timeList size: " + timeList.size());             
            List<String> shortTimeList = timeList.subList(0, timeList.size()>8?8:timeList.size());
            fd.markDeviErrorProcessing(shortTimeList);
            session.commit();
            logger.info(loggerPrefix + "markDeviErrorProcessing "+shortTimeList);
            try {
                for (String strTime : shortTimeList) {                      
                    if (strTime.trim().length() > 12)
                        strTime = strTime.substring(0, 12);
                    logger.info(loggerPrefix + " current time: " + strTime);
                    logger.info(loggerPrefix + " processing timeList: "+shortTimeList);                     
                    addDeviationData(strTime+"00");             

                }

            } catch (Exception e) {                 
                logger.error(e.getMessage());
                logger.info(loggerPrefix +"error message: "+e.toString());                  
                return;
            } finally {
                logger.info(loggerPrefix + "releaseDeviErrorProcessing " + shortTimeList);                  
                fd.releaseDeviErrorProcessing(shortTimeList);
                session.commit();
                releaseResource();
            }

        } else {
            logger.info(loggerPrefix + " There is no new error in fund_realtime_valuation_devi_error_top10 table.");
        }

        logger.info(loggerPrefix + "end process 3...");         

    }else if (iprocessType == 9){
        //valuationTime = "201810160958";
        //produceDeviationData(valuationTime, isSupplemented, iprocessType);
        String strDate = currentDate;

        logger.error(loggerPrefix + "error test");

/* for(int i=30; i <60; i++){
String strTime = strDate+"09"+i;
fd.insertFundValGlobalError(new FundValGlobalError(currentDate, strTime, "01", "TOP10基金配置表無數據",
new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
}

        for(int i=0; i <60; i++){   
            String strMin="";
            if(i<10) strMin="0"+i;
            else strMin=""+i;
            String strTime = strDate+"10"+strMin;               
            fd.insertFundValGlobalError(new FundValGlobalError(currentDate, strTime, "01", "TOP10基金配置表無數據",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
        } 

        for(int i=0; i <=30; i++){  
            String strMin="";
            if(i<10) strMin="0"+i;
            else strMin=""+i;
            String strTime = strDate+"11"+strMin;               
            fd.insertFundValGlobalError(new FundValGlobalError(currentDate, strTime, "01", "TOP10基金配置表無數據",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
        } 

        for(int i=0; i <60; i++){   
            String strMin="";
            if(i<10) strMin="0"+i;
            else strMin=""+i;
            String strTime = strDate+"13"+strMin;               
            fd.insertFundValGlobalError(new FundValGlobalError(currentDate, strTime, "01", "TOP10基金配置表無數據",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
        }

        for(int i=0; i <60; i++){   
            String strMin="";
            if(i<10) strMin="0"+i;
            else strMin=""+i;
            String strTime = strDate+"14"+strMin;               
            fd.insertFundValGlobalError(new FundValGlobalError(currentDate, strTime, "01", "TOP10基金配置表無數據",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
        }

        fd.insertFundValGlobalError(new FundValGlobalError(currentDate, strDate+"1500", "01", "TOP10基金配置表無數據",
                new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));

        session.commit();*/
    }

    releaseResource();

}

// 正常每分鐘計算基金估值的流程。交易時間段每分鐘觸發一次,取當前時間兩分鐘前的指數和股票實時數據,結合TOP10配置計算符合異動條件的基金估值並插入數據庫。
private static boolean produceValuationData(String valuationTime, boolean isSupplemented, int iprocessType) {
    logger.info(loggerPrefix + "start produceValuationData... ");
    String batchid = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
    List<FundValuation> fundValList = new ArrayList<FundValuation>();
    List<FundValError> valErrorList = new ArrayList<FundValError>();

    logger.info(loggerPrefix + "valuationTime: " + valuationTime);
    // logger.info(loggerPrefix + "batchid=" + batchid + " time1: " + new
    // Date());

    List<StockRealtime> stockRealTimes = new ArrayList<>();
    Map<String, StockRealtime> mapAllStockRealTime =  new HashMap<String, StockRealtime>();     

    if ("PA".equals(datasource)) {
        logger.info(loggerPrefix + "batchid=" + batchid + " current data source is PA");
        stockRealTimes = fd.getStockRealtimeByTime(valuationTime + "00");
    } else if ("JQ".equals(datasource)) {
        logger.info(loggerPrefix + "batchid=" + batchid + " current data source is JQ");
        stockRealTimes = fd.getStockRealtimeJQByTime(valuationTime + "00");
    }

    logger.info(loggerPrefix + "stockRealTime size : " + stockRealTimes.size());

    if (stockRealTimes == null || stockRealTimes.size() == 0) {
        if(iprocessType == 0){
            fd.insertFundValGlobalError(new FundValGlobalError(currentDate, valuationTime, "02", "全市場股票數據缺失",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
            session.commit();
            logger.info(loggerPrefix + "全市場股票數據缺失, 寫入全局錯誤表... ");
        }else if(iprocessType == 2){                
            logger.info(loggerPrefix + "batchid=" + batchid + " 全市場股票數據缺失, 更新全局錯誤表... ");
            FundValGlobalError globalError = fd.getFundValGlobalErrorByTime(valuationTime);
            if (globalError == null) {
                fd.insertFundValGlobalError(new FundValGlobalError(currentDate, valuationTime, "02",
                        "全市場股票數據缺失,無法計算基金估值", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())));
            } else {
                globalError.setProcessCount(globalError.getProcessCount() + 1);
                fd.updateGlobalError(globalError);
            }
            session.commit();               

        }                       

        logger.info(loggerPrefix + "end produceValuationData... ");
        return false;
    }

    mapAllStockRealTime = stockRealTimes.stream()
            .collect(Collectors.toMap(StockRealtime::getSymbol, Function.identity()));
    // logger.info(loggerPrefix + "batchid=" + batchid + " indexRealtimes: "
    // + indexRealtimes.size());
    logger.info(loggerPrefix + "batchid=" + batchid + " stockRealTimes: " + stockRealTimes.size());
    logger.info(loggerPrefix + "batchid=" + batchid + " mapAllStockRealTime: " + mapAllStockRealTime.size());

    // logger.info(loggerPrefix + "batchid=" + batchid + " time2: " + new
    // Date());
    int i = 0;
    for (FundTop10Qualification ftq : fundTop10QualifiedList) {
        i++;
        String symbol = ftq.getSymbolOf();
        Double muFactor = ftq.getMuFactor();
        Double nav = ftq.getNav();
        List<FundTop10Config> fundconfList = fundTop10ConfigMap.get(symbol);

        double retSum = 0;
        double ret = 0;
        // System.out.println(loggerPrefix +"
        // ----------------"+i+"-------------------");
        // System.out.println(loggerPrefix +" symbol="+ symbol);
        int j = 0;
        String lackStockIds = "";
        boolean isLack = false;
        for (FundTop10Config ftc : fundconfList) {
            j++;
            // System.out.println(loggerPrefix +"
            // ----------------"+i+"-------------------"+j);
            String stockId = ftc.getEsymbol();
            // 測試代碼
            // if(stockId.equals("000568")||stockId.equals("601336"))
            // stockId=stockId+".OA";
            // 測試代碼
            Double sholding7 = ftc.getSholding7() / 100;
            StockRealtime srt = mapAllStockRealTime.get(stockId);
            if (srt == null)
                srt = mapAllStockRealTime.get(stockId + ".SH");
            if (srt == null)
                srt = mapAllStockRealTime.get(stockId + ".SZ");

            if (srt == null) {
                System.out.println(loggerPrefix + "基金下的股票無實時數據.  symbol=" + symbol + ", stockId=" + stockId);
                isLack = true;
                if (lackStockIds.equals(""))
                    lackStockIds = stockId;
                else
                    lackStockIds = lackStockIds + "," + stockId;
                continue;
            }
            Double lastPrice = srt.getLastPrice();
            Double preClose = srt.getPreCloseprice();
            if (Double.doubleToLongBits(lastPrice) == Double.doubleToLongBits(0)) {
                lastPrice = srt.getPreCloseprice();
                // System.out.println(loggerPrefix +"基金"+symbol+"下的股票停牌:"+
                // stockId+",股票停牌前價格:"+ lastPrice);
            }
            ret = ((lastPrice - preClose) / preClose) * sholding7 * muFactor;
            retSum = retSum + ret;

/ if (symbol.equals("000011.OF")) {
logger.error(loggerPrefix + " ----------------" + j + "-------------------"+valuationTime);
logger.error(loggerPrefix + " stockId=" + stockId);
logger.error(loggerPrefix + " sholding7=" + sholding7);
logger.error(loggerPrefix + " lastPrice=" + lastPrice);
logger.error(loggerPrefix + " preClose=" + preClose);
logger.error(loggerPrefix + " muFactor=" + muFactor);
logger.error(loggerPrefix + " ret=" + ret);
logger.error(loggerPrefix + " symbol=" + symbol + ", retSum=" + retSum);
}
/
}

        if (isLack) {//if(symbol.equals("000011.OF")){logger.error(loggerPrefix +"000011.OF 股票沒有實時數據 stockId="+lackStockIds);}
            FundValError error = new FundValError();
            error.setBatchId(batchid);
            error.setCreateTime(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
            error.setDescription("股票沒有實時數據");
            error.setErrorCode("99");
            error.setFundId(symbol);
            error.setValuationDate(currentDate);
            error.setValuationTime(valuationTime + "00");
            error.setStockId(lackStockIds);
            valErrorList.add(error);
            continue;
        }

        //分紅
        double fundDividendVal = 0;
        FundDividend fundDividend = fundDividendMap.get(symbol.length()>6? symbol.substring(0, 6): symbol);
        if(fundDividend!=null){
            fundDividendVal = fundDividend.getDividendValue();
        }

//
double retValue = (retSum + 1) * (nav - fundDividendVal);

/ if(symbol.equals("000011.OF")){
logger.error("000011.OF nav = " + nav);
logger.error("000011.OF retValue = " + retValue);
logger.error("000011.OF valuationTime = " + valuationTime);
logger.error(loggerPrefix + "#####################################################################");
}
/

        FundValuation fv = new FundValuation();
        fv.setBatchId(batchid);
        fv.setCreatetime(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        fv.setFundId(symbol);
        fv.setIsSupplemented(isSupplemented ? "1" : "0");
        fv.setPreValuation(nav);
        fv.setValuation(retValue);
        fv.setValuationDate(currentDate);
        fv.setValuationTime(valuationTime + "00");
        fundValList.add(fv);

    }

    // logger.info(loggerPrefix + "batchid=" + " time3: " + new Date());

    logger.info(loggerPrefix + "batchid=" + batchid + " valuationList: " + fundValList.size());

    if (fundValList != null && fundValList.size() > 0) {
        batchInsertValuation(fundValList, 2000);
    }

    if (valErrorList != null && valErrorList.size() > 0) {
        batchInsertError(valErrorList, 2000);
    }
    // logger.info(loggerPrefix + "batchid=" + batchid + " time4: " + new
    // Date());
    logger.info(loggerPrefix + "end produceValuationData... ");
    return true;
}

//產生TOP10實時背離數據
private static void produceDeviationData(String valuationTime, boolean isSupplemented, int iprocessType){
    logger.info(loggerPrefix + "start produceDeviationData... ");
    List<FundValDeviation> deviList = null;
    List<FundValDeviation> validDeviList = new ArrayList<FundValDeviation>();
    List<FundDeviError> errorList = new ArrayList<FundDeviError>();

    //logger.info(loggerPrefix + "before getDeviationList... ");
    deviList  = fd.getDeviationList(valuationTime+"00", valuationTime.substring(0,8), preTradeday, version);
    //logger.info(loggerPrefix + "after getDeviationList... ");

    for(FundValDeviation fvd: deviList){

        String fundId = fvd.getFundId();
        Double value1 = fvd.getValuation1();
        Double value2 = fvd.getValuation2();            
        String valTime = fvd.getValuationTime();
        fvd.setValuationDate(valTime.substring(0,8));
        fvd.setIsSupplemented(isSupplemented ? "1" : "0");
        //Double deviPercent = fvd.getDeviPercent();

        if(value1==null 
                || value2==null 
                || Double.doubleToLongBits(value1)==Double.doubleToLongBits(0)
                || Double.doubleToLongBits(value2)==Double.doubleToLongBits(0))
        {
            //logger.info(loggerPrefix + " lackage of value1 or value2...");
            FundDeviError deviError = new FundDeviError();
            deviError.setFundId(fundId);
            deviError.setValuationDate(valTime.substring(0,8));
            deviError.setValuationTime(valTime);                
            errorList.add(deviError);               
        }else
            validDeviList.add(fvd);
    }

    logger.info(loggerPrefix + " valuationTime = " + valuationTime+"00");
    logger.info(loggerPrefix + " total deviation size = " + deviList.size());       
    logger.info(loggerPrefix + " valid deviation data size= " + validDeviList.size());
    logger.info(loggerPrefix + " missing deviation data size= " + errorList.size());    

    if(validDeviList!=null && validDeviList.size()>0){                      
        fd.insertFundDeviMinTop10(validDeviList);
        session.commit();
    }

    if(errorList!=null && errorList.size()>0){

        fd.insertFundDeviErrorTop10(errorList);
        session.commit();
    }

    logger.info(loggerPrefix + "end produceDeviationData... ");

}

// 補發數據流程2。 對於由於股票實時數據缺失而沒有計算出基金估值的數據,進行重算補發。
private static boolean addValuationData(String valTime) {
    String batchid = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
    logger.info(loggerPrefix + "batchid=" + batchid + " start addValuationData... " + new Date());
    List<FundValuation> valuationList = new ArrayList<FundValuation>();
    List<String> successList = new ArrayList<String>();
    List<FundValError> valErrorList = new ArrayList<>();

    // logger.info(loggerPrefix + "batchid=" + batchid + " time1: " + new Date());

    List<StockRealtime> stockRealTimes = null;
    List<FundValError> fundValErrors = null;
    Map<String, StockRealtime> mapAllStockRealTime = new HashMap<String, StockRealtime>();

    // logger.info(loggerPrefix + "batchid=" + batchid +" time2: " + new
    // Date());
    fundValErrors = fd.getFundValErrorListByMin(valTime + "00");
    if (fundValErrors == null || fundValErrors.size() == 0) {
        logger.info(loggerPrefix + "batchid=" + batchid + " Error list is empty!");
        return false;
    }

    // logger.info(loggerPrefix + "batchid=" + batchid + " time3: " + new
    // Date());
    logger.info("fundValErrors: " + fundValErrors.size());

    if ("PA".equals(datasource)) {
        stockRealTimes = fd.getStockRealtimeByTime(valTime + "00");
    } else if ("JQ".equals(datasource)) {
        stockRealTimes = fd.getStockRealtimeJQByTime(valTime + "00");
    }
    // logger.info(loggerPrefix + "batchid=" + batchid + " time5: " + new
    // Date());
    logger.info(loggerPrefix + "batchid=" + batchid + " stockRealTimes size: " + stockRealTimes.size());

    if ( (stockRealTimes == null || stockRealTimes.size() == 0)) {
        logger.info(loggerPrefix + "batchid=" + batchid + " stockRealTimes is empty!");
        return false;
    }

    mapAllStockRealTime = stockRealTimes.stream()
            .collect(Collectors.toMap(StockRealtime::getSymbol, Function.identity()));

    Map<String, FundTop10Qualification> mapAllTop10Qualification = fundTop10QualifiedList.stream()
            .collect(Collectors.toMap(FundTop10Qualification::getSymbolOf, Function.identity()));

    // logger.info(loggerPrefix + "batchid=" + batchid + " time6: " + new
    // Date());

    //double nav = 0.0;

    for (FundValError fve : fundValErrors) {
        String fundid = fve.getFundId();
        FundTop10Qualification ftq = mapAllTop10Qualification.get(fundid);
        Double muFactor = ftq.getMuFactor();
        Double nav = ftq.getNav();          

        List<FundTop10Config> fundconfList = fundTop10ConfigMap.get(fundid);

        double retSum = 0;
        double ret = 0;
        // System.out.println(loggerPrefix +"
        // ----------------"+i+"-------------------");
        // System.out.println(loggerPrefix +" symbol="+ symbol);
        int j = 0;
        String lackStockIds = "";
        boolean isLack = false;
        for (FundTop10Config ftc : fundconfList) {
            j++;
            // System.out.println(loggerPrefix +"
            // ----------------"+i+"-------------------"+j);
            String stockId = ftc.getEsymbol();
            // 測試代碼
            // if(stockId.equals("000568")||stockId.equals("601336"))
            // stockId=stockId+".OA";
            // 測試代碼
            Double sholding7 = ftc.getSholding7() / 100;
            StockRealtime srt = mapAllStockRealTime.get(stockId);
            if (srt == null)
                srt = mapAllStockRealTime.get(stockId + ".SH");
            if (srt == null)
                srt = mapAllStockRealTime.get(stockId + ".SZ");

            if (srt == null) {
                System.out.println(loggerPrefix + "基金下的股票無實時數據.  symbol=" + fundid + ", stockId=" + stockId);
                isLack = true;
                if (lackStockIds.equals(""))
                    lackStockIds = stockId;
                else
                    lackStockIds = lackStockIds + "," + stockId;
                continue;
            }
            Double lastPrice = srt.getLastPrice();
            Double preClose = srt.getPreCloseprice();
            if (Double.doubleToLongBits(lastPrice) == Double.doubleToLongBits(0)) {
                lastPrice = srt.getPreCloseprice();
                // System.out.println(loggerPrefix +"基金"+symbol+"下的股票停牌:"+
                // stockId+",股票停牌前價格:"+ lastPrice);
            }
            ret = ((lastPrice - preClose) / preClose) * sholding7 * muFactor;
            retSum = retSum + ret;              
        }

        if (isLack) {
            FundValError error = new FundValError();                
            error.setErrorId(fve.getErrorId());         
            error.setBatchId(batchid);
            error.setCreateTime(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
            error.setDescription("股票沒有實時數據");
            error.setErrorCode("99");
            error.setFundId(fundid);
            error.setValuationDate(fve.getValuationDate());
            error.setValuationTime(fve.getValuationTime());
            error.setStockId(lackStockIds);
            valErrorList.add(error);
            continue;
        }

        //分紅
        double fundDividendVal = 0;
        FundDividend fundDividend = fundDividendMap.get(fundid.length()>6? fundid.substring(0, 6): fundid);
        if(fundDividend!=null){
            fundDividendVal = fundDividend.getDividendValue();
        }

        double retValue = (retSum + 1) * (nav - fundDividendVal);

        FundValuation fv = new FundValuation();
        fv.setBatchId(batchid);
        fv.setCreatetime(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        fv.setFundId(fundid);
        fv.setIsSupplemented("0");
        fv.setPreValuation(nav);
        fv.setValuation(retValue);
        fv.setValuationDate(fve.getValuationDate());
        fv.setValuationTime(fve.getValuationTime());

        valuationList.add(fv);          
        successList.add(fve.getErrorId());
    }

    // logger.info(loggerPrefix + "batchid=" + batchid + " time7: " + new
    // Date());
    logger.info(loggerPrefix + "batchid=" + batchid + " valuationList size: " + valuationList.size());
    logger.info(loggerPrefix + "batchid=" + batchid + " successList size: " + successList.size());
    logger.info(loggerPrefix + "batchid=" + batchid + " valErrorList size: " + valErrorList.size());

    List<String> errorIdList = valErrorList.stream().map(e -> e.getErrorId()).collect(Collectors.toList());
    if (valuationList != null && valuationList.size() > 0) {
        batchInsertValuation(valuationList, 2000);
        batchDeleteError(successList, 2000);
    }

    if (valErrorList != null && valErrorList.size() > 0) {
        batchUpdateError(errorIdList, 2000);
    }

    // logger.info(loggerPrefix + "batchid=" + batchid + " time8: " + new
    // Date());
    logger.info(loggerPrefix + "batchid=" + batchid + " end addValuationData... " + new Date());
    return true;
}

//補算TOP10實時背離數據
private static void addDeviationData(String valuationTime){
    logger.info(loggerPrefix + "start addDeviationData... ");
    List<FundValDeviation> deviList = null;
    List<FundValDeviation> validDeviList = new ArrayList<FundValDeviation>();
    List<FundDeviError> errorList = new ArrayList<FundDeviError>();
    List<String> successList = new ArrayList<String>();

    logger.info(loggerPrefix + "before getDeviationListFromError...  valuationTime:" + valuationTime);      
    deviList = fd.getDeviationListFromError(valuationTime, valuationTime.substring(0,8) , preTradeday,  version );
    logger.info(loggerPrefix + "after getDeviationListFromError... ");

    for(FundValDeviation fvd: deviList){

        String fundId = fvd.getFundId();
        Double value1 = fvd.getValuation1();
        Double value2 = fvd.getValuation2();            
        String valTime = fvd.getValuationTime();
        fvd.setValuationDate(valTime.substring(0,8));
        fvd.setIsSupplemented("1");
        //Double deviPercent = fvd.getDeviPercent();

        if(value1==null 
                || value2==null 
                || Double.doubleToLongBits(value1)==Double.doubleToLongBits(0)
                || Double.doubleToLongBits(value2)==Double.doubleToLongBits(0))
        {
            //logger.info(loggerPrefix + " lackage of value1 or value2...");
            FundDeviError deviError = new FundDeviError();
            deviError.setErrorId(fvd.getErrorId());
            deviError.setFundId(fundId);
            deviError.setValuationDate(valTime.substring(0,8));
            deviError.setValuationTime(valTime);                
            errorList.add(deviError);               
        }else{
            validDeviList.add(fvd);
            successList.add(fvd.getErrorId());          
        }

    }

    logger.info(loggerPrefix + " valuationTime = " + valuationTime);
    logger.info(loggerPrefix + " total deviation size = " + deviList.size());       
    logger.info(loggerPrefix + " valid deviation data size= " + validDeviList.size());
    logger.info(loggerPrefix + " missing deviation data size= " + errorList.size());    

    List<String> errorIdList = errorList.stream().map(e -> e.getErrorId()).collect(Collectors.toList());
    if(validDeviList!=null && validDeviList.size()>0){                      
        fd.insertFundDeviMinTop10(validDeviList);
        session.commit();
        fd.deleteDeviErrorList(successList);
        session.commit();
    }

    if(errorList!=null && errorList.size()>0){              
        fd.updateDeviErrorList(errorIdList);
        session.commit();
    }

    logger.info(loggerPrefix + "end addDeviationData... ");

}

private static void batchInsertValuation(List<FundValuation> valuationList, int batchCount) {
    int count = valuationList.size() / batchCount;
    int mode = valuationList.size() % batchCount;
    int i = 0;
    for (; i < count; i++) {
        fd.insertFundValuation(valuationList.subList(i * batchCount, (i + 1) * batchCount));
        session.commit();
    }
    if (mode > 0) {
        fd.insertFundValuation(valuationList.subList(i * batchCount, valuationList.size()));
        session.commit();
    }

}

private static void batchInsertError(List<FundValError> valErrorList, int batchCount) {
    int count = valErrorList.size() / batchCount;
    int mode = valErrorList.size() % batchCount;
    int i = 0;
    for (; i < count; i++) {
        fd.insertFundValError(valErrorList.subList(i * batchCount, (i + 1) * batchCount));
        session.commit();
    }
    if (mode > 0) {
        fd.insertFundValError(valErrorList.subList(i * batchCount, valErrorList.size()));
        session.commit();
    }
}

private static void batchDeleteError(List<String> successList, int batchCount) {
    int count = successList.size() / batchCount;
    int mode = successList.size() % batchCount;
    int i = 0;
    for (; i < count; i++) {
        fd.deleteErrorList(successList.subList(i * batchCount, (i + 1) * batchCount));
        session.commit();
    }
    if (mode > 0) {
        fd.deleteErrorList(successList.subList(i * batchCount, successList.size()));
        session.commit();
    }
}

private static void batchUpdateError(List<String> errorIdList, int batchCount) {
    int count = errorIdList.size() / batchCount;
    int mode = errorIdList.size() % batchCount;
    int i = 0;
    for (; i < count; i++) {
        fd.updateErrorList(errorIdList.subList(i * batchCount, (i + 1) * batchCount));
        session.commit();
    }
    if (mode > 0) {
        fd.updateErrorList(errorIdList.subList(i * batchCount, errorIdList.size()));
        session.commit();
    }
}

private static void init() throws IOException {
    Reader reader = Resources.getResourceAsReader(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    session = sqlSessionFactory.openSession();
    fd = (fundDao) session.getMapper(fundDao.class);
    currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());

}

private static void releaseResource() {
    session.close();
}

private static void initFundDividendMap(String valuationTime){

    List<FundDividend> fundDividendList = fd.getFundDividendList(valuationTime);        
    if(fundDividendList != null && fundDividendList.size() > 0){            
        fundDividendMap = fundDividendList.stream()
                .collect(Collectors.toMap(FundDividend::getFundId, Function.identity()));                   
    }else
        fundDividendMap = new HashMap<String, FundDividend>();

}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章