In order to do so, I import data from a file, creating a DefaultOHLCDataset, as shown here: http://pastie.org/4655649
Code: Select all
package model;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import org.jfree.chart.axis.SegmentedTimeline;
import org.jfree.data.xy.DefaultOHLCDataset;
import org.jfree.data.xy.OHLCDataItem;
public class ProcessData {
private YardCalendar _calendar;
private SegmentedTimeline _timeline;
private String _market;
private String _alarm;
private String _stockSymbol;
private DefaultOHLCDataset _dataSet = null;
public String getAlarm() {
return _alarm;
}
public YardCalendar getCalendar() {
return _calendar;
}
public SegmentedTimeline getTimeline() {
return _timeline;
}
public DefaultOHLCDataset getDataSet() {
if(_dataSet == null){
//This is the data needed for the dataset
OHLCDataItem[] data = getData(_market, _stockSymbol, _alarm);
//Create a dataset, an Open, High, Low, Close dataset
_dataSet = new DefaultOHLCDataset(_stockSymbol, data);
}
return _dataSet;
}
public ProcessData(String market, String alarm, String stockSymbol){
_calendar = new YardCalendar(market, alarm);
_timeline = new SegmentedTimeline(SegmentedTimeline.DAY_SEGMENT_SIZE, 7, 0);
_market = market;
_alarm = alarm;
_stockSymbol = stockSymbol;
}
protected OHLCDataItem[] getData(String market, String stockSymbol, String alarmPath) {
List<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
try {
FileInputStream candleValues = new FileInputStream(alarmPath+"/GuiValue.txt");
DataInputStream in = new DataInputStream(candleValues);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String inputLine;
br.readLine();
int i = 0;
YardDay calendarDay;
Date date;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
while ((inputLine = br.readLine()) != null) {
calendarDay = _calendar.getDay(i);
//adds holidays and weekends to the candle exception list
while(calendarDay.isHoliday() || calendarDay.isWeekend()){
date = formatter.parse(calendarDay.getYear()+"/"+calendarDay.getMonth()+"/"+calendarDay.getDay());
_timeline.addException(date);
calendarDay = _calendar.getDay(++i);
}
if(calendarDay.isWorkDay()){
StringTokenizer st = new StringTokenizer(inputLine, " ");
NumberFormat nf = NumberFormat.getInstance(Locale.ITALIAN);
double open = nf.parse(st.nextToken()).doubleValue();
double high = nf.parse(st.nextToken()).doubleValue();
double low = nf.parse(st.nextToken()).doubleValue();
double close = nf.parse(st.nextToken()).doubleValue();
double volume = nf.parse(st.nextToken()).doubleValue();
date = formatter.parse(calendarDay.getYear()+"/"+calendarDay.getMonth()+"/"+calendarDay.getDay());
OHLCDataItem item = new OHLCDataItem(date, open, high, low, close, volume);
dataItems.add(item);
i++;
}
}
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
//Convert the list into an array
OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);
return data;
}
}
Code: Select all
package model;
import java.awt.Color;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
import java.util.StringTokenizer;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.SegmentedTimeline;
import org.jfree.chart.plot.IntervalMarker;
import org.jfree.chart.plot.Marker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.DefaultOHLCDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;
public class CandleChartModel extends AbstractModel{
private JFreeChart _chart;
public JFreeChart getChart() {
return _chart;
}
public CandleChartModel(ProcessData data) {
createChart(data);
}
public void setChart(ProcessData data){
createChart(data);
setChanged();
//model Push - send counter as part of the message
notifyObservers(_chart);
}
private void createChart(ProcessData data) {
//Creates and imports the data into the calendar
DateAxis domainAxis = new DateAxis("Date");
NumberAxis rangeAxis = new NumberAxis("Price");
CandlestickRenderer candleRenderer = new CandlestickRenderer();
XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer(true,false);
DefaultOHLCDataset candleDataset = data.getDataSet();
XYDataset linesDataSet = null;
XYPlot mainPlot = new XYPlot();
mainPlot.setRangeAxis(rangeAxis);
mainPlot.setDomainAxis(domainAxis);
mainPlot.setDataset(0, candleDataset);
mainPlot.setRenderer(0, candleRenderer);
//Do some setting up, see the API Doc
candleRenderer.setSeriesPaint(0, Color.BLACK);
candleRenderer.setDrawVolume(true);
rangeAxis.setAutoRangeIncludesZero(false);
lineRenderer.setPaint(Color.BLACK);
//Cutting the extra space that is included in the DomainAxis by setting the range manually
long start = data.getCalendar().getDay(0).getDate().getTime() - SegmentedTimeline.DAY_SEGMENT_SIZE;
long end = data.getCalendar().getDay(data.getCalendar().size()-1).getDate().getTime() + SegmentedTimeline.DAY_SEGMENT_SIZE;
domainAxis.setMinimumDate(new Date(start));
domainAxis.setMaximumDate(new Date(end));
//WARNING: Does not work with all charts.
domainAxis.setTimeline(data.getTimeline());
//Adds the color areas corresponding to the sub patterns found.
linesDataSet = addAreas(mainPlot, data.getAlarm(), candleDataset);
mainPlot.setDataset(1, linesDataSet);
mainPlot.setRenderer(1, lineRenderer);
//Now create the chart and chart panel
String title = data.getAlarm().substring(data.getAlarm().lastIndexOf("/")+1);
_chart = new JFreeChart(mainPlot);
_chart.setTitle(new TextTitle(title, new Font("SansSerif", Font.BOLD, 12)));
_chart.setAntiAlias(true);
_chart.removeLegend();
}
private XYDataset addAreas(XYPlot plot, String alarmPath, DefaultOHLCDataset dataset){
StringTokenizer st;
XYSeriesCollection sets = new XYSeriesCollection();
try {
FileInputStream fs = new FileInputStream(alarmPath+"/Disegno.txt");
DataInputStream in = new DataInputStream(fs);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String inputLine = br.readLine();
int numLines = Integer.parseInt(inputLine);
for(int i=0; i < numLines; i++) {
XYSeries line = new XYSeries(i);
inputLine = br.readLine();
st = new StringTokenizer(inputLine, " ");
NumberFormat nf = NumberFormat.getInstance(Locale.ITALIAN);
int linecode = nf.parse(st.nextToken()).intValue();
int colorcode = nf.parse(st.nextToken()).intValue();
int numDays = nf.parse(st.nextToken()).intValue();
int increment = nf.parse(st.nextToken()).intValue();
inputLine = br.readLine();
st = new StringTokenizer(inputLine, " ");
int point1X = nf.parse(st.nextToken()).intValue();
float point1Y = nf.parse(st.nextToken()).floatValue();
inputLine = br.readLine();
st = new StringTokenizer(inputLine, " ");
int point2X = nf.parse(st.nextToken()).intValue();
float point2Y = nf.parse(st.nextToken()).floatValue();
//The Calendar array starts at 0, the day number at 1, so a small adjustment was needed.
Date day1 = dataset.getXDate(1, point1X-1);
Date day2 = dataset.getXDate(1, point2X-1);
line.add(day1.getTime(),point1Y);
line.add(day2.getTime(), point2Y);
sets.addSeries(line);
Marker marker = new IntervalMarker(day1.getTime(),day2.getTime());
marker.setAlpha(0.15f);
marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
marker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
switch (colorcode){
case 1:
marker.setPaint(Color.BLUE);
break;
case 2:
marker.setPaint(Color.YELLOW);
break;
case 13:
marker.setPaint(Color.GREEN);
break;
case 18:
marker.setPaint(Color.RED);
break;
}
plot.addDomainMarker(marker);
}
in.close();
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return sets;
}
}
Code: Select all
import model.AbstractModel;
import model.CandleChartModel;
import model.ProcessData;
import view.CandleChartView;
import view.PNGView;
import controller.DefaultController;
public class Main {
public static void main(String[] args) {
String market = args[0];
String stockSymbol = args[1];
String alarmType = args[2];
String alarmFolder = args[3];
String destinationFolder = args[4];
String chartName = alarmType.substring(0, alarmType.lastIndexOf('_'))+"-"+alarmFolder.substring(alarmFolder.lastIndexOf("/")+1);
ProcessData data = new ProcessData(market, alarmFolder, stockSymbol);
//create Model and View
AbstractModel myModel = new CandleChartModel(data);
CandleChartView candleView = new CandleChartView(1280,600, myModel);
PNGView pngView = new PNGView(1280,600, myModel);
//tell Model about View.
myModel.addObserver(candleView);
myModel.addObserver(pngView);
//create Controller. tell it about Model and View, initialize model
DefaultController myController = new DefaultController();
myController.addModel(myModel);
myController.addView(candleView);
myController.addView(pngView);
//tell View about Controller
candleView.addController(myController);
pngView.addController(myController);
candleView.draw();
pngView.save(destinationFolder+"/"+chartName);
//program won't exit otherwise. it seams that some AWT is still opened...
System.exit(0);
}
}
When the custom timeline is not used there's no problem whatsoever.
Any idea why this happens?
EDIT: I've put the code directly in the post.