-
Notifications
You must be signed in to change notification settings - Fork 89
/
AbstractFinancialRenderer.java
138 lines (125 loc) · 6.16 KB
/
AbstractFinancialRenderer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package de.gsi.chart.renderer.spi.financial;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import de.gsi.chart.axes.Axis;
import de.gsi.chart.renderer.Renderer;
import de.gsi.chart.renderer.spi.AbstractDataSetManagement;
import de.gsi.chart.renderer.spi.financial.service.OhlcvRendererEpData;
import de.gsi.chart.renderer.spi.financial.service.PaintBarMarker;
import de.gsi.dataset.DataSet;
import de.gsi.dataset.spi.financial.OhlcvDataSet;
/**
* The ancestor for common financial renderers.
* If you use this parent for your financial renderers you can use general features:
* <ul>
* <li>PaintBar - coloring and painting changes of specific bars/candles/lines/dots</li>
* <li>Shadows - specific fast shadow paintings without fx-effects</li>
* <li>Extension-point before/after painting - extend specific renderers by your changes to add EP rules.</li>
* </ul>
*/
@SuppressWarnings({ "PMD.ExcessiveParameterList" })
public abstract class AbstractFinancialRenderer<R extends Renderer> extends AbstractDataSetManagement<R> implements Renderer {
protected PaintBarMarker paintBarMarker;
/**
* Inject PaintBar Marker service
*
* @param paintBarMarker service implementation
*/
public void setPaintBarMarker(PaintBarMarker paintBarMarker) {
this.paintBarMarker = paintBarMarker;
}
/**
* Simple algorithmic solution to calculate required chart area distances.
*
* @param findAreaDistances service for calculation of find chart area distances.
* @param dataset includes data for processing
* @param xAxis X-Axis DO
* @param yAxis Y-Axis DO
* @param xmin minimal value of X
* @param xmax maximal value of X
* @return the calculated distances
*/
protected double[] findAreaDistances(FindAreaDistances findAreaDistances,
DataSet dataset, Axis xAxis, Axis yAxis, double xmin, double xmax) {
return findAreaDistances.findAreaDistances(dataset, xAxis, yAxis, xmin, xmax);
}
/**
* Specific painting/coloring of the OHLCV/Candle Bars.
* If you need specific bar selection visualization - implement this service and write your selection.
*
* @param data domain object for Renderer Extension Points
* @return the specific paint bar Paint
*/
protected Paint getPaintBarColor(OhlcvRendererEpData data) {
if (paintBarMarker != null) {
return paintBarMarker.getPaintBy(data);
}
return null;
}
/**
* Possibility paint volume to financial renderers
*
* @param gc GraphicsContext
* @param ds DataSet domain object which contains volume data
* @param index actual index which is rendered
* @param volumeLongColor volume color for Long Uptick OHLC
* @param volumeShortColor volume color for Short Uptick OHLC
* @param yAxis Y-Axis DO
* @param distances distances estimated from finding service
* @param barWidth width of bar
* @param barWidthHalf half width of bar
* @param x0 the center of the bar for X coordination
*/
protected void paintVolume(GraphicsContext gc, DataSet ds, int index, Color volumeLongColor, Color volumeShortColor, Axis yAxis, double[] distances, double barWidth,
double barWidthHalf, double x0) {
double volume = ds.get(OhlcvDataSet.DIM_Y_VOLUME, index);
double open = ds.get(OhlcvDataSet.DIM_Y_OPEN, index);
double close = ds.get(OhlcvDataSet.DIM_Y_CLOSE, index);
double maxVolume = distances[1];
double volumeHeight = (volume / maxVolume) * 0.3;
double min = yAxis.getDisplayPosition(yAxis.getMin());
double max = yAxis.getDisplayPosition(yAxis.getMax());
double zzVolume = volumeHeight * (max - min);
gc.setFill(open < close ? volumeLongColor : volumeShortColor);
gc.fillRect(x0 - barWidthHalf, min + zzVolume, barWidth, -zzVolume);
}
// services --------------------------------------------------------
@FunctionalInterface
protected interface FindAreaDistances {
double[] findAreaDistances(DataSet dataset, Axis xAxis, Axis yAxis, double xmin, double xmax);
}
protected static class XMinAreaDistances implements FindAreaDistances {
@Override
public double[] findAreaDistances(DataSet dataset, Axis xAxis, Axis yAxis, double xmin, double xmax) {
double minDistance = Integer.MAX_VALUE;
for (int i = dataset.getIndex(DataSet.DIM_X, xmin) + 1; i < Math.min(dataset.getIndex(DataSet.DIM_X, xmax) + 1, dataset.getDataCount()); i++) {
final double param0 = xAxis.getDisplayPosition(dataset.get(DataSet.DIM_X, i - 1));
final double param1 = xAxis.getDisplayPosition(dataset.get(DataSet.DIM_X, i));
if (param0 != param1) {
minDistance = Math.min(minDistance, Math.abs(param1 - param0));
}
}
return new double[] { minDistance };
}
}
protected static class XMinVolumeMaxAreaDistances implements FindAreaDistances {
@Override
public double[] findAreaDistances(DataSet dataset, Axis xAxis, Axis yAxis, double xmin, double xmax) {
double minDistance = Integer.MAX_VALUE;
double maxVolume = Integer.MIN_VALUE;
for (int i = dataset.getIndex(DataSet.DIM_X, xmin) + 1; i < Math.min(dataset.getIndex(DataSet.DIM_X, xmax) + 1, dataset.getDataCount()); i++) {
final double param0 = xAxis.getDisplayPosition(dataset.get(DataSet.DIM_X, i - 1));
final double param1 = xAxis.getDisplayPosition(dataset.get(DataSet.DIM_X, i));
double volume = dataset.get(OhlcvDataSet.DIM_Y_VOLUME, i);
if (maxVolume < volume) {
maxVolume = volume;
}
if (param0 != param1) {
minDistance = Math.min(minDistance, Math.abs(param1 - param0));
}
}
return new double[] { minDistance, maxVolume };
}
}
}