ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Track line finance chart
Posted by Drops2 on May-25-2020 03:46
To the frmfinancedemo.cs file I include function
private void drawChart(WinChartViewer viewer)
trackFinance(c, ((XYChart)c.getChart(0)).getPlotArea().getRightX());
and next add
private void winChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
and
private void trackFinance(MultiChart m, int mouseX)
Unfortunately track line doesn't show up on the chart. What am I doing wrong ?

Code is like this:


namespace CSharpChartExplorer
{
    public partial class FrmFinanceDemo : Form
    {
        public FrmFinanceDemo()
        {
            InitializeComponent();
        }

        /// <summary>
        /// A utility class for adding items to ComboBox
        /// </summary>
        private class ListItem
        {
            string m_key;
            string m_value;

            public ListItem(string key, string val)
            {
                m_key = key;
                m_value = val;
            }

            public string Key
            {
                get { return m_key; }
            }

            public override string ToString()
            {
                return m_value;
            }
        }

        // The ticker symbol, timeStamps, volume, high, low, open and close data
        string tickerKey = "";
        private DateTime[] timeStamps;
        private double[] volData;
        private double[] highData;
        private double[] lowData;
        private double[] openData;
        private double[] closeData;

        // An extra data series to compare with the close data
        private string compareKey = "";
        private double[] compareData = null;

        // The resolution of the data in seconds. 1 day = 86400 seconds.
        private int resolution = 86400;

        // Will set to true at the end of initialization - prevents events from firing before the
        // controls are properly initialized.
        private bool hasFinishedInitialization = false;

        /// <summary>
        /// Form Load event handler - initialize the form
        /// </summary>
        private void FrmFinanceDemo_Load(object sender, System.EventArgs e)
        {
            hasFinishedInitialization = false;


            timeRange.SelectedIndex = timeRange.Items.Add(new ListItem("180", "6 months"));
            timeRange.Items.Add(new ListItem("360", "1 year"));
            timeRange.Items.Add(new ListItem("720", "2 years"));

            chartSize.Items.Add(new ListItem("L", "Large"));
            chartSize.SelectedIndex = chartSize.Items.Add(new ListItem("H", "Huge"));


            chartType.Items.Add(new ListItem("None", "None"));
            chartType.SelectedIndex = chartType.Items.Add(new ListItem("CandleStick", "CandleStick"));
            chartType.Items.Add(new ListItem("Close", "Closing Price"));


            priceBand.Items.Add(new ListItem("None", "None"));
            priceBand.SelectedIndex = priceBand.Items.Add(new ListItem("BB", "Bollinger Band"));


            avgType1.Items.Add(new ListItem("None", "None"));
            avgType1.SelectedIndex = avgType1.Items.Add(new ListItem("SMA", "Simple"));
            avgType1.Items.Add(new ListItem("EMA", "Exponential"));


            avgType2.Items.Add(new ListItem("None", "None"));
            avgType2.SelectedIndex = avgType2.Items.Add(new ListItem("SMA", "Simple"));
            avgType2.Items.Add(new ListItem("EMA", "Exponential"));


            ListItem[] indicators =
            {
                new ListItem("None", "None"),
                new ListItem("AccDist", "Accumulation/Distribution"),
                new ListItem("AroonOsc", "Aroon Oscillator"),

            };

            indicator1.Items.AddRange(indicators);
            indicator2.Items.AddRange(indicators);
            indicator3.Items.AddRange(indicators);
            indicator4.Items.AddRange(indicators);

            for (int i = 0; i < indicators.Length; ++i)
            {
                if (indicators[i].Key == "RSI")
                    indicator1.SelectedIndex = i;
                else if (indicators[i].Key == "MACD")
                    indicator2.SelectedIndex = i;
            }
            indicator3.SelectedIndex = 0;
            indicator4.SelectedIndex = 0;

            hasFinishedInitialization = true;
            drawChart(winChartViewer1);
        }


        /// <summary>
        /// Get daily data series for timeStamps, highData, lowData, openData, closeData
        /// and volData.
        /// </summary>
        /// <param name="ticker">The ticker symbol for the data series.</param>
        /// <param name="startDate">The starting date/time for the data series.</param>
        /// <param name="endDate">The ending date/time for the data series.</param>
        ///


