1. 程式人生 > >Java 股票K線邏輯 程式碼

Java 股票K線邏輯 程式碼

package com.gustoboard.bm.rtdg.service.impl;

import com.gustoboard.bm.rtdg.mapper.TradeMapper;
import com.gustoboard.bm.rtdg.model.KTrade;
import com.gustoboard.bm.rtdg.model.Market;
import com.gustoboard.bm.rtdg.util.DateUtils;
import com.gustoboard.bm.rtdg.util.JacksonUtils;
import com.gustoboard.bm.rtdg.util.RedisEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 後期優化處理 通過 jprofile 調優後發現cpu利用率偏高  整體專案線上%12 左右有峰值
 * 對於 15分鐘內k線 的只需存入10天左右的資料 如果使用者拖動到10天以後通過查詢拼接5天一檔
 * 啟動定時器執行緒來單獨執行K線方法資料  錯開其他統計定時器
 * 這裡提供程式碼邏輯
 */
@Service
public class KLineService {

    @Autowired
    private TradeMapper tradeMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    private final static Logger logger = LoggerFactory.getLogger(KLineService.class);


    //                                 1  5  15  30  60   2   4    6個   12   一天   3天    7天
    private static final int[] time = {1, 5, 15, 30, 60, 120, 240, 360, 720, 1440, 4320, 10080};

