設為首頁收藏本站

艾歐踢論壇

 找回密碼
 立即註冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 活動 交友 discuz

tag 標籤: 解决方案

相關日誌

分享 利用JFreeChart繪制股票K線圖完整解决方案
ifsapp 2015-1-18 02:18
在進行源代碼講解之前,有必要將本人所領悟到的一些關於jfreechart的概念講述下,jfreechart工具基本上把一個圖形分成了幾個邏輯部分。 1.首先是整個的畫布對象(chart),畫布就相當與一個大的容器,包含一些圖形元素,比如为一張白紙 2.然後是畫圖區域對象(plot),就是實際圖形所占據的區域,比如为白紙上的一個長方形 3.然後是圖形所需要兩條軸對象(axis),比如为白紙上的兩條軸線 4.最後是如何進行圖像的繪制對象(render),比如为一只畫圖的筆 5.除開上面的這些對象,還有一個最主要的就是通過必須的數據集(dataset)來生成圖形了 至於一些具體的對象細節,就只好請各位去閱讀相關的API文檔了,在這裏就不詳細的說明 package chart; import java.awt.Color;//顏色系統 import java.text.SimpleDateFormat;//時間格式 import java.awt.Paint;//畫筆系統 import org.jfree.data.time.*; import org.jfree.data.time.Day; import org.jfree.data.time.ohlc.OHLCSeries; import org.jfree.data.time.ohlc.OHLCSeriesCollection; import org.jfree.chart.renderer.xy.*; import org.jfree.chart.axis.*; import org.jfree.chart.plot.*; import org.jfree.chart.*; public class KLineCombineChart { public static void main(String[] args) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");//設置日期格式 double highValue = Double.MIN_VALUE;//設置K線數據當中的最大值 double minValue = Double.MAX_VALUE;//設置K線數據當中的最小值 double high2Value = Double.MIN_VALUE;//設置成交量的最大值 double min2Value = Double.MAX_VALUE;//設置成交量的最低值 OHLCSeries series = new OHLCSeries("");//高開低收數據序列,股票K線圖的四個數據,依次是開,高,低,收 series.add(new Day(28, 9, 2007), 9.2, 9.58, 9.16, 9.34); series.add(new Day(27, 9, 2007), 8.9, 9.06, 8.83, 8.96); series.add(new Day(26, 9, 2007), 9.0, 9.1, 8.82, 9.04); series.add(new Day(25, 9, 2007), 9.25, 9.33, 8.88, 9.00); series.add(new Day(24, 9, 2007), 9.05, 9.50, 8.91, 9.25); series.add(new Day(21, 9, 2007), 8.68, 9.05, 8.40, 9.00); series.add(new Day(20, 9, 2007), 8.68, 8.95, 8.50, 8.69); series.add(new Day(19, 9, 2007), 8.80, 8.94, 8.50, 8.66); series.add(new Day(18, 9, 2007), 8.88, 9.17, 8.69, 8.80); series.add(new Day(17, 9, 2007), 8.26, 8.98, 8.15, 8.89); series.add(new Day(14, 9, 2007), 8.44, 8.45, 8.13, 8.33); series.add(new Day(13, 9, 2007), 8.13, 8.46, 7.97, 8.42); series.add(new Day(12, 9, 2007), 8.2, 8.4, 7.81, 8.13); series.add(new Day(11, 9, 2007), 9.0, 9.0, 8.1, 8.24); series.add(new Day(10, 9, 2007), 8.6, 9.03, 8.40, 8.95); series.add(new Day(7, 9, 2007), 8.89, 9.04, 8.70, 8.73); series.add(new Day(6, 9, 2007), 8.4, 9.08, 8.33, 8.88); series.add(new Day(5, 9, 2007), 8.2, 8.74, 8.17, 8.36); series.add(new Day(4, 9, 2007), 7.7, 8.46, 7.67, 8.27); series.add(new Day(3, 9, 2007), 7.5, 7.8, 7.48, 7.69); series.add(new Day(31, 8, 2007), 7.4, 7.6, 7.28, 7.43); series.add(new Day(30, 8, 2007), 7.42, 7.56, 7.31, 7.40); series.add(new Day(29, 8, 2007), 7.42, 7.66, 7.22, 7.33); series.add(new Day(28, 8, 2007), 7.31, 7.70, 7.15, 7.56); series.add(new Day(27, 8, 2007), 7.05, 7.46, 7.02, 7.41); series.add(new Day(24, 8, 2007), 7.05, 7.09, 6.90, 6.99); series.add(new Day(23, 8, 2007), 7.12, 7.16, 7.00, 7.03); series.add(new Day(22, 8, 2007), 6.96, 7.15, 6.93, 7.11); series.add(new Day(21, 8, 2007), 7.10, 7.15, 7.02, 7.07); series.add(new Day(20, 8, 2007), 7.02, 7.19, 6.94, 7.14); final OHLCSeriesCollection seriesCollection = new OHLCSeriesCollection();//保留K線數據的數據集,必須申明为final,後面要在匿名內部類裏面用到 seriesCollection.addSeries(series); TimeSeries series2=new TimeSeries("");//對應時間成交量數據 series2.add(new Day(28, 9, 2007), 260659400/100); series2.add(new Day(27, 9, 2007), 119701900/100); series2.add(new Day(26, 9, 2007), 109719000/100); series2.add(new Day(25, 9, 2007), 178492400/100); series2.add(new Day(24, 9, 2007), 269978500/100); series2.add(new Day(21, 9, 2007), 361042300/100); series2.add(new Day(20, 9, 2007), 173912600/100); series2.add(new Day(19, 9, 2007), 154622600/100); series2.add(new Day(18, 9, 2007), 200661600/100); series2.add(new Day(17, 9, 2007), 312799600/100); series2.add(new Day(14, 9, 2007), 141652900/100); series2.add(new Day(13, 9, 2007), 221260400/100); series2.add(new Day(12, 9, 2007), 274795400/100); series2.add(new Day(11, 9, 2007), 289287300/100); series2.add(new Day(10, 9, 2007), 289063600/100); series2.add(new Day(7, 9, 2007), 351575300/100); series2.add(new Day(6, 9, 2007), 451357300/100); series2.add(new Day(5, 9, 2007), 442421200/100); series2.add(new Day(4, 9, 2007), 671942600/100); series2.add(new Day(3, 9, 2007), 349647800/100); series2.add(new Day(31, 8, 2007), 225339300/100); series2.add(new Day(30, 8, 2007), 160048200/100); series2.add(new Day(29, 8, 2007), 247341700/100); series2.add(new Day(28, 8, 2007), 394975400/100); series2.add(new Day(27, 8, 2007), 475797500/100); series2.add(new Day(24, 8, 2007), 297679500/100); series2.add(new Day(23, 8, 2007), 191760600/100); series2.add(new Day(22, 8, 2007), 232570200/100); series2.add(new Day(21, 8, 2007), 215693200/100); series2.add(new Day(20, 8, 2007), 200287500/100); TimeSeriesCollection timeSeriesCollection=new TimeSeriesCollection();//保留成交量數據的集合 timeSeriesCollection.addSeries(series2); //獲取K線數據的最高值和最低值 int seriesCount = seriesCollection.getSeriesCount();//一共有多少個序列,目前为一個 for (int i = 0; i seriesCount; i++) { int itemCount = seriesCollection.getItemCount(i);//每一個序列有多少個數據項 for (int j = 0; j itemCount; j++) { if (highValue seriesCollection.getHighValue(i, j)) {//取第i個序列中的第j個數據項的最大值 highValue = seriesCollection.getHighValue(i, j); } if (minValue seriesCollection.getLowValue(i, j)) {//取第i個序列中的第j個數據項的最小值 minValue = seriesCollection.getLowValue(i, j); } } } //獲取最高值和最低值 int seriesCount2 = timeSeriesCollection.getSeriesCount();//一共有多少個序列,目前为一個 for (int i = 0; i seriesCount2; i++) { int itemCount = timeSeriesCollection.getItemCount(i);//每一個序列有多少個數據項 for (int j = 0; j itemCount; j++) { if (high2Value timeSeriesCollection.getYValue(i,j)) {//取第i個序列中的第j個數據項的值 high2Value = timeSeriesCollection.getYValue(i,j); } if (min2Value timeSeriesCollection.getYValue(i, j)) {//取第i個序列中的第j個數據項的值 min2Value = timeSeriesCollection.getYValue(i, j); } } } final CandlestickRenderer candlestickRender=new CandlestickRenderer();//設置K線圖的畫圖器,必須申明为final,後面要在匿名內部類裏面用到 candlestickRender.setUseOutlinePaint(true); //設置是否使用自定義的邊框線,程序自帶的邊框線的顏色不符合中國股票市場的習慣 candlestickRender.setAutoWidthMethod(CandlestickRenderer.WIDTHMETHOD_AVERAGE);//設置如何對K線圖的寬度進行設定 candlestickRender.setAutoWidthGap(0.001);//設置各個K線圖之間的間隔 candlestickRender.setUpPaint(Color.RED);//設置股票上漲的K線圖顏色 candlestickRender.setDownPaint(Color.GREEN);//設置股票下跌的K線圖顏色 DateAxis x1Axis=new DateAxis();//設置x軸,也就是時間軸 x1Axis.setAutoRange(false);//設置不采用自動設置時間範圍 try{ x1Axis.setRange(dateFormat.parse("2007-08-20"),dateFormat.parse("2007-09-29"));//設置時間範圍,注意時間的最大值要比已有的時間最大值要多一天 }catch(Exception e){ e.printStackTrace(); } x1Axis.setTimeline(SegmentedTimeline.newMondayThroughFridayTimeline());//設置時間線顯示的規則,用這個方法就摒除掉了周六和周日這些沒有交易的日期(很多人都不知道有此方法),使圖形看上去連續 x1Axis.setAutoTickUnitSelection(false);//設置不采用自動選擇刻度值 x1Axis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);//設置標記的位置 x1Axis.setStandardTickUnits(DateAxis.createStandardDateTickUnits());//設置標准的時間刻度單位 x1Axis.setTickUnit(new DateTickUnit(DateTickUnit.DAY,7));//設置時間刻度的間隔,一般以周为單位 x1Axis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));//設置顯示時間的格式 NumberAxis y1Axis=new NumberAxis();//設定y軸,就是數字軸 y1Axis.setAutoRange(false);//不不使用自動設定範圍 y1Axis.setRange(minValue*0.9, highValue*1.1);//設定y軸值的範圍,比最低值要低一些,比最大值要大一些,這样圖形看起來會美觀些 y1Axis.setTickUnit(new NumberTickUnit((highValue*1.1-minValue*0.9)/10));//設置刻度顯示的密度 XYPlot plot1=new XYPlot(seriesCollection,x1Axis,y1Axis,candlestickRender);//設置畫圖區域對象 XYBarRenderer xyBarRender=new XYBarRenderer(){ private static final long serialVersionUID = 1L;//为了避免出現警告消息,特設定此值 public Paint getItemPaint(int i, int j){//匿名內部類用來處理當日的成交量柱形圖的顏色與K線圖的顏色保持一致 if(seriesCollection.getCloseValue(i,j)seriesCollection.getOpenValue(i,j)){//收盤價高於開盤價,股票上漲,選用股票上漲的顏色 return candlestickRender.getUpPaint(); }else{ return candlestickRender.getDownPaint(); } }}; xyBarRender.setMargin(0.1);//設置柱形圖之間的間隔 NumberAxis y2Axis=new NumberAxis();//設置Y軸,为數值,後面的設置,参考上面的y軸設置 y2Axis.setAutoRange(false); y2Axis.setRange(min2Value*0.9, high2Value*1.1); y2Axis.setTickUnit(new NumberTickUnit((high2Value*1.1-min2Value*0.9)/4)); XYPlot plot2=new XYPlot(timeSeriesCollection,null,y2Axis,xyBarRender);//建立第二個畫圖區域對象,主要此時的x軸設为了null值,因为要與第一個畫圖區域對象共享x軸 CombinedDomainXYPlot combineddomainxyplot = new CombinedDomainXYPlot(x1Axis);//建立一個恰當的聯合圖形區域對象,以x軸为共享軸 combineddomainxyplot.add(plot1, 2);//添加圖形區域對象,後面的數字是計算這個區域對象應該占據多大的區域2/3 combineddomainxyplot.add(plot2, 1);//添加圖形區域對象,後面的數字是計算這個區域對象應該占據多大的區域1/3 combineddomainxyplot.setGap(10);//設置兩個圖形區域對象之間的間隔空間 JFreeChart chart = new JFreeChart("中國聯通", JFreeChart.DEFAULT_TITLE_FONT, combineddomainxyplot, false); ChartFrame frame = new ChartFrame("中國聯通股票", chart); frame.pack(); frame.setVisible(true); } } 为了能夠保證K線圖的上影線和下影線能夠和K線圖本身的顏色保持一致,找了很多的方法設置都不成功,可以說目前暫不提供單獨繪制K線邊框顏色的方法,所以,經過本人的實驗,對其中的源代碼進行了下修改,具體修改的地方是在下載回來的文件目中source\org\jfree\chart\renderer\xy\CandlestickRenderer.java文件,將 Paint p = getItemPaint(series, item); Paint outlinePaint = null; outlinePaint = getItemOutlinePaint(series, item); } 修改为如下的代碼,這样就會保證K線圖的上影線和下影線能夠和K線圖本身的顏色保持一致,符合中國股票市場K線圖形顏色的習慣: Paint p = getItemPaint(series, item); Paint outlinePaint = null; if (this.useOutlinePaint) { if(yCloseyOpen){ if (this.upPaint != null) { outlinePaint=this.upPaint; } else { outlinePaint=p; } }else{ if (this.downPaint != null) { outlinePaint=this.downPaint; } else { outlinePaint=p; } } } chart.setBackgroundPaint(Color.white);//設置曲線圖背景色 XYPlot plot = (XYPlot) chart.getPlot(); XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)plot.getRenderer(); plot.setBackgroundPaint(Color.white));//設置網格背景顏色 plot.setDomainGridlinePaint(Color.pink);//設置網格豎線顏色 plot.setRangeGridlinePaint(Color.pink);//設置網格橫線顏色 plot.setAxisOffset(new RectangleInsets(0D, 0D, 0D, 10D));//設置曲線圖與xy軸的距離,即曲線與xy軸貼近的距離 xylineandshaperenderer.setBaseShapesVisible(true);//設置曲線是否顯示數據點
個人分類: java|2518 次閱讀|0 個評論

小黑屋|Archiver|手機版|艾歐踢創新工坊    

GMT+8, 2024-5-15 14:32 , Processed in 2.073170 second(s), 16 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

返回頂部