Fibonacci retracement in trading chart

Need help in implementing some specific function to your LightningChart Ultimate powered application? Post a question and get code snippets from other LightningChart Ultimate community members.

Moderator: Queue Moderators

Post Reply
User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Fibonacci retracement in trading chart

Post by ArctionPasi » Thu Jan 04, 2018 3:51 pm

Hi Developers,

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>
And I'll do other stuff in code:

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); 
            }
        }
    }
}

The application has mouse event handling for showing a context menu, when movement is below panning threshold. The context menu item allows hiding / showing the bands.
Fibonacci levels in back of trading data
Fibonacci levels in back of trading data
Screenshot.png (72.51 KiB) Viewed 13931 times
I hope this helps ;)
LightningChart Support Team, PT

Post Reply