Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Financial Footprint Chart Renderer added. #415

Merged
merged 3 commits into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,15 +253,19 @@ mvn exec:java

<table>
<tr>
<td><figure><img src="docs/pics/FinancialCandlestickSample.png" alt="FinancialCandlestickSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/chart/samples/financial/FinancialCandlestickSample.java">FinancialCandlestickSample.java (Several Themes Supported)</a></figcaption></figure></td>
<td><figure><img src="docs/pics/FinancialHiLowSample.png" alt="FinancialHiLowSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/chart/samples/financial/FinancialHiLowSample.java">FinancialHiLowSample.java (OHLC Renderer)</a></figcaption></figure></td>
<td><figure><img src="docs/pics/FinancialCandlestickSample.png" alt="FinancialCandlestickSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/financial/samples/FinancialCandlestickSample.java">FinancialCandlestickSample.java (Several Themes Supported)</a></figcaption></figure></td>
<td><figure><img src="docs/pics/FinancialHiLowSample.png" alt="FinancialHiLowSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/financial/samples/FinancialHiLowSample.java">FinancialHiLowSample.java (OHLC Renderer)</a></figcaption></figure></td>
</tr>
<tr>
<td><figure><img src="docs/pics/FinancialAdvancedCandlestickSample.png" alt="FinancialAdvancedCandlestickSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/chart/samples/financial/FinancialAdvancedCandlestickSample.java">FinancialAdvancedCandlestickSample.java (Advanced PaintBars and Extension Points)</a></figcaption></figure></td>
<td><figure><img src="docs/pics/FinancialRealtimeCandlestickSample.png" alt="FinancialAdvancedCandlestickSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/chart/samples/financial/FinancialRealtimeCandlestickSample.png">FinancialRealtimeCandlestickSample.java (OHLC Tick Replay Real-time processing)</a></figcaption></figure></td>
<td><figure><img src="docs/pics/FinancialAdvancedCandlestickSample.png" alt="FinancialAdvancedCandlestickSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/financial/samples/FinancialAdvancedCandlestickSample.java">FinancialAdvancedCandlestickSample.java (Advanced PaintBars and Extension Points)</a></figcaption></figure></td>
<td><figure><img src="docs/pics/FinancialRealtimeCandlestickSample.png" alt="FinancialAdvancedCandlestickSample" width=600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/financial/samples/FinancialRealtimeCandlestickSample.java">FinancialRealtimeCandlestickSample.java (OHLC Tick Replay Real-time processing)</a></figcaption></figure></td>
</tr>
</table>

#### Financial Footprint Chart

<figure><img src="docs/pics/FinancialRealtimeFootprintSample.png" alt="FinancialAdvancedCandlestickSample" width=1600/><figcaption><a href="chartfx-samples/src/main/java/de/gsi/financial/samples/FinancialRealtimeFootprintSample.java">FinancialRealtimeFootprintSample.java (FOOTPRINT Tick Replay Real-time processing)</a></figcaption></figure>

