Stock chart in c#

Jack Herer 105 Reputation points
2023-04-25T13:24:41.2833333+00:00
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FinanceChart
{
    public partial class MainWindow : Form
    {
        private DataLoader dataLoader { get; set; }

        private List<DataModel> data = new List<DataModel>();
        private List<DataModel> dataFiltered = new List<DataModel>();
        private List<DataModel> dataNormalized = new List<DataModel>();

        private PointF mousePoint { get; set; }
        private int dateBorder { get; set; }
        private int costBorder { get; set; }
        private float volumeHeight { get; set; }

        private int heightConst = 16;
        private int widthConst = 39;

        private DateTime oldest { get; set; }
        private DateTime newest { get; set; }

        public MainWindow()
        {
            InitializeComponent();


            dateBorder = 100;
            costBorder = 130;
            PictureBox.Height = this.Height + heightConst;
            PictureBox.Width = this.Width + widthConst;
            volumeHeight = PictureBox.Height / 5;

            dataLoader = new DataLoader();
            data = dataLoader.LoadData();
            dataFiltered = data;

            oldest = data.Aggregate((first, other) => first.date < other.date ? first : other).date;
            newest = data.Aggregate((first, other) => first.date > other.date ? first : other).date;
        }

        private void PictureBox_Paint(object sender, PaintEventArgs e)
        {
            DrawBackground(e);
            NormalizeData();
            DrawCursor(e);
            DrawGraph(e);
            DrawBorder(e);
        }

        private void PictureBox_Resize(object sender, EventArgs e)
        {
            PictureBox.Invalidate();
        }


        private void Form1_Resize(object sender, EventArgs e)
        {
            PictureBox.Height = this.Height + heightConst;
            PictureBox.Width = this.Width + widthConst;
            volumeHeight = PictureBox.Height / 5;
        }

        private void DrawBackground(PaintEventArgs e)
        {
            int height = this.Height;
            Color color = Color.FromArgb(60, Color.Gray);
            for (int i = 100; i <= this.Width; i = i + 200)
            {
                Rectangle rectangle = new Rectangle();
                rectangle.X = i;
                rectangle.Y = 0;
                rectangle.Height = height;
                rectangle.Width = 100;
                e.Graphics.FillRectangle(new SolidBrush(color), rectangle);
            }
        }

        private void NormalizeData()
        {
            dataNormalized.Clear();
            int grafWidth = PictureBox.Width - costBorder;
            int grafHeight = PictureBox.Height - dateBorder;
            int itemsPerPixel = (int)Math.Ceiling(Convert.ToDecimal(dataFiltered.Count / grafWidth));
            if (itemsPerPixel == 0) itemsPerPixel = 1;
            for (int i = 0; i < dataFiltered.Count; i = i + itemsPerPixel)
            {
                dataNormalized.Add(dataFiltered[i]);
            }
            dataNormalized.Add(dataFiltered[dataFiltered.Count - 1]);


            float highestValue = dataNormalized.Aggregate((first, other) => first.close < other.close ? first : other).close;
            float lowestValue = dataNormalized.Aggregate((first, other) => first.close > other.close ? first : other).close;
            for (int i = 0; i < dataNormalized.Count; i++)
            {
                PointF temp = new PointF((float)((float)i / (float)dataNormalized.Count * grafWidth), (((dataNormalized[i].close - lowestValue) / (highestValue - lowestValue)) * (grafHeight - volumeHeight)));
                dataNormalized[i].grafPoint = temp;
            }


            float highestVolume = dataNormalized.Aggregate((first, other) => first.volume < other.volume ? first : other).volume;
            float lowestVolume = dataNormalized.Aggregate((first, other) => first.volume > other.volume ? first : other).volume;
            for (int i = 0; i < dataNormalized.Count; i++)
            {
                PointF temp = new PointF(dataNormalized[i].grafPoint.X, ((dataNormalized[i].volume - lowestVolume) / (highestVolume - lowestVolume) * volumeHeight) + grafHeight - volumeHeight);
                dataNormalized[i].volumePoint = temp;
            }
        }

        private void DrawGraph(PaintEventArgs e)
        {
            for (int i = 0; i < dataNormalized.Count; i++)
            {
                // graph
                if (i != dataNormalized.Count - 1)
                {
                    DrawLine(e, dataNormalized[i], dataNormalized[i + 1]);
                }

                // volume
                if (i == 0)
                {
                    DrawVolume(e, dataNormalized[i], true);
                }
                else if (dataNormalized[i - 1].close < dataNormalized[i].close)
                {
                    DrawVolume(e, dataNormalized[i], true);
                }
                else
                {
                    DrawVolume(e, dataNormalized[i], false);
                }
            }
        }

        private void DrawBorder(PaintEventArgs e)
        {
            Pen pen = new Pen(Brushes.Black, 2);
            Rectangle rectangle = new Rectangle(new Point(0, 0), new Size(PictureBox.Width - this.costBorder, PictureBox.Height - this.dateBorder));

            e.Graphics.DrawRectangle(pen, rectangle);
        }

        
        private void DrawVolume(PaintEventArgs e, DataModel _data, bool closeHigh)
        {
            Pen pen = new Pen(Color.FromArgb(100, Color.Green), 2);

            if (closeHigh == false)
            {
                pen = new Pen(Color.FromArgb(100, Color.Red), 2);
            }

            e.Graphics.DrawLine(pen, new PointF(_data.volumePoint.X, PictureBox.Height - dateBorder), _data.volumePoint);
        }

        
        private void DrawLine(PaintEventArgs e, DataModel first, DataModel second)
        {
            Pen pen = new Pen(Color.Blue, 2);
            e.Graphics.DrawLine(pen, first.grafPoint, second.grafPoint);
        }

        private void DrawCursor(PaintEventArgs e)
        {
            Pen pen = new Pen(Brushes.Gray);
            float[] dashValues = { 5, 5 };
            pen.DashPattern = dashValues;

            
            DataModel focusedObject = dataNormalized.Aggregate((x, y) => Math.Abs(x.grafPoint.X - mousePoint.X) < Math.Abs(y.grafPoint.X - mousePoint.X) ? x : y);
            focusedObject.focused = true;

            e.Graphics.DrawLine(pen, new PointF(focusedObject.grafPoint.X, 0), new PointF(focusedObject.grafPoint.X, PictureBox.Height - this.dateBorder + 5));
            e.Graphics.DrawLine(pen, new PointF(0, focusedObject.grafPoint.Y), new PointF(PictureBox.Width - this.costBorder + 5, focusedObject.grafPoint.Y));

            Font font = new Font(FontFamily.GenericSansSerif, 7, FontStyle.Bold);
            //date
            e.Graphics.DrawString(focusedObject.date.ToString("dd/MM/yyyy"), font, Brushes.Black, new PointF(focusedObject.grafPoint.X, PictureBox.Height - this.dateBorder + 5));

            //volume
            e.Graphics.DrawString(focusedObject.volume.ToString(), font, Brushes.Black, new PointF(focusedObject.grafPoint.X, PictureBox.Height - this.dateBorder - this.volumeHeight / 2));

            //close
            e.Graphics.DrawString(focusedObject.close.ToString(), font, Brushes.Black, new PointF(PictureBox.Width - this.costBorder + 5, focusedObject.grafPoint.Y));

            
            label1.Text = "Open: " + focusedObject.open;
            label2.Text = "High: " + focusedObject.high;
            label3.Text = "Low: " + focusedObject.low;
            label4.Text = "Close: " + focusedObject.close;

            
            string temp;
            if ((float)focusedObject.volume / 1000000 >= 1)
            {
                temp = (float)focusedObject.volume / 1000000 + " Mil.";
            }
            else if ((float)focusedObject.volume / 1000 >= 1)
            {
                temp = (float)focusedObject.volume / 1000 + " Tis.";
            }
            else
            {
                temp = focusedObject.volume.ToString();
            }
            label5.Text = "Volume " + temp;
            label8.Text = "% Change: " + Math.Round(((focusedObject.close - focusedObject.open) / focusedObject.open * 100), 2) + "%";
        }

        
        private void SetDataBetweenDates(DateTime dateTime1, DateTime dateTime2)
        {
            dataFiltered = data.Where(x => x.date > dateTime1 && x.date < dateTime2).ToList();
        }

        
        private void MainWindow_Load(object sender, EventArgs e)
        {
            dateTimePicker1.Value = oldest;
            dateTimePicker2.Value = newest;
            this.Activate();
        }

        
        private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
        {
            if (dateTimePicker1.Value <= oldest)
            {
                dateTimePicker1.Value = oldest;
            }
            else if (dateTimePicker1.Value >= newest)
            {
                dateTimePicker1.Value = newest;
            }
            else
            {
                SetDataBetweenDates(dateTimePicker1.Value, dateTimePicker2.Value);
                
                PictureBox.Invalidate();
            }
        }

        
        private void dateTimePicker2_ValueChanged(object sender, EventArgs e)
        {
            if (dateTimePicker1.Value <= oldest)
            {
                dateTimePicker1.Value = oldest;
            }
            else if (dateTimePicker1.Value >= newest)
            {
                dateTimePicker1.Value = newest;
            }
            else
            {
                SetDataBetweenDates(dateTimePicker1.Value, dateTimePicker2.Value);
                PictureBox.Invalidate();
            }
        }

        
        private void button1_Click(object sender, EventArgs e)
        {
            dataFiltered = data;
            PictureBox.Invalidate();
        }

        
        private void PictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            mousePoint = e.Location;
            PictureBox.Invalidate();
        }
    }
}

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,525 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,483 questions
{count} votes