I am currently experimenting with the JFreeChart library to create an OHLC chart. I would like to draw a horizontal line at a certain price level, for example, at 10.5, and place a point on the line at a specific date, for example, "2021-01-02". Although my code successfully draws the axis, bars, and a horizontal line at 10.5, but the filled circle/point (point2d) I tried to add is not visible by some reason (probably because of wrong coordinates).
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYShapeAnnotation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.data.xy.DefaultHighLowDataset;
import org.jfree.data.xy.OHLCDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleInsets;
public class OHLCChartDemo extends ApplicationFrame {
public OHLCChartDemo(final String title) throws ParseException {
super(title);
final JFreeChart chart = createChart(createDataset());
setContentPane(new ChartPanel(chart));
}
private OHLCDataset createDataset() throws ParseException {
final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final DefaultHighLowDataset dataset = new DefaultHighLowDataset("Series 1",
new Date[] { new Date(df.parse("2021-01-01").getTime()), new Date(df.parse("2021-01-02").getTime()),
new Date(df.parse("2021-01-03").getTime()), new Date(df.parse("2021-01-04").getTime()) },
new double[] { 11.0, 13.0, 9.0, 12.0 }, new double[] { 8.0, 9.0, 7.0, 8.5 },
new double[] { 10.0, 11.0, 8.0, 10.5 }, new double[] { 9.0, 10.0, 8.5, 9.5 },
new double[] { 11.0, 11.0, 9.0, 9.5 });
return dataset;
}
private JFreeChart createChart(final XYDataset dataset) throws ParseException {
final JFreeChart chart = ChartFactory.createCandlestickChart("OHLC Chart", "Date", "Price", (OHLCDataset) dataset, false);
chart.setBackgroundPaint(Color.white);
final XYPlot plot = (XYPlot) chart.getPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.lightGray);
plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
final CandlestickRenderer renderer = new CandlestickRenderer();
renderer.setDrawVolume(false);
plot.setRenderer(renderer);
final DateAxis axis = (DateAxis) plot.getDomainAxis();
axis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setAutoRangeIncludesZero(false);
double price = 10.5;
final ValueMarker marker = new ValueMarker(price);
marker.setPaint(Color.blue);
plot.addRangeMarker(marker);
final Ellipse2D point2d = new Ellipse2D.Double(2.5, 10.5, 20, 20);
XYShapeAnnotation annotation = new XYShapeAnnotation(point2d, new BasicStroke(2.0f), Color.BLACK, Color.BLUE);
plot.addAnnotation(annotation);
return chart;
}
public static void main(final String[] args) throws ParseException {
final OHLCChartDemo demo = new OHLCChartDemo("OHLC Chart Demo");
demo.pack();
demo.setVisible(true);
}
}
How can I draw a filled circle at the intersection of the horizontal line at level (FEX)10.5 and the date (FEX)"2021-01-02"? Alternatively, how can I draw a horizontal line starting from that point and extending to the right end of the chart?
XYShapeAnnotation
notes that "shape coordinates are specified in data space." For a DateAxis
, this is milliseconds since the Java epoch. As an example, the following ad hoc fragment added to your example produces the ellipse show below. It's a half-day wide and one price unit high.
double w = 12 * 60 * 60 * 1000;
double t = dataset.getX(0, 1).doubleValue() - w;
final Ellipse2D point2d =
new Ellipse2D.Double(t + w / 2, 10, w, 1);