### Math- & Signal-Processing related examples
The math samples can be started by running:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected double[] findAreaDistances(FindAreaDistances findAreaDistances,
* @return the specific paint bar Paint
*/
protected Paint getPaintBarColor(OhlcvRendererEpData data) {
if (paintBarMarker != null) {
if (paintBarMarker != null && data != null) {
return paintBarMarker.getPaintBy(data);
}
return null;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import de.gsi.chart.axes.spi.AbstractAxisParameter;
import de.gsi.chart.renderer.Renderer;
import de.gsi.chart.renderer.spi.financial.CandleStickRenderer;
import de.gsi.chart.renderer.spi.financial.FootprintRenderer;
import de.gsi.chart.renderer.spi.financial.HighLowRenderer;
import de.gsi.chart.renderer.spi.financial.PositionFinancialRendererPaintAfterEP;
import de.gsi.chart.renderer.spi.financial.service.DataSetAware;
Expand Down Expand Up @@ -86,6 +87,33 @@ else if (renderer instanceof HighLowRenderer) {
throw new IllegalArgumentException("HighLowRenderer: Not implemented yet. ColorScheme=" + theme);
}
}
// driven-by FootprintRenderer
else if (renderer instanceof FootprintRenderer) {
switch (theme) {
case CLASSIC:
dataSet.setStyle("footprintLongColor=green; footprintShortColor=red; footprintCrossLineColor=grey; footprintDefaultFontColor=rgba(255,255,255,0.58); footprintPocColor=#d1d100; "
+ "footprintVolumeLongColor=rgba(139,199,194,0.4); footprintVolumeShortColor=rgba(235,160,159,0.4)");
break;
case CLEARLOOK:
dataSet.setStyle("footprintLongColor=#4c4c4c; footprintShortColor=red; footprintCrossLineColor=grey; footprintDefaultFontColor=rgba(255,255,255,0.58); footprintPocColor=#d1d100; "
+ "footprintVolumeLongColor=rgba(139,199,194,0.4); footprintVolumeShortColor=rgba(235,160,159,0.4)");
break;
case SAND:
dataSet.setStyle("footprintLongColor=#00aa00; footprintShortColor=red; footprintCrossLineColor=black; footprintDefaultFontColor=rgba(255,255,255,0.58); footprintPocColor=#d1d100; "
+ "candleShadowColor=rgba(72,72,72,0.2); footprintVolumeLongColor=rgba(139,199,194,0.4); footprintVolumeShortColor=rgba(235,160,159,0.4)");
break;
case BLACKBERRY:
dataSet.setStyle("footprintLongColor=#00022e; footprintShortColor=#780000; footprintCrossLineColor=grey; footprintDefaultFontColor=rgba(255,255,255,0.58); footprintPocColor=yellow; "
+ "candleLongWickColor=white; candleShortWickColor=red; footprintVolumeLongColor=rgba(139,199,194,0.4); footprintVolumeShortColor=rgba(235,160,159,0.4)");
break;
case DARK:
dataSet.setStyle("footprintLongColor=#298988; footprintShortColor=#963838; footprintCrossLineColor=grey; footprintDefaultFontColor=rgba(255,255,255,0.58); footprintPocColor=yellow; "
+ "footprintVolumeLongColor=rgba(139,199,194,0.4); footprintVolumeShortColor=rgba(235,160,159,0.4)");
break;
default:
throw new IllegalArgumentException("FootprintRenderer: Not implemented yet. ColorScheme=" + theme);
}
}

// extension points configuration support
if (renderer instanceof RendererPaintAfterEPAware) {
Expand Down Expand Up @@ -203,8 +231,6 @@ public void applyTo(String theme, String customColorScheme, XYChart chart) throw
((AbstractAxisParameter) chart.getYAxis()).setTickLabelFill(Color.rgb(194, 194, 194));
}
break;
default:
throw new IllegalArgumentException("Theme is not implemented yet. Theme=" + theme);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,53 @@ public class FinancialCss { // NOPMD decide not to rename it for the time being
*/
public static final String DATASET_POSITION_ORDER_LINKAGE_LINE_WIDTH = "positionOrderLinkageLineWidth";

// FOOTPRINT ----------------------------------------------------------

/**
* Footprint bar relative width against actual scaled view. Defined in percentage range: {@literal <}0.0, 1.0{@literal >}
*/
public static final String DATASET_FOOTPRINT_BAR_WIDTH_PERCENTAGE = "footprintBarWidthPercent";

/**
* Footprint renderer the main ratio for resizing of the final footprint bar paint
*/
public static final String DATASET_FOOTPRINT_PAINT_MAIN_RATIO = "footprintPaintMainRatio";

/**
* The footprint candle boxes color for candle's upstick
*/
public static final String DATASET_FOOTPRINT_LONG_COLOR = "footprintLongColor";

/**
* The footprint candle boxed color for candle's downstick
*/
public static final String DATASET_FOOTPRINT_SHORT_COLOR = "footprintShortColor";

/**
* Volume Long bars with this defined color and transparency, if paintVolume=true, the volume bars are painted.
*/
public static final String DATASET_FOOTPRINT_VOLUME_LONG_COLOR = "footprintVolumeLongColor";

/**
* Volume Short bars with this defined color and transparency, if paintVolume=true, the volume bars are painted.
*/
public static final String DATASET_FOOTPRINT_VOLUME_SHORT_COLOR = "footprintVolumeShortColor";

/**
* Footprint division line between bid and ask numbers (cross-line vertical)
*/
public static final String DATASET_FOOTPRINT_CROSS_LINE_COLOR = "footprintCrossLineColor";

/**
* Footprint default font color. If the column color grouping is disabled, this color is taken.
*/
public static final String DATASET_FOOTPRINT_DEFAULT_FONT_COLOR = "footprintDefaultFontColor";

/**
* Footprint POC color. POC = Point of control.
*/
public static final String DATASET_FOOTPRINT_POC_COLOR = "footprintPocColor";

private FinancialCss() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ public class OhlcvRendererEpData {
public double yClose; // close in display coords
public double yDiff; // diff = open - close
public double yMin; // minimal y coord of bar
public Object addon; // addon defined by specific renderer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package de.gsi.chart.renderer.spi.financial.service.footprint;

import static de.gsi.chart.renderer.spi.financial.css.FinancialColorSchemeConstants.*;

import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

import de.gsi.dataset.spi.financial.api.attrs.AttributeKey;
import de.gsi.dataset.spi.financial.api.attrs.AttributeModel;

public class FootprintRendererAttributes extends AttributeModel {
/** Column coloring group feature active, default true */
public static final AttributeKey<Boolean> COLUMN_COLORING_FEATURE_ACTIVE = AttributeKey.create(Boolean.class, "COLUMN_COLORING_FEATURE_ACTIVE");

/** Draw pullback column, default true */
public static final AttributeKey<Boolean> DRAW_PULLBACK_COLUMN = AttributeKey.create(Boolean.class, "DRAW_PULLBACK_COLUMN");

/** Draw rectangle of POC of each bar, default true */
public static final AttributeKey<Boolean> DRAW_POC_RECTANGLE_OF_EACH_BAR = AttributeKey.create(Boolean.class, "DRAW_POC_RECTANGLE_OF_EACH_BAR");

/**
* Column color group settings:
* 1st column bid [0, 1, 2, 3] groups
* 2nd column ask [0, 1, 2, 3] groups
*/
public static final AttributeKey<Color[][]> COLUMN_COLOR_GROUP_SETTINGS = AttributeKey.create(Color[][].class, "COLUMN_COLOR_GROUP_SETTINGS");

/**
* Column color group thresholds:
* three thresholds for calculation of column color group choosing process
*/
public static final AttributeKey<Double[]> COLUMN_COLOR_GROUP_THRESHOLDS = AttributeKey.create(Double[].class, "COLUMN_COLOR_GROUP_THRESHOLDS");

/** Bolding/Plain font bid/ask under defined threshold, 0 means disabled, default 30 */
public static final AttributeKey<Double> BID_ASK_BOLD_THRESHOLD = AttributeKey.create(Double.class, "BID_ASK_BOLD_THRESHOLD");

/**
* Bid/Ask volume fonts:
* 0 - plain normal font, number is less BID_ASK_BOLD_THRESHOLD
* 1 - bold normal font, number is higher or equal than BID_ASK_BOLD_THRESHOLD
* 2 - bold big font, the number is last bar and last price
*/
public static final AttributeKey<Font[]> BID_ASK_VOLUME_FONTS = AttributeKey.create(Font[].class, "BID_ASK_VOLUME_FONTS");

/**
* Configure Footprint by default values. Good practise is create these defaults and apply your changes to this instance by direct call setAttribute method.
*
* @param scheme the coloring scheme
* @return define default values
*/
public static FootprintRendererAttributes getDefaultValues(String scheme) {
FootprintRendererAttributes model = new FootprintRendererAttributes();

model.setAttribute(COLUMN_COLORING_FEATURE_ACTIVE, true);

model.setAttribute(DRAW_POC_RECTANGLE_OF_EACH_BAR, true);

model.setAttribute(DRAW_PULLBACK_COLUMN, true);

model.setAttribute(COLUMN_COLOR_GROUP_THRESHOLDS, new Double[] { 40.0d, 100.0d, 150.0d });

model.setAttribute(BID_ASK_BOLD_THRESHOLD, 30.0d);

model.setAttribute(BID_ASK_VOLUME_FONTS, new Font[] {
Font.font("Segoe UI", FontWeight.NORMAL, 13), // plain normal font, number is less BID_ASK_BOLD_THRESHOLD
Font.font("Segoe UI", FontWeight.BOLD, 12), // bold normal font, number is higher or equal than BID_ASK_BOLD_THRESHOLD
Font.font("Segoe UI", FontWeight.BOLD, 15) // bold big font, the number is last bar and last price
});

Color[][] columnColorGroupSettings;
switch (scheme) {
case SAND:
case CLASSIC:
case CLEARLOOK:
columnColorGroupSettings = new Color[][] {
{
Color.rgb(0, 128, 255), // RANGE 0 BID COLOR, color: light blue
Color.rgb(128, 128, 128), // RANGE 1 BID COLOR, color: white
Color.rgb(255, 128, 192), // RANGE 2 BID COLOR, color: pink
Color.rgb(242, 0, 0) // RANGE 3 BID COLOR, color: red
},
{
Color.rgb(0, 128, 255), // RANGE 0 ASK COLOR, color: light blue
Color.rgb(128, 128, 128), // RANGE 1 ASK COLOR, color: white
Color.rgb(124, 190, 190), // RANGE 2 ASK COLOR, color: light green
Color.rgb(0, 128, 0) // RANGE 3 ASK COLOR, color: green
}
};
break;
default:
columnColorGroupSettings = new Color[][] {
{
Color.rgb(0, 128, 255), // RANGE 0 BID COLOR, color: light blue
Color.rgb(255, 255, 255), // RANGE 1 BID COLOR, color: white
Color.rgb(255, 128, 192), // RANGE 2 BID COLOR, color: pink
Color.rgb(242, 0, 0) // RANGE 3 BID COLOR, color: red
},
{
Color.rgb(0, 128, 255), // RANGE 0 ASK COLOR, color: light blue
Color.rgb(255, 255, 255), // RANGE 1 ASK COLOR, color: white
Color.rgb(124, 190, 190), // RANGE 2 ASK COLOR, color: light green
Color.rgb(0, 128, 0) // RANGE 3 ASK COLOR, color: green
}
};
break;
}
model.setAttribute(COLUMN_COLOR_GROUP_SETTINGS, columnColorGroupSettings);

return model;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.gsi.chart.renderer.spi.financial.service.footprint;

import java.util.HashMap;
import java.util.Map;

import javafx.scene.paint.Color;
import javafx.scene.text.Font;

/**
* The domain object provides data for footprint column colors.
* Defines specific colors for each footprint lines by column color services.
*/
public class NbColumnColorGroup {
public Map<Double, FontColor> fontColorMap = new HashMap<>();

public static class FontColor {
public final Font bidFont;
public final Color bidColor;
public final Font askFont;
public final Color askColor;

public FontColor(Font bidFont, Color bidColor, Font askFont, Color askColor) {
this.bidFont = bidFont;
this.bidColor = bidColor;
this.askFont = askFont;
this.askColor = askColor;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Calendar;

import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

Expand All @@ -22,6 +23,7 @@
import de.gsi.chart.axes.spi.CategoryAxis;
import de.gsi.chart.axes.spi.DefaultNumericAxis;
import de.gsi.chart.renderer.spi.financial.css.FinancialColorSchemeConfig;
import de.gsi.chart.renderer.spi.financial.service.OhlcvRendererEpData;
import de.gsi.chart.renderer.spi.financial.utils.CalendarUtils;
import de.gsi.chart.renderer.spi.financial.utils.FinancialTestUtils;
import de.gsi.chart.renderer.spi.financial.utils.FinancialTestUtils.TestChart;
Expand Down Expand Up @@ -49,7 +51,7 @@ public void start(Stage stage) throws Exception {
rendererTested.setComputeLocalRange(false);
rendererTested.setComputeLocalRange(true);

assertNull(rendererTested.getPaintBarColor(null));
assertNull(rendererTested.getPaintBarColor(new OhlcvRendererEpData()));

final DefaultNumericAxis xAxis = new DefaultNumericAxis("time", "iso");
xAxis.setTimeAxis(true);
Expand Down Expand Up @@ -134,7 +136,7 @@ public void testVolumeConstructor() {

@Test
public void noXyChartInstance() {
assertThrows(InvalidParameterException.class, () -> rendererTested.render(null, new TestChart(), 0, null));
assertThrows(InvalidParameterException.class, () -> rendererTested.render(new Canvas(300, 200).getGraphicsContext2D(), new TestChart(), 0, null));
}

@Test
Expand Down
Loading