        private void getDailyData(string ticker, DateTime startDate, DateTime endDate)
        {


            // We use these three SQLite objects:
            SQLiteConnection sqlite_conn;
            sqlite_conn = CreateConnection();
            ReadData(sqlite_conn);


            SQLiteConnection CreateConnection()
        {


            // Create a new database connection:
            sqlite_conn = new SQLiteConnection("Data Source= MT4.sqlite; Version = 3; New = false; Compress = True; ");
           // Open the connection:
         try
            {
                sqlite_conn.Open();
            }
            catch (Exception ex)
            {
                   // MessageBox("sqlite brak polaczenia");
            }
                //MessageBox("sqlite jest polaczenie");
                return sqlite_conn;
        }



            void ReadData(SQLiteConnection conn)
        {
SQLiteDataReader sqlite_datareader;
                SQLiteCommand sqlite_cmd;
                sqlite_cmd = conn.CreateCommand();

                sqlite_cmd.CommandText = "SELECT  timestamp, open, high, low, close, volume FROM EURUSD";


                DBTable table = new DBTable(sqlite_cmd.ExecuteReader());

                conn.Close();


                //Now get the data into arrays
                string[] MyString = table.getColAsString(0);

                timeStamps = new DateTime[MyString.Length];
                for (int i = 0; i < MyString.Length; ++i)
                {
                    string s = MyString[i];

                    // The following is how your text string is to be interpreted
                    int mm = int.Parse(s.Substring(0, 2));
                    int dd = int.Parse(s.Substring(2, 2));
                    int yyyy = int.Parse(s.Substring(4, 4));
                    int hh = int.Parse(s.Substring(9, 2));
                    int nn = int.Parse(s.Substring(12, 2));
                    int ss = 0;

                    timeStamps[i] = new DateTime(yyyy, mm, dd, hh, nn, ss);
                }

                openData = table.getCol(1);
                highData = table.getCol(2);
                lowData = table.getCol(3);
                closeData = table.getCol(4);
                volData = table.getCol(5);

            }
        }




        /// <summary>
        /// In this sample code, the chart updates when the user selection changes. You may
        /// modify the code to update the data and chart periodically for real time charts.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///
                //
        // Draw track cursor when mouse is moving over plotarea
        //


        private void selectionChanged(object sender, System.EventArgs e)
        {

            if (hasFinishedInitialization)
                drawChart(winChartViewer1);
        }

        ///
        /// For the ticker symbols, the chart will update when the user enters a new symbol,
        /// and then press the enter button or leave the text box.
        ///

        private void tickerSymbol_Leave(object sender, System.EventArgs e)
        {
            // User leave ticker symbol text box - redraw chart if symbol has changed
            if (tickerSymbol.Text != tickerKey)
                drawChart(winChartViewer1);
        }

        private void tickerSymbol_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            // User press enter key - same action as leaving the text box.
            if (e.KeyChar == 'r')
                tickerSymbol_Leave(sender, e);
        }

        private void compareWith_Leave(object sender, System.EventArgs e)
        {
            // User leave compare symbol text box - redraw chart if symbol has changed
            if (compareWith.Text != compareKey)
                drawChart(winChartViewer1);
        }

