I thought to share info how to set bands to show Fibonacci retracement levels in a trading chart. The levels are got from data Y min... Y max, and applied to 0%, 23.6%, 38.2%, 50%, 61.8% and 100% between that range.
I'm using Semi-bindable WPF chart here. Set their references in your project.
I'll create chart here in the designer in XAML.
Code: Select all
<Window x:Class="WpfTradingFibonacciBands.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lcu="http://schemas.arction.com/semibindablecharting/ultimate/"
Title="MainWindow" Height="350" Width="525">
<Grid Name="gridMain">
<lcu:LightningChartUltimate Name="_chart">
<lcu:LightningChartUltimate.ViewXY>
<lcu:ViewXY>
<lcu:ViewXY.GraphBackground>
<lcu:Fill Color="Black" GradientFill="Solid"/>
</lcu:ViewXY.GraphBackground>
<lcu:ViewXY.YAxes>
<lcu:AxisY/>
</lcu:ViewXY.YAxes>
<lcu:ViewXY.XAxes>
<lcu:AxisX/>
</lcu:ViewXY.XAxes>
</lcu:ViewXY>
</lcu:LightningChartUltimate.ViewXY>
</lcu:LightningChartUltimate>
</Grid>
</Window>
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Arction.Wpf.SemibindableCharting;
using Arction.Wpf.SemibindableCharting.SeriesXY;
using Arction.Wpf.SemibindableCharting.Axes;
using Arction.Wpf.SemibindableCharting.Views.ViewXY;
using Arction.Wpf.SemibindableCharting.Annotations;
namespace WpfTradingFibonacciBands
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ContextMenu _contextMenu = null;
private Point _mouseDownCoords;
//In Fibonacci sequence, next value is about 1.618 times previous. 1/1.618 = 0.618, known as 'golden ratio'
//50 is not part of Fibonacci sequence but used in trading very often
private double[] FibonacciLevels = { 0, 23.6, 38.2, 50, 61.8, 100 };
public MainWindow()
{
InitializeComponent();
InitChart();
//Create right-click menu
_contextMenu = new ContextMenu();
MenuItem item = new MenuItem();
item.Header = "Show / hide Fibonacci retracement";
item.Click += item_Click;
_contextMenu.Items.Add(item);
_chart.ContextMenu = _contextMenu;
}
void item_Click(object sender, RoutedEventArgs e)
{
MenuItem m = sender as MenuItem;
if (m != null)
{
_chart.BeginUpdate();
foreach (Band band in _chart.ViewXY.Bands)
{
band.Visible = !band.Visible;
}
_chart.EndUpdate();
}
}
void InitChart()
{
//Disable rendering, strongly recommended before updating chart properties
_chart.BeginUpdate();
//Remember old data
_chart.ViewXY.DropOldSeriesData = false;
//Setup legend box
_chart.ViewXY.LegendBoxes = ViewXY.CreateDefaultLegendBoxes();
_chart.ViewXY.LegendBoxes[0].Visible = true;
_chart.ViewXY.LegendBoxes[0].Position = LegendBoxPositionXY.TopRight;
_chart.ViewXY.LegendBoxes[0].Offset.SetValues(0, 0);
// Configure x-axis.
AxisX xAxis = _chart.ViewXY.XAxes[0];
xAxis.ScrollMode = XAxisScrollMode.None;
xAxis.Title.Visible = false;
xAxis.AutoFormatLabels = false;
xAxis.MajorGrid.Visible = false;
xAxis.MinorDivTickStyle.Visible = false;
xAxis.ValueType = AxisValueType.DateTime;
xAxis.LabelsAngle = 90;
xAxis.LabelsTimeFormat = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
xAxis.AutoDivSpacing = false;
//major div is one day in seconds
xAxis.MajorDiv = 24 * 60 * 60;
string strStockName = "Stockrise Busters, Inc.";
//Chart has one Y axis ready to go. Just set the range
AxisY axisSharePrice = _chart.ViewXY.YAxes[0];
axisSharePrice.SetRange(60, 90);
axisSharePrice.MinorGrid.Visible = false;
axisSharePrice.Title.Text = "USD";
Color color = Colors.Orange;
axisSharePrice.Title.Color = Color.FromArgb(180, color.R, color.G, color.B);
axisSharePrice.MajorGrid.Color = Color.FromArgb(50, 255, 255, 255);
//Add stock series
StockSeries stockSeries = new StockSeries(_chart.ViewXY, _chart.ViewXY.XAxes[0], axisSharePrice);
stockSeries.FillBorder.Style = BorderType.None;
stockSeries.Name = strStockName;
stockSeries.Title.Text = strStockName;
stockSeries.ItemWidth = 9;
stockSeries.StickWidth = 1;
//Put data to stock series. Create data array
StockSeriesData[] data = new StockSeriesData[] {
new StockSeriesData(2010,09,01, 24.35, 24.76, 24.81, 23.82, 269210, 6610451.55),
new StockSeriesData(2010,09,02, 24.85, 24.66, 24.85, 24.53, 216395, 5356858.225),
new StockSeriesData(2010,09,03, 24.80, 24.84, 25.07, 24.60, 164583, 4084950.06),
new StockSeriesData(2010,09,06, 24.85, 25.01, 25.12, 24.84, 118367, 2950889.31),
new StockSeriesData(2010,09,07, 25.00, 24.89, 25.10, 24.60, 210504, 5251022.28),
new StockSeriesData(2010,09,08, 24.87, 25.00, 25.03, 24.61, 151786, 3784783.91),
new StockSeriesData(2010,09,09, 24.97, 25.33, 25.33, 24.86, 142280, 3578342),
new StockSeriesData(2010,09,10, 25.33, 24.92, 25.60, 24.90, 293428, 7372378.5),
new StockSeriesData(2010,09,13, 25.29, 25.42, 25.57, 25.01, 156204, 3960552.42),
new StockSeriesData(2010,09,14, 25.50, 25.16, 25.56, 25.00, 164878, 4176359.74),
new StockSeriesData(2010,09,15, 25.29, 25.45, 25.51, 25.07, 219961, 5580410.57),
new StockSeriesData(2010,09,16, 25.42, 25.30, 25.59, 25.24, 109173, 2768627.28),
new StockSeriesData(2010,09,17, 25.59, 25.90, 26.20, 25.43, 435968, 11223996.16),
new StockSeriesData(2010,09,20, 25.90, 25.93, 26.10, 25.72, 221870, 5749761.05),
new StockSeriesData(2010,09,21, 25.93, 26.31, 26.42, 25.89, 297268, 7764640.16),
new StockSeriesData(2010,09,22, 26.40, 25.96, 26.42, 25.93, 247470, 6478764.6),
new StockSeriesData(2010,09,23, 26.01, 25.84, 26.40, 25.57, 189544, 4913928.2),
new StockSeriesData(2010,09,24, 25.72, 26.56, 26.58, 25.72, 157053, 4105365.42),
new StockSeriesData(2010,09,27, 26.50, 26.97, 27.00, 26.36, 179097, 4788158.295),
new StockSeriesData(2010,09,28, 26.90, 27.44, 27.44, 26.56, 342460, 9304638.2),
new StockSeriesData(2010,09,29, 27.48, 27.24, 27.60, 27.02, 227424, 6222320.64),
new StockSeriesData(2010,09,30, 27.01, 27.43, 27.57, 27.01, 176893, 4815027.46),
new StockSeriesData(2010,10,01, 27.59, 27.11, 27.74, 27.00, 192182, 5256177.7),
new StockSeriesData(2010,10,04, 27.11, 26.90, 27.31, 26.85, 166542, 4497466.71),
new StockSeriesData(2010,10,05, 26.67, 26.64, 26.72, 26.06, 650758, 17345954.49),
new StockSeriesData(2010,10,06, 26.71, 26.40, 26.85, 26.37, 335201, 8901262.555),
new StockSeriesData(2010,10,07, 26.41, 26.55, 26.81, 26.41, 267515, 7083797.2),
new StockSeriesData(2010,10,08, 26.65, 26.32, 26.65, 26.28, 292845, 7755999.825),
new StockSeriesData(2010,10,11, 26.43, 26.68, 26.78, 26.40, 167057, 4436198.635),
new StockSeriesData(2010,10,12, 26.66, 27.41, 27.53, 26.38, 310791, 8402234.685),
new StockSeriesData(2010,10,13, 27.50, 28.70, 28.83, 27.50, 453671, 12748155.1),
new StockSeriesData(2010,10,14, 28.71, 27.77, 28.84, 27.77, 439874, 12422041.76),
new StockSeriesData(2010,10,15, 27.91, 27.46, 28.00, 27.35, 239784, 6638420.04),
new StockSeriesData(2010,10,18, 27.40, 27.43, 27.82, 27.12, 181351, 4971737.665),
new StockSeriesData(2010,10,19, 27.52, 27.22, 27.81, 27.06, 239276, 6548984.12),
new StockSeriesData(2010,10,20, 27.19, 28.02, 28.02, 27.00, 181063, 4998244.115),
new StockSeriesData(2010,10,21, 29.10, 29.78, 30.62, 29.10, 896709, 26399112.96),
new StockSeriesData(2010,10,22, 29.97, 30.05, 30.27, 29.40, 341932, 10261379.32),
new StockSeriesData(2010,10,25, 30.21, 30.49, 30.54, 30.21, 362823, 11011678.05),
new StockSeriesData(2010,10,26, 30.30, 29.85, 30.45, 29.40, 318239, 9571037.925),
new StockSeriesData(2010,10,27, 29.90, 29.30, 30.00, 29.16, 170894, 5058462.4),
new StockSeriesData(2010,10,28, 29.30, 28.48, 29.36, 28.36, 256130, 7399595.7),
new StockSeriesData(2010,10,29, 28.60, 28.67, 29.00, 28.25, 246450, 7057095.75),
};
stockSeries.DataPoints = data;
//Add the created series into list
_chart.ViewXY.StockSeries.Add(stockSeries);
// x-axis stretched half a day at both ends
xAxis.SetRange(
xAxis.DateTimeToAxisValue(stockSeries.DataPoints[0].Date) - 12 * 60 * 60,
xAxis.DateTimeToAxisValue(stockSeries.DataPoints[stockSeries.DataCount - 1].Date) + 12 * 60 * 60);
bool bFitted = false;
//Fit Y range
axisSharePrice.Fit(5.0, out bFitted, true, false);
//Add point line series. Jump from Close values of stock series
PointLineSeries pls = new PointLineSeries(_chart.ViewXY, _chart.ViewXY.XAxes[0], _chart.ViewXY.YAxes[0]);
pls.LineStyle.Color = Color.FromArgb(255, 128, 255, 255);
pls.Title.Text = strStockName;
//set data for point lines series. Only line is set visible, not points.
int pointCount = stockSeries.DataCount;
SeriesPoint[] aLineSeriesPoints = new SeriesPoint[pointCount];
for (int pointIndex = 0; pointIndex < pointCount; pointIndex++)
{
aLineSeriesPoints[pointIndex].X = _chart.ViewXY.XAxes[0].DateTimeToAxisValue(data[pointIndex].Date);
aLineSeriesPoints[pointIndex].Y = data[pointIndex].Close;
}
//Assign the data for the point line series
pls.Points = aLineSeriesPoints;
//Add the created point line series into PointLineSeries list
_chart.ViewXY.PointLineSeries.Add(pls);
//Create bands for Fibonacci sequence
double yMin, yMax;
stockSeries.GetMinMaxFromXRange(out yMin, out yMax, xAxis.Minimum, xAxis.Maximum,false);
for (int i = 1; i < FibonacciLevels.Length; i++)
{
Band band = new Band(_chart.ViewXY, xAxis, axisSharePrice);
band.Binding = AxisBinding.YAxis;
band.Behind = true;
double minToMax = yMax-yMin;
double bandMin, bandMax;
if (i == 1)
bandMin = yMin;
else
bandMin = yMin + FibonacciLevels[i-1] / 100.0 * minToMax;
bandMax = yMin + FibonacciLevels[i] / 100.0 * minToMax;
band.SetValues(bandMin, bandMax);
//make color as step between white dark gray
band.Fill.GradientFill = GradientFill.Solid;
band.Fill.Color = ChartTools.CalcGradient(Color.FromArgb(150,255,255,255), Color.FromArgb(150,40,40,40)
, (double)i / (double)(FibonacciLevels.Length)*100.0);
band.IncludeInAutoFit = false;
band.Title.Text = FibonacciLevels[i].ToString("0.0");
band.Title.Visible = true;
band.Title.Color = Colors.Orange;
band.ShowInLegendBox = false;
band.MouseInteraction = false;
band.BorderColor = band.Fill.Color;
band.BorderWidth = 1.5f;
_chart.ViewXY.Bands.Add(band);
}
//Add event handlers, to help with context menu
_chart.PreviewMouseDown += _chart_PreviewMouseDown;
_chart.PreviewMouseUp += _chart_PreviewMouseUp;
_chart.ViewXY.LegendBoxes[0].Position = LegendBoxPositionXY.SegmentBottomCenter;
//Allow chart rendering
_chart.EndUpdate();
}
void _chart_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Right)
{
Point p = e.GetPosition(_chart);
//Open context menu if panning threshold exceeded
if (Math.Abs(p.X - _mouseDownCoords.X) < _chart.ViewXY.ZoomPanOptions.MousePanThreshold &&
Math.Abs(p.Y - _mouseDownCoords.Y) < _chart.ViewXY.ZoomPanOptions.MousePanThreshold)
{
_contextMenu.Visibility = System.Windows.Visibility.Visible;
}
else
{
_contextMenu.Visibility = System.Windows.Visibility.Hidden;
}
}
}
void _chart_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
_mouseDownCoords = e.GetPosition(_chart);
}
}
}
}
I hope this helps