using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using ChartForgeX.Core;
using ChartForgeX.Primitives;
using ChartForgeX.Rendering;
using ChartForgeX.Themes;
using ChartForgeX.Topology;
using ChartForgeX.Typography;
using ChartForgeX.VisualArtifacts;
using ChartForgeX.VisualBlocks;
var mode = VisualThemeMode.Light;
var theme = VisualTheme.Graphite();
var model = CandlestickRecipe.Create("compact-options", mode);
var context = new VisualRenderContext(
new VisualLayoutOptions(new VisualSize(360, 360)), theme, mode,
new VisualFrame("Daily opening and closing prices", "Hollow rising bodies, filled falling bodies and independent wick strokes", showLegend: null, showSurface: false));
var prepared = model.Prepare(context);
File.WriteAllText("visual.svg", prepared.ToSvg());
File.WriteAllBytes("visual.png", prepared.ToPng());
File.WriteAllText("visual.html", prepared.ToArtifact("example", VisualArtifactKind.Chart).ToHtmlPage());
/// Builds daily opening, closing, high and low prices as candlesticks.
public static class CandlestickRecipe {
/// Creates the selected candlestick example with optional authored body and wick styling.
public static Chart Create(string variant = "wide", VisualThemeMode mode = VisualThemeMode.Light) {
if (variant is not ("wide" or "compact" or "sparse" or "options" or "compact-options" or "dashed" or "compact-dashed"))
throw new ArgumentOutOfRangeException(nameof(variant));
var chart = Chart.Create();
if (variant is "options" or "compact-options" or "dashed" or "compact-dashed") {
var prices = ChartSeries.CreateCandlestick(new ChartSeriesId("daily-prices"), "Daily prices", new[] {
new ChartCandlestick(1, 44, 58, 38, 53), new ChartCandlestick(2, 53, 60, 42, 45),
new ChartCandlestick(3, 46, 55, 41, 46), new ChartCandlestick(4, 47, 47, 47, 47),
new ChartCandlestick(5, 47, 63, 44, 58)
});
prices.ConfigureFinancial(financial => {
financial.Rising.Stroke = ChartColor.FromHex("#2A967B");
financial.Rising.StrokeWidth = 2.4;
financial.Falling.Stroke = ChartColor.FromHex("#DB825B");
financial.Falling.StrokeWidth = 2.8;
financial.Falling.StrokeOpacity = .85;
financial.Rising.FillOpacity = 0;
financial.Rising.Wick.Stroke = ChartColor.FromHex("#729BB7");
financial.Rising.Wick.StrokeWidth = 1.2;
financial.Falling.Fill = ChartColor.FromHex("#EBA85B");
financial.Falling.FillOpacity = .65;
financial.Falling.Wick.Stroke = ChartColor.FromHex("#729BB7");
financial.Falling.Wick.StrokeWidth = 1.4;
}).WithPointColor(4, "#729BB7");
if (variant is "dashed" or "compact-dashed") prices.ConfigureFinancial(financial => {
financial.Rising.DashPattern = new[] { 7d, 5d, 2d };
financial.Rising.DashOffset = -3;
financial.Falling.DashPattern = new[] { 4d, 4d };
financial.Falling.DashOffset = 2;
financial.Rising.Wick.DashPattern = Array.Empty();
financial.Falling.Wick.DashOffset = -1;
});
chart.WithXLabels("Mon", "Tue", "Wed", "Thu", "Fri").WithYAxis("Price")
.WithPointLegend().WithDataLabels(false).AddSeries(prices);
}
else {
var count = variant == "sparse" ? 2 : 5;
var values = Enumerable.Range(1, count).Select(index => new ChartCandlestick(index, 30 + index * 3,
44 + index * 3, 20 + index * 3, index % 2 == 0 ? 26 + index * 3 : 38 + index * 3));
var prices = ChartSeries.CreateCandlestick(new ChartSeriesId("market-price"), "Market price", values);
chart.WithXLabels("Mon", "Tue", "Wed", "Thu", "Fri", "Sat").AddSeries(prices);
}
return chart.WithValueFormat(ChartValueFormat.Number("0.##", CultureInfo.InvariantCulture));
}
}