        private void compareWith_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            // User press enter key - same action as leaving the text box.
            if (e.KeyChar == 'r')
                compareWith_Leave(sender, e);
        }

        /// <summary>
        /// Draw the chart according to user selection and display it in the WinChartViewer.
        /// </summary>
        /// <param name="viewer">The WinChartViewer object to display the chart.</param>
        private void drawChart(WinChartViewer viewer)
        {
            // Use InvariantCulture to draw the chart. This ensures the chart will look the
            // same on any computer.
            System.Threading.Thread.CurrentThread.CurrentCulture =
                      System.Globalization.CultureInfo.InvariantCulture;

            // In this demo, we just assume we plot up to the latest time. So endDate is now.
            DateTime endDate = DateTime.Now;

            // If the trading day has not yet started (before 9:30am), or if the end date is
            // on on Sat or Sun, we set the end date to 4:00pm of the last trading day
            while ((endDate.TimeOfDay.CompareTo(new TimeSpan(9, 30, 0)) < 0) || (
                endDate.DayOfWeek == DayOfWeek.Sunday) || (endDate.DayOfWeek ==
                DayOfWeek.Saturday))
            {
                endDate = endDate.Date.AddDays(-1).Add(new TimeSpan(16, 0, 0));
            }

            // The duration selected by the user
            int durationInDays = int.Parse(((ListItem)timeRange.SelectedItem).Key);

            // Compute the start date by subtracting the duration from the end date.
            DateTime startDate;
            if (durationInDays >= 30)
            {
                // More or equal to 30 days - so we use months as the unit
                startDate = new DateTime(endDate.Year, endDate.Month, 1).AddMonths(
                    -durationInDays / 30);
            }
            else
            {
                // Less than 30 days - use day as the unit. Note that we use trading days
                // below. For less than 30 days, the starting point of the axis is always at
                // the start of the day.
                startDate = endDate.Date;
                for (int i = 1; i < durationInDays; ++i)
                    startDate = startDate.AddDays(
                        (startDate.DayOfWeek == DayOfWeek.Monday) ? -3 : -1);
            }

            // The first moving average period selected by the user.
            int avgPeriod1;
            try { avgPeriod1 = int.Parse(movAvg1.Text); }
            catch { avgPeriod1 = 0; }
            avgPeriod1 = Math.Max(0, Math.Min(300, avgPeriod1));

            // The second moving average period selected by the user.
            int avgPeriod2;
            try { avgPeriod2 = int.Parse(movAvg2.Text); }
            catch { avgPeriod2 = 0; }
            avgPeriod2 = Math.Max(0, Math.Min(300, avgPeriod2));

            // We need extra leading data points in order to compute moving averages.
            int extraPoints = Math.Max(20, Math.Max(avgPeriod1, avgPeriod2));

            // Get the data series to compare with, if any.
            compareKey = compareWith.Text.Trim();
            compareData = null;
            if (getData(compareKey, startDate, endDate, durationInDays, extraPoints))
                compareData = closeData;

            // The data series we want to get.
            tickerKey = tickerSymbol.Text.Trim();
            if (!getData(tickerKey, startDate, endDate, durationInDays, extraPoints))
            {
                errMsg(viewer, "Please enter a valid ticker symbol");
                return;
            }

            // We now confirm the actual number of extra points (data points that are before
            // the start date) as inferred using actual data from the database.
            extraPoints = timeStamps.Length;
            for (int i = 0; i < timeStamps.Length; ++i)
            {
                if (timeStamps[i] >= startDate)
                {
                    extraPoints = i;
                    break;
                }
            }

            // Check if there is any valid data
            if (extraPoints >= timeStamps.Length)
            {
                // No data - just display the no data message.
                errMsg(viewer, "No data available for the specified time period");
                return;
            }

            // In some finance chart presentation style, even if the data for the latest day
            // is not fully available, the axis for the entire day will still be drawn, where
            // no data will appear near the end of the axis.
            if (resolution < 86400)
            {
                // Add extra points to the axis until it reaches the end of the day. The end
                // of day is assumed to be 4:00pm (it depends on the stock exchange).
                DateTime lastTime = timeStamps[timeStamps.Length - 1];
                int extraTrailingPoints = (int)(new TimeSpan(16, 0, 0).Subtract(
                    lastTime.TimeOfDay).TotalSeconds / resolution);

                if (extraTrailingPoints > 0)
                {
                    DateTime[] extendedTimeStamps = new DateTime[timeStamps.Length +
                        extraTrailingPoints];
                    Array.Copy(timeStamps, 0, extendedTimeStamps, 0, timeStamps.Length);
                    for (int i = 0; i < extraTrailingPoints; ++i)
                        extendedTimeStamps[i + timeStamps.Length] = lastTime.AddSeconds(
                            resolution * i);
                    timeStamps = extendedTimeStamps;
                }
            }

            //
            // At this stage, all data is available. We can draw the chart as according to
            // user input.
            //

            //
            // Determine the chart size. In this demo, user can select 4 different chart
            // sizes. Default is the large chart size.
            //
            int width = 780;
            int mainHeight = 255;
            int indicatorHeight = 80;

            string selectedSize = ((ListItem)chartSize.SelectedItem).Key;
            if (selectedSize == "S")
            {
                // Small chart size
                width = 450;
                mainHeight = 160;
                indicatorHeight = 60;
            }
            else if (selectedSize == "M")
            {
                // Medium chart size
                width = 620;
                mainHeight = 215;
                indicatorHeight = 70;
            }
            else if (selectedSize == "H")
            {
                // Huge chart size
                width = 1000;
                mainHeight = 320;
                indicatorHeight = 90;
            }

            // Create the chart object using the selected size
            FinanceChart m = new FinanceChart(width);

            // Set the data into the chart object
            m.setData(timeStamps, highData, lowData, openData, closeData, volData, extraPoints);


            //
            // We configure the title of the chart. In this demo chart design, we put the
            // company name as the top line of the title with left alignment.
            //
            m.addPlotAreaTitle(Chart.TopLeft, tickerKey);

            // We displays the current date as well as the data resolution on the next line.
            string resolutionText = "";
            if (resolution == 30 * 86400)
                resolutionText = "Monthly";
            else if (resolution == 7 * 86400)
                resolutionText = "Weekly";
            else if (resolution == 86400)
                resolutionText = "Daily";
            else if (resolution == 900)
                resolutionText = "15-min";

            m.addPlotAreaTitle(Chart.BottomLeft, "<*font=Arial,size=8*>" + m.formatValue(
                DateTime.Now, "mmm dd, yyyy") + " - " + resolutionText + " chart");

            // A copyright message at the bottom left corner the title area
            //     m.addPlotAreaTitle(Chart.BottomRight,"<*font=arial.ttf,size=8*>(c) Black Fox");

            //
            // Add the first techical indicator according. In this demo, we draw the first
            // indicator on top of the main chart.
            //
            addIndicator(m, ((ListItem)indicator1.SelectedItem).Key, indicatorHeight);

            //
            // Add the main chart
            //
            m.addMainChart(mainHeight);

            //
            // Set log or linear scale according to user preference
            //
            m.setLogScale(logScale.Checked);

            //
            // Set axis labels to show data values or percentage change to user preference
            //
            if (percentageScale.Checked)
                m.setPercentageAxis();

            //
            // Draw any price line the user has selected
            //
            string mainType = ((ListItem)chartType.SelectedItem).Key;
            if (mainType == "Close")
                m.addCloseLine(0x000040);
            else if (mainType == "TP")
                m.addTypicalPrice(0x000040);
            else if (mainType == "WC")
                m.addWeightedClose(0x000040);
            else if (mainType == "Median")
                m.addMedianPrice(0x000040);

            //
            // Add comparison line if there is data for comparison
            //
            if ((compareData != null) && (compareData.Length > extraPoints))
                m.addComparison(compareData, 0x0000ff, compareKey);

            //
            // Add moving average lines.
            //
            addMovingAvg(m, ((ListItem)avgType1.SelectedItem).Key, avgPeriod1, 0x663300);
            addMovingAvg(m, ((ListItem)avgType2.SelectedItem).Key, avgPeriod2, 0x9900ff);

            // Add a 20 period EMA to the main chart
            LineLayer layer = m.addExpMovingAvg(300, 0x9900ff);

            //
            // Draw candlesticks or OHLC symbols if the user has selected them.
            //
            if (mainType == "CandleStick")
                m.addCandleStick(0x33ff33, 0xff3333);
            else if (mainType == "OHLC")
                m.addHLOC(0x008800, 0xcc0000);

            //
            // Add parabolic SAR if necessary
            //
            if (parabolicSAR.Checked)
                m.addParabolicSAR(0.02, 0.02, 0.2, Chart.DiamondShape, 5, 0x008800, 0x000000);

            //
            // Add price band/channel/envelop to the chart according to user selection
            //
            string selectedBand = ((ListItem)priceBand.SelectedItem).Key;
            if (selectedBand == "BB")
                m.addBollingerBand(20, 2, 0x9999ff, unchecked((int)(0xc06666ff)));
            else if (selectedBand == "DC")
                m.addDonchianChannel(20, 0x9999ff, unchecked((int)(0xc06666ff)));
            else if (selectedBand == "Envelop")
                m.addEnvelop(20, 0.1, 0x9999ff, unchecked((int)(0xc06666ff)));

            //
            // Add volume bars to the main chart if necessary
            //
            if (volumeBars.Checked)
                m.addVolBars(indicatorHeight, 0x99ff99, 0xff9999, 0xc0c0c0);

            //
            // Add additional indicators as according to user selection.
            //
            addIndicator(m, ((ListItem)indicator2.SelectedItem).Key, indicatorHeight);
            addIndicator(m, ((ListItem)indicator3.SelectedItem).Key, indicatorHeight);
            addIndicator(m, ((ListItem)indicator4.SelectedItem).Key, indicatorHeight);

            // Include track line with legend for the latest data values
            trackFinance(m, ((XYChart)m.getChart(0)).getPlotArea().getRightX());

            //
            // output the chart
            //
            viewer.Chart = m;

            //
            // tooltips for the chart
            //
            viewer.ImageMap = m.getHTMLImageMap("", "", "title='" + m.getToolTipDateFormat() + " {value|P}'");


        }


        //
        // Draw track cursor when mouse is moving over plotarea
        //
        private void winChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
        {
            WinChartViewer viewer = (WinChartViewer)sender;
            trackFinance((MultiChart)viewer.Chart, viewer.PlotAreaMouseX);
            viewer.updateDisplay();
        }

        //
        // Draw finance chart track line with legend
        //
        private void trackFinance(MultiChart m, int mouseX)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = m.initDynamicLayer();

            // It is possible for a FinanceChart to be empty, so we need to check for it.
            if (m.getChartCount() == 0)
            {
                return;
            }

            // Get the data x-value that is nearest to the mouse
            int xValue = (int)(((XYChart)m.getChart(0)).getNearestXValue(mouseX));

            // Iterate the XY charts (main price chart and indicator charts) in the FinanceChart
            XYChart c = null;
            for (int i = 0; i < m.getChartCount(); ++i)
            {
                c = (XYChart)m.getChart(i);

                // Variables to hold the legend entries
                string ohlcLegend = "";
                ArrayList legendEntries = new ArrayList();

                // Iterate through all layers to find the highest data point
                for (int j = 0; j < c.getLayerCount(); ++j)
                {
                    Layer layer = c.getLayerByZ(j);
                    int xIndex = layer.getXIndexOf(xValue);
                    int dataSetCount = layer.getDataSetCount();

                    // In a FinanceChart, only layers showing OHLC data can have 4 data sets
                    if (dataSetCount == 4)
                    {
                        double highValue = layer.getDataSet(0).getValue(xIndex);
                        double lowValue = layer.getDataSet(1).getValue(xIndex);
                        double openValue = layer.getDataSet(2).getValue(xIndex);
                        double closeValue = layer.getDataSet(3).getValue(xIndex);

                        if (closeValue != Chart.NoValue)
                        {
                            // Build the OHLC legend
                            ohlcLegend = "Open: " + c.formatValue(openValue, "{value|P4}") + ", High: " +
                                c.formatValue(highValue, "{value|P4}") + ", Low: " + c.formatValue(lowValue,
                                "{value|P4}") + ", Close: " + c.formatValue(closeValue, "{value|P4}");

                            // We also draw an upward or downward triangle for up and down days and the %
                            // change
                            double lastCloseValue = layer.getDataSet(3).getValue(xIndex - 1);
                            if (lastCloseValue != Chart.NoValue)
                            {
                                double change = closeValue - lastCloseValue;
                                double percent = change * 100 / closeValue;
                                string symbol = ((change >= 0) ?
                                    "<*font,color=008800*><*img=@triangle,width=8,color=008800*>" :
                                    "<*font,color=CC0000*><*img=@invertedtriangle,width=8,color=CC0000*>");

                                ohlcLegend = ohlcLegend + "  " + symbol + " " + c.formatValue(change,
                                    "{value|P4}") + " (" + c.formatValue(percent, "{value|2}") + "%)<*/font*>"
                                    ;
                            }

                            // Use a <*block*> to make sure the line does not wrap within the legend entry
                            ohlcLegend = "<*block*>" + ohlcLegend + "      <*/*>";
                        }
                    }
                    else
                    {
                        // Iterate through all the data sets in the layer
                        for (int k = 0; k < layer.getDataSetCount(); ++k)
                        {
                            ChartDirector.DataSet dataSet = layer.getDataSetByZ(k);

                            string name = dataSet.getDataName();
                            double value = dataSet.getValue(xIndex);
                            if ((!string.IsNullOrEmpty(name)) && (value != Chart.NoValue))
                            {

                                // In a FinanceChart, the data set name consists of the indicator name and its
                                // latest value. It is like "Vol: 123M" or "RSI (14): 55.34". As we are
                                // generating the values dynamically, we need to extract the indictor name
                                // out, and also the volume unit (if any).

                                // The unit character, if any, is the last character and must not be a digit.
                                string unitChar = name.Substring(name.Length - 1);
                                if (unitChar.CompareTo("0") >= 0 && unitChar.CompareTo("9") <= 0)
                                {
                                    unitChar = "";
                                }

                                // The indicator name is the part of the name up to the colon character.
                                int delimiterPosition = name.IndexOf(":");
                                if (delimiterPosition != -1)
                                {
                                    name = name.Substring(0, delimiterPosition);
                                }

                                // In a FinanceChart, if there are two data sets, it must be representing a
                                // range.
                                if (dataSetCount == 2)
                                {
                                    // We show both values in the range in a single legend entry
                                    value = layer.getDataSet(0).getValue(xIndex);
                                    double value2 = layer.getDataSet(1).getValue(xIndex);
                                    name = name + ": " + c.formatValue(Math.Min(value, value2), "{value|P3}")
                                         + " - " + c.formatValue(Math.Max(value, value2), "{value|P3}");
                                }
                                else
                                {
                                    // In a FinanceChart, only the layer for volume bars has 3 data sets for
                                    // up/down/flat days
                                    if (dataSetCount == 3)
                                    {
                                        // The actual volume is the sum of the 3 data sets.
                                        value = layer.getDataSet(0).getValue(xIndex) + layer.getDataSet(1
                                            ).getValue(xIndex) + layer.getDataSet(2).getValue(xIndex);
                                    }

                                    // Create the legend entry
                                    name = name + ": " + c.formatValue(value, "{value|P3}") + unitChar;
                                }

                                // Build the legend entry, consist of a colored square box and the name (with
                                // the data value in it).
                                legendEntries.Add("<*block*><*img=@square,width=8,edgeColor=000000,color=" +
                                    dataSet.getDataColor().ToString("x") + "*> " + name + "<*/*>");
                            }
                        }
                    }
                }

                // Get the plot area position relative to the entire FinanceChart
                PlotArea plotArea = c.getPlotArea();
                int plotAreaLeftX = plotArea.getLeftX() + c.getAbsOffsetX();
                int plotAreaTopY = plotArea.getTopY() + c.getAbsOffsetY();

                // The legend is formed by concatenating the legend entries.
                legendEntries.Reverse();
                string legendText = String.Join("      ", (string[])legendEntries.ToArray(typeof(string)));

                // Add the date and the ohlcLegend (if any) at the beginning of the legend
                legendText = "<*block,valign=top,maxWidth=" + (plotArea.getWidth() - 5) +
                    "*><*font=Arial Bold*>[" + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") +
                    "]<*/font*>      " + ohlcLegend + legendText;

                // Draw a vertical track line at the x-position
                d.vline(plotAreaTopY, plotAreaTopY + plotArea.getHeight(), c.getXCoor(xValue) +
                    c.getAbsOffsetX(), d.dashLineColor(0x000000, 0x0101));

                // Display the legend on the top of the plot area
                TTFText t = d.text(legendText, "Arial", 8);
                t.draw(plotAreaLeftX + 5, plotAreaTopY + 3, 0x000000, Chart.TopLeft);
            }
        }
    }
}

  Re: Track line finance chart
Posted by Peter Kwan on May-25-2020 16:45
Hi Drops2,

Would you mind to clarify how do you "add" winChartViewer1_MouseMovePlotArea to your code? The winChartViewer1_MouseMovePlotArea is an event handler for the MouseMovePlotArea event. Are you adding it as an event handler, or do you just copy and paste the code?

I have tried myself with the original sample code, and it works in my case. I added trackFinance to the code, and added winChartViewer1_MouseMovePlotArea as the event handler for the MouseMovePlotArea event, and it works normally.

Regards
Peter Kwan

  Re: Track line finance chart
Posted by Drops2 on May-26-2020 03:20
I just copy and paste the code. When I add as an event handler work good. Thank you Peter for help.