none
C# Объясните, как убрать в chart пустые значения на графике RRS feed

  • Вопрос

  • Рисую с помощью chart график свечей, данные берутся из файла. 

    Как убрать на графике пустые значения(в файле данных в эти даты нет)?

    И все-таки есть ли возможность сделать автомасштабирование при увеличении графика, без применения костыля с циклом и привязыванием горизонтальному скролу, может есть какая специальная функция для этого?


    Сам код. В англоязычном форуме, мне сказали, что возможно не правильно считываю с файла.

    Но, так как для меня эта тема нова, собственно и сам C#, то просьба поправить в коде, что не так.

    Перерыл весь интернет и не нашел хорошей справки по компоненте Chart. Есть примеры, но там мало понятно для чайника.

    using System;
    using System.Windows.Forms;
    using System.Windows.Forms.DataVisualization.Charting;
    using System.IO;
    
    namespace stock3
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                this.chart1.AxisViewChanged += chart1_AxisViewChanged;
            }              
    
            private void CandleStick_Load(object sender, EventArgs e)
            {
                CHART();
            }
    
            public void CHART()
            {
                string path = @"C:\...\#S-PG1440.csv";//файл для считывания котировок
                int count = System.IO.File.ReadAllLines(@"C:\...\#S-PG1440.csv").Length;//размер массива
                int i = 0;
                DateTime[] nums = new DateTime[count];
                double[,] mass = new double[count, 4];
                
                try
                {
                    using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
                    {
                        string line, b;
                        double Open, High, Low, Close;
                        while ((line = sr.ReadLine()) != null)//цикл заполнения котировками массивов для отрисовки свечей
                        {
                            String data = line;
                            String substring = data.Substring(0, 10);
                            DateTime Data = DateTime.Parse(substring);
                            nums[i] = Data;//время 
    
                            String open = line;
                            String substring1 = open.Substring(17, 5);
                            b = substring1.Replace('.', ',');
                            Open = double.Parse(b);
                            mass[i, 0] = Open;//цена открытия
    
                            String high = line;
                            String substring2 = high.Substring(23, 5);
                            b = substring2.Replace('.', ',');
                            High = double.Parse(b);
                            mass[i, 1] = High;//максимум
    
                            String low = line;
                            String substring3 = low.Substring(29, 5);
                            b = substring3.Replace('.', ',');
                            Low = double.Parse(b);
                            mass[i, 2] = Low;//минимум
    
                            String close = line;
                            String substring4 = close.Substring(35, 5);
                            b = substring4.Replace('.', ',');
                            Close = double.Parse(b);
                            mass[i, 3] = Close;//цена закрытия
                            i = i + 1;
    
                        }
                        sr.Close();//закрываем файл
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
    
                chart1.Series.Clear();
    
                Series price = new Series("price"); 
                chart1.Series.Add(price);
    
                chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
                chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
                chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
                chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = false; 
    
                chart1.ChartAreas[0].AxisY.IsStartedFromZero = false;
    
                chart1.Series["price"].ChartType = SeriesChartType.Candlestick;
                chart1.Series["price"]["OpenCloseStyle"] = "Candlestick";
                chart1.Series["price"]["ShowOpenClose"] = "Close";
                chart1.Series["price"]["PointWidth"] = "1.0";
                chart1.Series["price"]["PriceUpColor"] = "Blue"; //цвет растущей свечи
                chart1.Series["price"]["PriceDownColor"] = "Red";//цвет падающей свечи
                chart1.Series["price"]["MaxPixelPointWidth"] = "2.5";
    
    
                for (i = 0; i < count-1; i++)
                {
                    chart1.Series["price"].Points.AddXY(nums[i], mass[i, 1], mass[i, 2], mass[i, 0], mass[i, 3]);//дата,максимум, минимум, открытие, закрытие
                }
            }
    
            private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
            {
                double diapazon = 0.0;
                double viewMin = chart1.ChartAreas[0].AxisX.ScaleView.ViewMinimum;
                double viewMax = chart1.ChartAreas[0].AxisX.ScaleView.ViewMaximum;
    
                DataPoint min = new DataPoint(0, double.MaxValue);
                DataPoint max = new DataPoint(0, double.MinValue);
    
                DataPointCollection points = chart1.Series["price"].Points;
    
                foreach (var dp in points)
                {
                    if (dp.XValue >= viewMin && dp.XValue <= viewMax)
                    {
                        if (dp.YValues[0] > max.YValues[0]) max = dp;
                        if (dp.YValues[0] < min.YValues[0]) min = dp;
    
                    }
                }
                diapazon = ((max.YValues[0] - min.YValues[1])/100.0)*35.0;
    
                chart1.ChartAreas[0].AxisY.Minimum = min.YValues[0];
                chart1.ChartAreas[0].AxisY.Maximum = max.YValues[0];
               
            }
    
            private void chart1_Click(object sender, EventArgs e)
            {
    
            }
    
    
        }
    }



    • Изменено Qtrade1 27 ноября 2017 г. 16:56
    26 ноября 2017 г. 19:36

