首先,k線圖裏包含了蠟燭圖、折線圖、柱狀圖,上面圖例。而後,折線圖和蠟燭圖畫在了一個plot裏面。柱狀圖單獨一個plot。java
先說說蠟燭圖。JFreeCharts裏專門提供了一個叫OHLCSeries(open、high、low、close)的類來存放蠟燭圖數據。構造方法直接指定時間,而後指定OHLC數據就完成了數據構建。數據完成了,而後開始讓圖變得美觀。經過CandlestickRenderer(蠟燭圖畫圖器)來設置股票漲時的顏色(紅)和跌時的顏色(青),畫圖器有專門的方法提供setUp(Down)Paint。而後還能分別指定你的series顏色,setSeriesPaint(int index, Paint paint),這裏若是設置了up(down)paint,這個設置就只會改變外框的顏色(要的就是這個效果)。而後就完成了國內股票市場展現的通用顏色。es6
均線也是一個道理,設置方法基本差很少。在這裏,均線和k線放在一塊兒。要實現這個效果其實很簡單。在咱們new plot對象時,先不要給對象設置數據和畫圖器,由於蠟燭圖和均線圖使用的series不是同一個(均線使用的是TimeSeries),因此new plot對象時若是設置了數據,則plot會默認數據格式爲OHLCSeries(猜的),而後在設置進TimeSeries的數據時就會出現數據轉換異常。解決的方法就是先不設置,而後初始化好對象後,調用plot.setDateset(int index, SeriesCollection series),而後調用plot.setRenderer來指定畫圖器便可。這樣,兩個數據線就疊加到了一個plot裏。dom
柱狀圖數據省略掉了噢。數聽說完,而後說說軸線問題,先說x軸(時間軸)。首先,x軸會自動生成,可是不少時候自動生成的每每不符合咱們的需求,因此先.setAutoTickUnitSelection(false);//設置不採用自動選擇刻度值。關閉自動設置,而後關閉自動設置範圍,setAutoRange(false)。關閉完成後,須要設置的地方其實很少,先設置時間範圍setRange(startDate, endDate)、而後設置時間格式setDateFormatOverrride、設置時間刻度間隔setTickUnit(new DateTickUnit(DateTickUnit.DAY, 1)、而後還能夠設置時間顯示規則,例如去掉周6、週日這種節假日SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();.setTimeline(timeline);若是還想排除一些特殊日子,能夠用timeline.addException(date)。這樣,x軸的設置就完成了。而後是y軸,y軸這裏沒有什麼特殊要求,直接先取消自動設置範圍setAutoRange(false),而後設置一個數據範圍就好了,setRange(low, high)。ide
最後將兩個Plot結合到一個畫板裏。使用CombinedDomainXYPlot這個類來操做便可,調用add(Plot plot, int weight)//添加圖形區域對象,後面的數字是計算這個區域對象應該佔據多大的區域2/3。這個類沒多少要設置的,這裏我就不一一講解了。最後生成Chart,經過ChartUtilities.saveChartAsJPEG存放到指定路徑就ok了。字體
public String stockKChart(Map<String, String> params) { String data = null; //獲取數據 if("index".equalsIgnoreCase(params.get("type"))){//指數 data = dataService.getIndexKData(params); } else if("stock".equalsIgnoreCase(params.get("type"))){//股票 data = dataService.getaStockKData(params); } params.put("data", data); logger.info("stockKChart : params : " + params); logger.info("stockKChart : data : " + data); String path = null; //繪畫圖片 if(StringUtils.isBlank(params.get("isAverage"))&&StringUtils.isBlank(params.get("isTradVol"))) { path = kChartPlant(params); } else if(StringUtils.isBlank(params.get("isAverage")) && StringUtils.isNotBlank(params.get("isTradVol"))){ path = kBarChartPlant(params); } else if(StringUtils.isNotBlank(params.get("isAverage")) && StringUtils.isNotBlank(params.get("isTradVol"))){ path = kBarLineChartPlant(params); } //返回圖片存放路徑 return path; }
數據模型:ui
/** * 獲取指數據日K線數據 */ public String getIndexKData(Map<String,String> params){ String secucode = (String)params.get("secucode"); String startDate = (String)params.get("startDate"); String endDate = (String)params.get("endDate"); String isAverage = (String)params.get("isAverage");//判斷是否須要均線 String isTradVol = (String)params.get("isTradVol");//判斷是否須要日交易量 String type = (String)params.get("type"); if(secucode.indexOf(".") > 0 ) secucode = secucode.substring(0 , secucode.indexOf(".")); //若是代碼中包括:.sh、.sz時,取出正式的代碼 List<Map> dataList = jydbDataServiceImpl.getAIndexOrStockKData(secucode,false, startDate, endDate, type); if("1".equalsIgnoreCase(isAverage)){ jydbDataServiceImpl.initAverage(secucode ,false ,type); } Map map = new HashMap(); List quoteList = new ArrayList();//封裝日行情數據 List tradVol = new ArrayList();//封裝日交易量數據 List average5 = new ArrayList();//五日均線數據 List average20 = new ArrayList();//十日均線數據 String secuabbr = null; // System.out.println("dataList is :"+dataList); for(Map data : dataList){ if(secuabbr == null) { secuabbr = (String)data.get("secuabbr"); if(secuabbr.startsWith("申萬")){ secuabbr = secuabbr.substring(2); } } List dayQuote = new ArrayList();//日K線數據 List dayTradVol = new ArrayList();//日成交量數據 Date tradingDay = (Date)data.get("tradingday"); Double openPrice = (Double)data.get("openprice"); Double highprice = (Double)data.get("highprice"); Double lowprice = (Double)data.get("lowprice"); Double closeprice = (Double)data.get("closeprice"); Double turnovervolume = (Double)data.get("turnovervolume"); dayQuote.add(DateFormatUtils.getDate12(tradingDay)); dayQuote.add(openPrice); dayQuote.add(closeprice); dayQuote.add(highprice); dayQuote.add(lowprice); quoteList.add(dayQuote); //添加成交量數據 if("1".equalsIgnoreCase(isTradVol)){ dayTradVol.add(DateFormatUtils.getDate12(tradingDay)); dayTradVol.add(turnovervolume); tradVol.add(dayTradVol); } //添加均線數據 if("1".equalsIgnoreCase(isAverage)){ if(jydbDataServiceImpl.indexFiveAverage.get(secucode+"_"+DateFormatUtils.getDate12(tradingDay)) != null){ List average5day = new ArrayList(); average5day.add(DateFormatUtils.getDate12(tradingDay)); average5day.add(jydbDataServiceImpl.indexFiveAverage.get(secucode+"_"+DateFormatUtils.getDate12(tradingDay))); average5.add(average5day); } if(jydbDataServiceImpl.indexTwentyAverage.get(secucode+"_"+DateFormatUtils.getDate12(tradingDay)) != null){ List average20day = new ArrayList(); average20day.add(DateFormatUtils.getDate12(tradingDay)); average20day.add(jydbDataServiceImpl.indexTwentyAverage.get(secucode+"_"+DateFormatUtils.getDate12(tradingDay))); average20.add(average20day); } } } Map average = new HashMap(); if(average5.size() > 0){ average.put("MA5",average5); } if(average20.size() > 0){ average.put("MA20",average20); } if(average.size() > 0){ map.put("average", average); } map.put("quoteList", quoteList); if(tradVol.size() > 0){ map.put("tradVol", tradVol); } if(secuabbr != null){ map.put("title", secuabbr+"("+secucode+")"); }else{ map.put("title", secucode); } return JsonUtil.toJson(map); } /** * K線圖繪畫工廠 * 單k線 * @param params * @return 圖片存放路徑 */ private String kChartPlant(Map<String, String> params) { String path = null; try{ //獲取繪圖數據 String data = params.get("data"); Map<String, Object> datas = (Map<String, Object>) JsonUtil.parse(data); //獲取標題 String title = (String) datas.get("title"); OHLCSeriesCollection seriesCollection = new OHLCSeriesCollection();//定義k線圖數據集 OHLCSeries series1 = new OHLCSeries("k_up");//高開低收數據序列,股票K線圖的四個數據,依次是開,高,低,收 OHLCSeries series2 = new OHLCSeries("k_down");//定義上漲和下跌的兩個數據集 //K線圖數據 List<List<Object>> quoteList = (List<List<Object>>) datas.get("quoteList"); double mLow = 0d; double mHigh = 0d; //統計這段數據包含多少個交易日,好計算設置時間軸刻度規則 int days = 0; String startDate = null; String endDate = null; int i = 0; //獲取全部工做日 List<Date> workDate = new ArrayList<Date>(); //添加k線圖數據,添加成交量數據 for(List<Object> list : quoteList){ Date quoteListDate = DateFormatUtils.getDateTimeForAll12((String) list.get(0)); double open = Double.valueOf(list.get(1).toString()); double close = Double.valueOf(list.get(2).toString()); double high = Double.valueOf(list.get(3).toString()); double low = Double.valueOf(list.get(4).toString()); Calendar quoteCalendar = Calendar.getInstance(); quoteCalendar.setTimeInMillis(quoteListDate.getTime()); workDate.add(quoteListDate); //取這段交易日內最高和最低價格 if(mHigh < high){ mHigh = high; } if(mLow > low){ mLow = low; } else if(mLow == 0){ mLow = low; } if(i == 0){//拿到起始時間 startDate = (String) list.get(0); } if(i == quoteList.size() - 1){ endDate = (String) list.get(0); } if(open > close){ series2.add(new Day(quoteCalendar.get(quoteCalendar.DAY_OF_MONTH), quoteCalendar.get(quoteCalendar.MONTH) + 1, quoteCalendar.get(quoteCalendar.YEAR)), open, high, low, close); } else { series1.add(new Day(quoteCalendar.get(quoteCalendar.DAY_OF_MONTH), quoteCalendar.get(quoteCalendar.MONTH) + 1, quoteCalendar.get(quoteCalendar.YEAR)), open, high, low, close); } i++; days++; } //將數據添加進數據集合 seriesCollection.addSeries(series1); seriesCollection.addSeries(series2); if(StringUtils.isBlank(params.get("startDate"))){ params.put("startDate", startDate); } if(StringUtils.isBlank(params.get("startDate"))){ params.put("endDate", endDate); } //獲取全部節假日 List<Date> allHolidys = getAllHolidays(workDate); //建立主題樣式 StandardChartTheme standardChartTheme = new StandardChartTheme("CN"); //設置標題字體 standardChartTheme.setExtraLargeFont(new Font("微軟雅黑",Font.BOLD,20)); //設置圖例的字體 standardChartTheme.setRegularFont(new Font("微軟雅黑",Font.PLAIN,15)); //應用主題樣式 ChartFactory.setChartTheme(standardChartTheme); //生成k線圖畫板 JFreeChart chart = ChartFactory.createCandlestickChart(title, null, null, seriesCollection, true); CandlestickRenderer candlestickRender = new CandlestickRenderer();//設置K線圖的畫圖器 candlestickRender.setUpPaint(Color.BLACK);//設置股票上漲的K線圖顏色 candlestickRender.setDownPaint(Color.CYAN);//設置股票下跌的K線圖顏色 candlestickRender.setSeriesPaint(1, Color.CYAN);//設置股票下跌的K線圖顏色 candlestickRender.setSeriesPaint(0, Color.RED);//設置股票上漲的K線圖顏色 candlestickRender.setAutoWidthMethod(CandlestickRenderer.WIDTHMETHOD_AVERAGE);//設置如何對K線圖的寬度進行設定 candlestickRender.setAutoWidthGap(0.001);//設置各個K線圖之間的間隔 candlestickRender.setSeriesVisibleInLegend(false);//設置不顯示legend(數據顏色提示) //設置k線圖x軸,也就是時間軸 DateAxis domainAxis = new DateAxis(); domainAxis.setAutoRange(false);//設置不採用自動設置時間範圍 //設置時間範圍,注意,最大和最小時間設置時須要+ - 。不然時間刻度沒法顯示 Date da = DateFormatUtils.getDateTimeForAll12(endDate); da.setTime(da.getTime() + 1); Date sda = DateFormatUtils.getDateTimeForAll12(startDate); sda.setTime(sda.getTime() - 1); domainAxis.setRange(sda, da); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); domainAxis.setAutoTickUnitSelection(false);//設置不採用自動選擇刻度值 domainAxis.setTickMarkPosition(DateTickMarkPosition.START);//設置標記的位置 domainAxis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12)); domainAxis.setStandardTickUnits(DateAxis.createStandardDateTickUnits());// 設置標準的時間刻度單位 domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, days / Const.TIME_SCALE));// 設置時間刻度的間隔 domainAxis.setDateFormatOverride(df);//設置時間格式 SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();//設置時間線顯示的規則,用這個方法摒除掉週六和週日這些沒有交易的日期 //排除全部節假日 for(Date holiday : allHolidys){ timeline.addException(holiday); } domainAxis.setTimeline(timeline); //設置Y軸 NumberAxis y1Axis = new NumberAxis(); y1Axis.setAutoRange(false);//設置不採用自動設置時間範圍 y1Axis.setUpperMargin(0.5D);//設置向上邊框距離 y1Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12)); y1Axis.setRange(mLow - (mLow * Const.UP_OR_DOWN_RANGE), mHigh + (mHigh * Const.UP_OR_DOWN_RANGE));//設置y軸數據範圍 XYPlot plot = (XYPlot) chart.getPlot();//生成畫圖細節 plot.setRenderer(candlestickRender);//設置畫圖器 plot.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色 plot.setDomainGridlinesVisible(false);//不顯示網格 plot.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色 plot.setDomainAxis(domainAxis);//設置x軸 plot.setRangeAxis(y1Axis);//設置y軸 Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); int day = calendar.get(Calendar.DAY_OF_MONTH); int month = calendar.get(Calendar.MONTH) + 1; int year = calendar.get(Calendar.YEAR); String file_path = PropertiesRead.getinstance().getValue("FILE_PATH"); path = year + "-" + month + "-" + day + "/" + Uuid.getUUID() + "k.png"; file_path = file_path + path; saveChartAsJPEG(chart, file_path); } catch (Exception e) { logger.warn("kChartPlant:------------Exception--------------"); logger.warn(e); e.printStackTrace(); } return path; } /** * 組合圖繪畫工廠 * K線圖 + 柱狀圖 * @param params * @return 圖片存放路徑 */ private String kBarChartPlant(Map<String, String> params) { String path = null; try{ //獲取繪圖數據 String data = params.get("data"); Map<String, Object> datas = (Map<String, Object>) JsonUtil.parse(data); //獲取標題 String title = (String) datas.get("title"); OHLCSeriesCollection seriesCollection = new OHLCSeriesCollection();//定義k線圖數據集 OHLCSeries series1 = new OHLCSeries("k_up");//高開低收數據序列,股票K線圖的四個數據,依次是開,高,低,收 OHLCSeries series2 = new OHLCSeries("k_down");//定義上漲和下跌的兩個數據集 TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();//保留成交量數據的集合 TimeSeries series3 = new TimeSeries("bar_up");//對應時間成交量數據 TimeSeries series4 = new TimeSeries("bar_down");//對應時間成交量數據 //K線圖數據 List<List<Object>> quoteList = (List<List<Object>>) datas.get("quoteList"); //成交量數據 List<List<Object>> tradVol = (List<List<Object>>) datas.get("tradVol"); double mLow = 0d; double mHigh = 0d; //統計這段數據包含多少個交易日,好計算設置時間軸刻度規則 int days = 0; String startDate = null; String endDate = null; //獲取全部工做日 List<Date> workDate = new ArrayList<Date>(); //添加k線圖數據,添加成交量數據 for(int i = 0; i < quoteList.size(); i++){ Date quoteListDate = DateFormatUtils.getDateTimeForAll12((String) quoteList.get(i).get(0)); double open = Double.valueOf(quoteList.get(i).get(1).toString()); double close = Double.valueOf(quoteList.get(i).get(2).toString()); double high = Double.valueOf(quoteList.get(i).get(3).toString()); double low = Double.valueOf(quoteList.get(i).get(4).toString()); Calendar quoteCalendar = Calendar.getInstance(); quoteCalendar.setTimeInMillis(quoteListDate.getTime()); Date tradVolDate = DateFormatUtils.getDateTimeForAll12((String) tradVol.get(i).get(0)); double vol = Double.valueOf(tradVol.get(i).get(1).toString()); Calendar volCalendar = Calendar.getInstance(); volCalendar.setTimeInMillis(tradVolDate.getTime()); workDate.add(quoteListDate); //取這段交易日內最高和最低價格 if(mHigh < high){ mHigh = high; } if(mLow > low){ mLow = low; } else if(mLow == 0){ mLow = low; } if(i == 0){//拿到起始時間 startDate = (String) quoteList.get(i).get(0); } if(i == quoteList.size() - 1){ endDate = (String) quoteList.get(i).get(0); } if(open > close){ series2.add(new Day(quoteCalendar.get(quoteCalendar.DAY_OF_MONTH), quoteCalendar.get(quoteCalendar.MONTH) + 1, quoteCalendar.get(quoteCalendar.YEAR)), open, high, low, close); series4.add(new Day(volCalendar.get(volCalendar.DAY_OF_MONTH), volCalendar.get(volCalendar.MONTH) + 1, volCalendar.get(volCalendar.YEAR)), vol); } else { series1.add(new Day(quoteCalendar.get(quoteCalendar.DAY_OF_MONTH), quoteCalendar.get(quoteCalendar.MONTH) + 1, quoteCalendar.get(quoteCalendar.YEAR)), open, high, low, close); series3.add(new Day(volCalendar.get(volCalendar.DAY_OF_MONTH), volCalendar.get(volCalendar.MONTH) + 1, volCalendar.get(volCalendar.YEAR)), vol); } days++; } //將數據添加進數據集合 seriesCollection.addSeries(series1); seriesCollection.addSeries(series2); timeSeriesCollection.addSeries(series3); timeSeriesCollection.addSeries(series4); if(StringUtils.isBlank(params.get("startDate"))){ params.put("startDate", startDate); } if(StringUtils.isBlank(params.get("startDate"))){ params.put("endDate", endDate); } //獲取全部節假日 List<Date> allHolidys = getAllHolidays(workDate); //設置k線圖參數 CandlestickRenderer candlestickRender = new CandlestickRenderer();//設置K線圖的畫圖器 candlestickRender.setUpPaint(Color.BLACK);//設置股票上漲的K線圖顏色 candlestickRender.setDownPaint(Color.CYAN);//設置股票下跌的K線圖顏色 candlestickRender.setSeriesPaint(1, Color.CYAN);//設置股票下跌的K線圖顏色 candlestickRender.setSeriesPaint(0, Color.RED);//設置股票上漲的K線圖顏色 candlestickRender.setAutoWidthMethod(CandlestickRenderer.WIDTHMETHOD_AVERAGE);//設置如何對K線圖的寬度進行設定 candlestickRender.setAutoWidthGap(0.001);//設置各個K線圖之間的間隔 candlestickRender.setSeriesVisibleInLegend(false);//設置不顯示legend(數據顏色提示) NumberAxis y1Axis=new NumberAxis();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置 y1Axis.setAutoRange(false);//設置不採用自動設置時間範圍 y1Axis.setUpperMargin(0.5D);//設置向上邊框距離 y1Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12)); y1Axis.setRange(mLow - (mLow * Const.UP_OR_DOWN_RANGE), mHigh + (mHigh * Const.UP_OR_DOWN_RANGE));//設置y軸數據範圍 //設置k線圖x軸,也就是時間軸 DateAxis domainAxis = new DateAxis(); domainAxis.setAutoRange(false);//設置不採用自動設置時間範圍 //設置時間範圍,注意,最大和最小時間設置時須要+ - 。不然時間刻度沒法顯示 Date da = DateFormatUtils.getDateTimeForAll12(endDate); da.setTime(da.getTime() + 1); Date sda = DateFormatUtils.getDateTimeForAll12(startDate); sda.setTime(sda.getTime() - 1); domainAxis.setRange(sda, da); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); domainAxis.setAutoTickUnitSelection(false);//設置不採用自動選擇刻度值 domainAxis.setTickMarkPosition(DateTickMarkPosition.START);//設置標記的位置 domainAxis.setStandardTickUnits(DateAxis.createStandardDateTickUnits());// 設置標準的時間刻度單位 domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, days / Const.TIME_SCALE));// 設置時間刻度的 domainAxis.setDateFormatOverride(df);//設置時間格式 SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();//設置時間線顯示的規則,用這個方法摒除掉週六和週日這些沒有交易的日期 //排除全部節假日 for(Date holiday : allHolidys){ timeline.addException(holiday); } domainAxis.setTimeline(timeline); XYPlot plot = new XYPlot(seriesCollection,domainAxis,y1Axis,candlestickRender);//生成畫圖細節 plot.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色 plot.setDomainGridlinesVisible(false);//不顯示網格 plot.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色 //設置柱狀圖參數 XYBarRenderer barRenderer = new XYBarRenderer(); barRenderer.setDrawBarOutline(true);//設置顯示邊框線 barRenderer.setBarPainter(new StandardXYBarPainter());//取消漸變效果 barRenderer.setMargin(0.3);//設置柱形圖之間的間隔 barRenderer.setSeriesPaint(0, Color.BLACK);//設置柱子內部顏色 barRenderer.setSeriesPaint(1, Color.CYAN);//設置柱子內部顏色 barRenderer.setSeriesOutlinePaint(0, Color.RED);//設置柱子邊框顏色 barRenderer.setSeriesOutlinePaint(1, Color.CYAN);//設置柱子邊框顏色 barRenderer.setSeriesVisibleInLegend(false);//設置不顯示legend(數據顏色提示) barRenderer.setShadowVisible(false);//設置沒有陰影 //設置柱狀圖y軸參數 NumberAxis y2Axis=new NumberAxis();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置 y2Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12));//設置y軸字體 y2Axis.setAutoRange(true);//設置採用自動設置範圍 XYPlot plot2 = new XYPlot(timeSeriesCollection, null, y2Axis, barRenderer); plot2.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色 plot2.setDomainGridlinesVisible(false);//不顯示網格 plot2.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色 CombinedDomainXYPlot domainXYPlot = new CombinedDomainXYPlot(domainAxis);//創建一個恰當的聯合圖形區域對象,以x軸爲共享軸 domainXYPlot.add(plot, 2);//添加圖形區域對象,後面的數字是計算這個區域對象應該佔據多大的區域2/3 domainXYPlot.add(plot2, 1);//添加圖形區域對象,後面的數字是計算這個區域對象應該佔據多大的區域2/3 domainXYPlot.setGap(10);//設置兩個圖形區域對象之間的間隔空間 JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, domainXYPlot, true); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); int day = calendar.get(Calendar.DAY_OF_MONTH); int month = calendar.get(Calendar.MONTH) + 1; int year = calendar.get(Calendar.YEAR); String file_path = PropertiesRead.getinstance().getValue("FILE_PATH"); path = year + "-" + month + "-" + day + "/" + Uuid.getUUID() + "kBar.png"; file_path = file_path + path; saveChartAsJPEG(chart, file_path); } catch (Exception e) { logger.warn("kBarChartPlant:------------Exception--------------"); logger.warn(e); e.printStackTrace(); } return path; } /** * 組合圖繪畫工廠 * k線圖 + 柱狀圖 + 折線圖 * @param params * @return 圖片存放路徑 */ private String kBarLineChartPlant(Map<String, String> params) { String path = null; try{ //獲取繪圖數據 String data = params.get("data"); Map<String, Object> datas = (Map<String, Object>) JsonUtil.parse(data); //獲取標題 String title = (String) datas.get("title"); OHLCSeriesCollection seriesCollection = new OHLCSeriesCollection();//定義k線圖數據集 OHLCSeries series1 = new OHLCSeries("");//高開低收數據序列,股票K線圖的四個數據,依次是開,高,低,收 OHLCSeries series2 = new OHLCSeries("");//定義上漲和下跌的兩個數據集 //K線圖數據 List<List<Object>> quoteList = (List<List<Object>>) datas.get("quoteList"); //成交量數據 List<List<Object>> tradVol = (List<List<Object>>) datas.get("tradVol"); TimeSeriesCollection volSeriesCollection = new TimeSeriesCollection();//保留成交量數據的集合 TimeSeries series3 = new TimeSeries("");//對應時間成交量數據 TimeSeries series4 = new TimeSeries("");//對應時間成交量數據 double mLow = 0d; double mHigh = 0d; //統計這段數據包含多少個交易日,好計算設置時間軸刻度規則 int days = 0; String startDate = null; String endDate = null; //全部工做日 List<Date> workDate = new ArrayList<Date>(); //添加k線圖數據,添加成交量數據 for(int i = 0; i < quoteList.size(); i++){ Date quoteListDate = DateFormatUtils.getDateTimeForAll12((String) quoteList.get(i).get(0)); double open = Double.valueOf(quoteList.get(i).get(1).toString()); double close = Double.valueOf(quoteList.get(i).get(2).toString()); double high = Double.valueOf(quoteList.get(i).get(3).toString()); double low = Double.valueOf(quoteList.get(i).get(4).toString()); Calendar quoteCalendar = Calendar.getInstance(); quoteCalendar.setTimeInMillis(quoteListDate.getTime()); Date tradVolDate = DateFormatUtils.getDateTimeForAll12((String) tradVol.get(i).get(0)); double vol = Double.valueOf(tradVol.get(i).get(1).toString()); Calendar volCalendar = Calendar.getInstance(); volCalendar.setTimeInMillis(tradVolDate.getTime()); workDate.add(quoteListDate); //取這段交易日內最高和最低價格 if(mHigh < high){ mHigh = high; } if(mLow > low){ mLow = low; } else if(mLow == 0){ mLow = low; } if(i == 0){//拿到起始時間 startDate = (String) quoteList.get(i).get(0); } if(i == quoteList.size() - 1){ endDate = (String) quoteList.get(i).get(0); } if(open > close){ series2.add(new Day(quoteCalendar.get(quoteCalendar.DAY_OF_MONTH), quoteCalendar.get(quoteCalendar.MONTH) + 1, quoteCalendar.get(quoteCalendar.YEAR)), open, high, low, close); series4.add(new Day(volCalendar.get(volCalendar.DAY_OF_MONTH), volCalendar.get(volCalendar.MONTH) + 1, volCalendar.get(volCalendar.YEAR)), vol); } else { series1.add(new Day(quoteCalendar.get(quoteCalendar.DAY_OF_MONTH), quoteCalendar.get(quoteCalendar.MONTH) + 1, quoteCalendar.get(quoteCalendar.YEAR)), open, high, low, close); series3.add(new Day(volCalendar.get(volCalendar.DAY_OF_MONTH), volCalendar.get(volCalendar.MONTH) + 1, volCalendar.get(volCalendar.YEAR)), vol); } days++; } //k線圖數據 seriesCollection.addSeries(series1); seriesCollection.addSeries(series2); //成交量數據 volSeriesCollection.addSeries(series3); volSeriesCollection.addSeries(series4); if(StringUtils.isBlank(params.get("startDate"))){ params.put("startDate", startDate); } if(StringUtils.isBlank(params.get("startDate"))){ params.put("endDate", endDate); } //獲取全部節假日 List<Date> allHolidys = getAllHolidays(workDate); //獲取均線圖數據 Map<String, List<List<Object>>> average = (Map<String, List<List<Object>>>) datas.get("average"); List<List<Object>> fiveDayAvg = average.get("MA5");//5天均線數據 List<List<Object>> twentyDayAvg = average.get("MA20");//20天均線數據 TimeSeriesCollection lineSeriesConllection = new TimeSeriesCollection();//保留均線圖數據的集合 TimeSeries series5 = new TimeSeries("MA5");//對應時間成交量數據,5天 TimeSeries series6 = new TimeSeries("MA10");//對應時間成交量數據,10天 TimeSeries series7 = new TimeSeries("MA20");//對應時間成交量數據,20天 //添加均線圖5天數據 if(fiveDayAvg != null){ for(List<Object> list : fiveDayAvg){ Date avgDate = DateFormatUtils.getDateTimeForAll12((String) list.get(0)); double avg = Double.valueOf(list.get(1).toString()); Calendar avgCalendar = Calendar.getInstance(); avgCalendar.setTimeInMillis(avgDate.getTime()); series5.add(new Day(avgCalendar.get(avgCalendar.DAY_OF_MONTH), avgCalendar.get(avgCalendar.MONTH) + 1, avgCalendar.get(avgCalendar.YEAR)), avg); } } //添加均線圖20天數據 if(twentyDayAvg != null){ for(List<Object> list : twentyDayAvg){ Date avgDate = DateFormatUtils.getDateTimeForAll12((String) list.get(0)); double avg = Double.valueOf(list.get(1).toString()); Calendar avgCalendar = Calendar.getInstance(); avgCalendar.setTimeInMillis(avgDate.getTime()); series7.add(new Day(avgCalendar.get(avgCalendar.DAY_OF_MONTH), avgCalendar.get(avgCalendar.MONTH) + 1, avgCalendar.get(avgCalendar.YEAR)), avg); } } lineSeriesConllection.addSeries(series5); lineSeriesConllection.addSeries(series6); lineSeriesConllection.addSeries(series7); //設置K線圖的畫圖器 CandlestickRenderer candlestickRender = new CandlestickRenderer(); candlestickRender.setUpPaint(Color.BLACK);//設置股票上漲的K線圖顏色 candlestickRender.setDownPaint(Color.CYAN);//設置股票下跌的K線圖顏色 candlestickRender.setSeriesPaint(1, Color.CYAN);//設置股票下跌的K線圖顏色 candlestickRender.setSeriesPaint(0, Color.RED);//設置股票上漲的K線圖顏色 candlestickRender.setAutoWidthMethod(CandlestickRenderer.WIDTHMETHOD_AVERAGE);//設置如何對K線圖的寬度進行設定 candlestickRender.setAutoWidthGap(0.001);//設置各個K線圖之間的間隔 candlestickRender.setSeriesVisibleInLegend(false);//設置不顯示legend(數據顏色提示) //設置k線圖y軸參數 NumberAxis y1Axis=new NumberAxis();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置 y1Axis.setAutoRange(false);//設置不採用自動設置數據範圍 y1Axis.setUpperMargin(Const.UPPER_RANGE);//設置向上邊框距離 y1Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12)); y1Axis.setRange(mLow - (mLow * Const.UP_OR_DOWN_RANGE), mHigh + (mHigh * Const.UP_OR_DOWN_RANGE));//設置y軸數據範圍 // y1Axis.setAutoTickUnitSelection(true);//數據軸的數據標籤是否自動肯定(默認爲true) //設置k線圖x軸,也就是時間軸 DateAxis domainAxis = new DateAxis(); domainAxis.setAutoRange(false);//設置不採用自動設置時間範圍 //設置時間範圍,注意,最大和最小時間設置時須要+ - 。不然時間刻度沒法顯示 Date da = DateFormatUtils.getDateTimeForAll12(endDate); da.setTime(da.getTime() + 1); Date sda = DateFormatUtils.getDateTimeForAll12(startDate); sda.setTime(sda.getTime() - 1); domainAxis.setRange(sda, da); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); domainAxis.setAutoTickUnitSelection(false);//設置不採用自動選擇刻度值 domainAxis.setTickMarkPosition(DateTickMarkPosition.START);//設置標記的位置 domainAxis.setStandardTickUnits(DateAxis.createStandardDateTickUnits());// 設置標準的時間刻度單位 domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, days / Const.TIME_SCALE));// 設置時間刻度的間隔 domainAxis.setDateFormatOverride(df);//設置時間格式 SegmentedTimeline timeline = SegmentedTimeline.newMondayThroughFridayTimeline();//設置時間線顯示 //排除全部節假日 for(Date holiday : allHolidys){ timeline.addException(holiday); } domainAxis.setTimeline(timeline); //設置均線圖畫圖器 XYLineAndShapeRenderer lineAndShapeRenderer = new XYLineAndShapeRenderer(); lineAndShapeRenderer.setBaseItemLabelsVisible(true); lineAndShapeRenderer.setSeriesShapesVisible(0, false);//設置不顯示數據點模型 lineAndShapeRenderer.setSeriesShapesVisible(1, false); lineAndShapeRenderer.setSeriesShapesVisible(2, false); lineAndShapeRenderer.setSeriesPaint(0, Color.WHITE);//設置均線顏色 lineAndShapeRenderer.setSeriesPaint(1, Color.YELLOW); lineAndShapeRenderer.setSeriesPaint(2, Color.MAGENTA); //生成畫圖細節 第一個和最後一個參數這裏須要設置爲null,不然畫板加載不一樣類型的數據時會有類型錯誤異常 //多是由於初始化時,構造器內會把統一數據集合設置爲傳參的數據集類型,畫圖器可能也是一樣一個道理 XYPlot plot = new XYPlot(null,domainAxis,y1Axis,null); plot.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色 plot.setDomainGridlinesVisible(false);//不顯示網格 plot.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色 //將設置好的數據集合和畫圖器放入畫板 plot.setDataset(0, seriesCollection); plot.setRenderer(0, candlestickRender); plot.setDataset(1, lineSeriesConllection); plot.setRenderer(1, lineAndShapeRenderer); //設置柱狀圖參數 XYBarRenderer barRenderer = new XYBarRenderer(); barRenderer.setDrawBarOutline(true);//設置顯示邊框線 barRenderer.setBarPainter(new StandardXYBarPainter());//取消漸變效果 barRenderer.setMargin(0.3);//設置柱形圖之間的間隔 barRenderer.setSeriesPaint(0, Color.BLACK);//設置柱子內部顏色 barRenderer.setSeriesPaint(1, Color.CYAN);//設置柱子內部顏色 barRenderer.setSeriesOutlinePaint(0, Color.RED);//設置柱子邊框顏色 barRenderer.setSeriesOutlinePaint(1, Color.CYAN);//設置柱子邊框顏色 barRenderer.setSeriesVisibleInLegend(false);//設置不顯示legend(數據顏色提示) barRenderer.setShadowVisible(false);//設置沒有陰影 //設置柱狀圖y軸參數 NumberAxis y2Axis=new NumberAxis();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置 y2Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12));//設置y軸字體 y2Axis.setAutoRange(true);//設置採用自動設置時間範圍 //這裏不設置x軸,x軸參數依照k線圖x軸爲模板 XYPlot plot2 = new XYPlot(volSeriesCollection, null, y2Axis, barRenderer); plot2.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色 plot2.setDomainGridlinesVisible(false);//不顯示網格 plot2.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色 //創建一個恰當的聯合圖形區域對象,以x軸爲共享軸 CombinedDomainXYPlot domainXYPlot = new CombinedDomainXYPlot(domainAxis);// domainXYPlot.add(plot, 2);//添加圖形區域對象,後面的數字是計算這個區域對象應該佔據多大的區域2/3 domainXYPlot.add(plot2, 1);//添加圖形區域對象,後面的數字是計算這個區域對象應該佔據多大的區域1/3 domainXYPlot.setGap(10);//設置兩個圖形區域對象之間的間隔空間 //生成圖紙 JFreeChart chart = new JFreeChart(title, new Font("微軟雅黑", Font.BOLD, 24), domainXYPlot, true); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); int day = calendar.get(Calendar.DAY_OF_MONTH); int month = calendar.get(Calendar.MONTH) + 1; int year = calendar.get(Calendar.YEAR); String file_path = PropertiesRead.getinstance().getValue("FILE_PATH"); path = year + "-" + month + "-" + day + "/" + Uuid.getUUID() + "kLineBar.png"; file_path = file_path + path; saveChartAsJPEG(chart, file_path); } catch (Exception e) { logger.warn("kBarLineChartPlant:------------Exception--------------"); logger.warn(e); e.printStackTrace(); } return path; }