    /**
     * 30秒輪詢一次
     */
    @Scheduled(fixedRate = 30000)
    public void TradeKLine() {
        //redis 獲取股票的id 和初始時間初始價格
        String marketRedis = redisTemplate.opsForValue().get(RedisEnum.GUSTO.getDesc() + "market");
        List<Market> integers = null;
        if (null != marketRedis) {
            integers = JacksonUtils.getObjectFromJson(marketRedis, ArrayList.class, Market.class);
        } else {
            integers = tradeMapper.listMarket();
        }
        //迴圈股票
        for (int i = 0; i < integers.size(); i++) {

            Market market = integers.get(i);
            //初始最後價格
            BigDecimal priceslasts = new BigDecimal("0");
            //迴圈時間
            for (int j = 0; j < time.length; j++) {
                String memberRedis = redisTemplate.opsForValue().get(RedisEnum.GUSTO.getDesc() + market.getId() + ":k:" + time[j]);
                Date openingDate = null;
                ArrayList<ArrayList> objectFromJson = null;

                if (null != memberRedis) {
                    objectFromJson = JacksonUtils.getObjectFromJson(memberRedis, ArrayList.class, Object.class);
                    //獲取redis最後的時間搓
                    Long endDate = (Long) objectFromJson.get(objectFromJson.size() - 1).get(0);
                    openingDate = DateUtils.dateParse(endDate, null);
                    //獲取最後的價格
                    priceslasts = new BigDecimal(objectFromJson.get(objectFromJson.size() - 1).get(4).toString());
                } else {
                    //獲取債捲髮行的時間
                    openingDate = market.getOpeningDate();
                    //獲取債捲髮行價格
                    priceslasts = market.getIssuePrice().setScale(2, BigDecimal.ROUND_HALF_UP);
                }

                //獲取發行
                Date date = null;
                try {
                    date = DateUtils.dateParse(DateUtils.dateFormat(openingDate, null), null);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                //獲取當前時間至 redis 最後一個時間 的分鐘數
                long distanceTimes = DateUtils.getDistanceTimes(new Date(), date);
                String listStirng = null;
                ArrayList<ArrayList> lists = new ArrayList<ArrayList>();
                int sum = 0;

                for (int k = 0; k < distanceTimes; k++) {
                    if (k % time[j] == 0) {
                        //上次最後一個的價格
                        Date dateEnd = DateUtils.dateAddSeconds(date, (sum * time[j]) * 60);
                        //刪除掉最後一個
                        if(dateEnd.getTime()==date.getTime()&& objectFromJson!=null){
                            objectFromJson.remove(objectFromJson.size()-1);
                        }
                        Date dateStrat = DateUtils.dateAddSeconds(date, ((sum + 1) * time[j]) * 60);
                        sum = sum + 1;
                        KTrade trade = new KTrade();
                        trade.setMarketId(market.getId());
                        trade.setCreatedAtEnd(dateEnd);
                        trade.setCreatedAtStart(dateStrat);
                        KTrade kTrades = tradeMapper.listHistoryCurrency(trade);
                        ArrayList list = new ArrayList(6);
                        if (null != kTrades) {
                            //時間搓
                            list.add(dateEnd.getTime());
                            //當前時間區間的第一個價格
                            list.add(kTrades.getPriceFirst());
                            //當前時間區間最高價格
                            list.add(kTrades.getPriceMax());
                            //當前時間區間最低
                            list.add(kTrades.getPriceMin());
                            //當前時間區間最後
                            list.add(kTrades.getPriceLast());
                            //當前時間數量
                            list.add(kTrades.getVolumeSum());
                            priceslasts = kTrades.getPriceLast().setScale(2, BigDecimal.ROUND_HALF_UP);
                        } else {
                            list.add(dateEnd.getTime());
                            list.add(priceslasts);
                            list.add(priceslasts);
                            list.add(priceslasts);
                            list.add(priceslasts);
                            list.add(0);
                        }
                        lists.add(list);
                    }


                }


                if (null != objectFromJson) {
                    objectFromJson.addAll(lists);
                    listStirng = JacksonUtils.getJsonObject(objectFromJson);
                } else {
                    listStirng = JacksonUtils.getJsonObject(lists);
                }
                redisTemplate.opsForValue().set(RedisEnum.GUSTO.getDesc() + market.getId() + ":k:" + time[j], listStirng, 1500, TimeUnit.MINUTES);
                lists.clear();

            }


            //儲存 每月 的 K線openingDate 這個時間 為第一個月
            ArrayList<ArrayList> listMonth = new ArrayList<ArrayList>();
            int monthDifference = DateUtils.getMonthDifference(market.getOpeningDate(), new Date());
            for (int j = 0; j < monthDifference; j++) {
                //上次最後一個的價格
                Date monthOne = DateUtils.getMonthOne(market.getOpeningDate(), j);
                Date monthLast = DateUtils.getMonthLast(market.getOpeningDate(), j);
                KTrade trade = new KTrade();
                trade.setMarketId(market.getId());
                trade.setCreatedAtEnd(monthOne);
                trade.setCreatedAtStart(monthLast);
                KTrade kTrades = tradeMapper.listHistoryCurrency(trade);
                ArrayList list = new ArrayList(6);
                if (null != kTrades) {
                    list.add(monthLast.getTime());
                    list.add(kTrades.getPriceFirst());
                    list.add(kTrades.getPriceMax());
                    list.add(kTrades.getPriceMin());
                    list.add(kTrades.getPriceLast());
                    list.add(kTrades.getVolumeSum());
                    priceslasts = kTrades.getPriceLast().setScale(2, BigDecimal.ROUND_HALF_UP);
                } else {
                    list.add(monthLast.getTime());
                    list.add(priceslasts);
                    list.add(priceslasts);
                    list.add(priceslasts);
                    list.add(priceslasts);
                    list.add(0);
                }
                listMonth.add(list);
            }
            redisTemplate.opsForValue().set(RedisEnum.GUSTO.getDesc() + market.getId() + ":k:month", JacksonUtils.getJsonObject(listMonth), 1500, TimeUnit.MINUTES);

            /**
             *   if period == 1
             *     # 24*60 = 1440
             *     if point = @r.lindex(key(market, 1), -1441)
             *       Rails.cache.write "peatio:#{market}:ticker:open", JSON.parse(point)[4]
             *     end
             *   end
             * end
             * 獲取24小時之前的最後一筆價格
             */
            String kRedis1 = redisTemplate.opsForValue().get(RedisEnum.GUSTO.getDesc() + market.getId() + ":k:" + time[0]);
            if (null != kRedis1) {
                ArrayList<ArrayList> objectFromJson = JacksonUtils.getObjectFromJson(kRedis1, ArrayList.class, Object.class);
                int low = (objectFromJson.size() - 1441);
                if (low >= 0) {
                    ArrayList arrayList = objectFromJson.get(low);
                    String lastprices = arrayList.get(4).toString();
                    redisTemplate.opsForValue().set(RedisEnum.GUSTO.getDesc() + market.getId() + ":ticker:open", lastprices, 1500, TimeUnit.MINUTES);
                }
            }

        }


    }

}