Ответы

  • "...чтобы были даты и чтобы доступ к индексам был,
    при этом убрать пробелы, где нет данных..."
    Сам график чувствует и реагирует на мышиные манипуляции,
    но то, что Вы хотите показать, нужно организовывать программно.
    Если по оси X Вы показываете DateTime, то пробелы будут,
    если же по этой оси записаны даты в строковом формате,
    то пробелов не будет, но индексирование и всевозможные показы
    нужно будет организовать самому.

    "...получать доступ к данным оси Y, ко всем четырем элементам..."
    - может быть и можно, но я не знаю как,
    но выход простой - см. выше.

    "...экстремумы в определенных промежутках..." - то же самое.
    DataVisualization.Charting - это только рисовка графиков с графическим интерфейсом,
    вся математика на совести программера.

    А вообще графика очень удобна и нехлопотна в Excel-е - 
    все готово, кидаешь цифирь и получаешь график
    или несколько графиков, по желанию.
    Да к тому же, если нужно, еще и при облегченном программировании.

    А в принципе фирмачи дают вполне приличную графику.
    где можно рассматривать графики одновременно нескольких бумаг / индексов,
    и можно какие-то дополнительные манипуляции производить - рисовать тренды,
    получать статистику в скользящих окнах и пр.
    Т.е. с этой точки зрения собственное программирование - 
    это дополнительная головная боль,
    непроизводительное расходование сил и времени.

    Более того, если речь идет о NYSE,
    где рынок сверхнормализован,
    то об эту глыбу уже столько сломано копий,
    что нужно хорошенько подумать,
    стоит ли вообще этим заниматься.
    Во всяком случае имеет смысл посмотреть в интернете 
    информацию о диссертациях на эту тему.

    Курсов по этой тематике больше, чем звезд на небе,
    но, как сказал один великий человек,
    если идею легче продать, чем воплотить,
    то это пустая идея.




    • Изменено QazRdx 2 декабря 2017 г. 22:21
    • Помечено в качестве ответа Qtrade1 3 декабря 2017 г. 11:47
    2 декабря 2017 г. 21:59

Все ответы

  • Может быть дату оставить строкой,
    а не преобразовывать ее в DateTime.
    Тогда все свечи должны следовать друг за другом без пробелов.
    2 декабря 2017 г. 6:17
  • Может быть дату оставить строкой,
    а не преобразовывать ее в DateTime.
    Тогда все свечи должны следовать друг за другом без пробелов.

    Попробовал сделать так:

    String[] nums = new String[count];
    
    String data = line;
    String substring = data.Substring(0, 10);
    nums[i] = substring;//время

    Визуально вроде видно, что нет пропусков. Но, нужно увеличение, чтобы увидеть.

    А чтобы сделать увеличение необходимо вызвать функцию

    private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
            {
    
            }


    там нужны индексы. В итоге красный конверт при скроле выходит.

    Еще прочитал, что если есть данные DateTime по оси, то выводятся все даты, даже где нет данных(из файла)

    То есть можно вызвать:

    //chart1.Series["price"].IsXValueIndexed = true;//Возвращает или задает флаг, указывающий, будет ли использоваться индексы точек данных для значения X.

    но не будут доступны индексы, которые нужны для авто масштабирования минимума максимума по оси Y.

    Сейчас только начал изучать C#, в документации вообще "плаваю", там в одном только классе chart методов, свойств и пр. сотни. C chart control, все примеры, что нашел перечитал, не все правда понял. Может где по незнанию неправильно делаю..?
    • Изменено Qtrade1 2 декабря 2017 г. 13:13
    2 декабря 2017 г. 13:06
  • А вот это Вы видели?
    Ссылка
    Посмотрите! Полезно.
    Здесь примеры использования с кодом на C#.


    • Изменено QazRdx 2 декабря 2017 г. 15:19
    2 декабря 2017 г. 15:18
  • А вот это Вы видели?
    Ссылка
    Посмотрите! Полезно.
    Здесь примеры использования с кодом на C#.


    Конечно видел. Скачал,читал и периодически перечитываю.

    Все равно не понятно можно ли по оси X, чтобы были даты и чтобы доступ к индексам был, при этом убрать пробелы, где нет данных?

    Хорошо бы понять, как получать доступ к данным оси Y, ко всем четырем элементам. Как работать с ними извлекая экстремумы в определенных промежутках.

    У меня получается, что авто масштабирование идет по первому элементу, то есть по максимуму.

    • Изменено Qtrade1 2 декабря 2017 г. 16:29
    2 декабря 2017 г. 16:25
  • "...чтобы были даты и чтобы доступ к индексам был,
    при этом убрать пробелы, где нет данных..."
    Сам график чувствует и реагирует на мышиные манипуляции,
    но то, что Вы хотите показать, нужно организовывать программно.
    Если по оси X Вы показываете DateTime, то пробелы будут,
    если же по этой оси записаны даты в строковом формате,
    то пробелов не будет, но индексирование и всевозможные показы
    нужно будет организовать самому.

    "...получать доступ к данным оси Y, ко всем четырем элементам..."
    - может быть и можно, но я не знаю как,
    но выход простой - см. выше.

    "...экстремумы в определенных промежутках..." - то же самое.
    DataVisualization.Charting - это только рисовка графиков с графическим интерфейсом,
    вся математика на совести программера.

    А вообще графика очень удобна и нехлопотна в Excel-е - 
    все готово, кидаешь цифирь и получаешь график
    или несколько графиков, по желанию.
    Да к тому же, если нужно, еще и при облегченном программировании.

    А в принципе фирмачи дают вполне приличную графику.
    где можно рассматривать графики одновременно нескольких бумаг / индексов,
    и можно какие-то дополнительные манипуляции производить - рисовать тренды,
    получать статистику в скользящих окнах и пр.
    Т.е. с этой точки зрения собственное программирование - 
    это дополнительная головная боль,
    непроизводительное расходование сил и времени.

    Более того, если речь идет о NYSE,
    где рынок сверхнормализован,
    то об эту глыбу уже столько сломано копий,
    что нужно хорошенько подумать,
    стоит ли вообще этим заниматься.
    Во всяком случае имеет смысл посмотреть в интернете 
    информацию о диссертациях на эту тему.

    Курсов по этой тематике больше, чем звезд на небе,
    но, как сказал один великий человек,
    если идею легче продать, чем воплотить,
    то это пустая идея.




    • Изменено QazRdx 2 декабря 2017 г. 22:21
    • Помечено в качестве ответа Qtrade1 3 декабря 2017 г. 11:47
    2 декабря 2017 г. 21:59
  • "...чтобы были даты и чтобы доступ к индексам был,
    при этом убрать пробелы, где нет данных..."
    Сам график чувствует и реагирует на мышиные манипуляции,
    но то, что Вы хотите показать, нужно организовывать программно.
    Если по оси X Вы показываете DateTime, то пробелы будут,
    если же по этой оси записаны даты в строковом формате,
    то пробелов не будет, но индексирование и всевозможные показы
    нужно будет организовать самому.

    "...получать доступ к данным оси Y, ко всем четырем элементам..."
    - может быть и можно, но я не знаю как,
    но выход простой - см. выше.

    "...экстремумы в определенных промежутках..." - то же самое.
    DataVisualization.Charting - это только рисовка графиков с графическим интерфейсом,
    вся математика на совести программера.



    Тоже прихожу к таким выводам. В принципе буду дальше читать и изучать. Кое-что уже понял, как сделать.

    В англоязычной части форума есть раздел по chart control, но есть некоторые трудности перевода, да плюс по самой теме не слишком разбираюсь. Попробую еще по изучать. В любом случае спасибо за ответы.

    C# привлек, тем что можно все сделать именно под свои нужды, которые не даст не один навороченный и специализированный софт.

    Нашел решение, в сети интернет. Не совсем конечно изящно, но работает:

    int[] index = new int[count];//теперь по оси вместо дат просто номера начиная с 0
    
     while ((line = sr.ReadLine()) != null)//цикл заполнения котировками массивов для отрисовки свечей
                        {
                            ************
    
                            nums[i] = Data;//время 
    
                            index[i] = i;
                            
                            ************
                          i = i + 1;
                        }
    
    for (i = 0; i < count-1; i++)
                {
                    chart1.Series["price"].Points.AddXY(index[i], mass[i, 1], mass[i, 2], mass[i, 0], mass[i, 3]);//дата,максимум, минимум, открытие, закрытие
                }
    
                int INDEX = 0;
                foreach (DataPoint point in chart1.Series["price"].Points)
                {
                    point.AxisLabel = nums[INDEX].ToShortDateString();
                    INDEX++;
                }





    • Изменено Qtrade1 3 декабря 2017 г. 13:16
    3 декабря 2017 г. 11:47
  • Ну, что же? Удачи !
    Попробуйте обратиться сюда - может быть поможет!
    https://www.chechet.org/

    3 декабря 2017 г. 13:45