C# PR

【質問回答】Chart ローソク足グラフの作り方 【前場と後場の隙間をなくす方法付き】

記事内に商品プロモーションを含む場合があります

はじめに

C#のChartコントロールを使って、株価チャートなどでよく見るローソク足のグラフを表示させる方法を解説します。

なお、Chartコントロールでローソク足を表示させた場合、前場と後場、土日など、取引が行われない期間が「隙間」となって表示されてしまいます。この隙間をなくす方法について質問いただいたので、ローソク足の表示方法とあわせて解説したいと思います。

ご質問いただいた「トム」さん、質問いただきありがとうございます。

環境

この記事で使用する環境は以下の通りです。

環境 バージョンなど 備考
OS Windows11 Windows10でもOKです
言語 C#
開発環境  Visual Studio 2019
.net Framework 4.7.1

プログラム概要

今回のプログラムの概要は以下の通りです。架空銘柄の株価(30分足)のグラフを作成します。

  • 株価データを作成
  • グラフを「ローソク足」に設定
  • 前場・後場の隙間をなくす
  • ローソク足1本分のデータを作成する。

実行結果

後述するプログラムを実行すると、以下のローソク足のグラフを表示できます。

ローソク足を表示するプログラムの実行結果

全体コード

全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。

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;

using System.IO;
using Csv;

// Chartクラスの宣言を簡略化するために
// Usingを追加しています
using System.Windows.Forms.DataVisualization.Charting;

namespace FormCandle
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // FormにChartコントロール(chart1)を
            // 貼り付け済みであることを前提にしています。

            //
            // サンプル用の日付データです
            //
            DateTime[] timeList = new DateTime[12];

            timeList[ 0] = new DateTime(2023, 5, 1, 9, 00, 00);
            timeList[ 1] = new DateTime(2023, 5, 1, 9, 30, 00);
            timeList[ 2] = new DateTime(2023, 5, 1, 10, 00, 00);
            timeList[ 3] = new DateTime(2023, 5, 1, 10, 30, 00);
            timeList[ 4] = new DateTime(2023, 5, 1, 11, 00, 00);

            // 11:30(前場) ~ 12:30(後場) の間の取引はありません

            timeList[ 5] = new DateTime(2023, 5, 1, 12, 30, 00);
            timeList[ 6] = new DateTime(2023, 5, 1, 13, 00, 00);
            timeList[ 7] = new DateTime(2023, 5, 1, 13, 30, 00);
            timeList[ 8] = new DateTime(2023, 5, 1, 14, 00, 00);
            timeList[ 9] = new DateTime(2023, 5, 1, 14, 30, 00);
            timeList[ 10] = new DateTime(2023, 5, 1, 15, 00, 00);

            //
            // サンプル用の株価データ(2次元配列)を作ります。 
            //
            double[,] priceList = new double[,]
            {
                //
                // 以下の順番で並べます
                // Low, hight, open, close
                //
                {  800, 1000,  900,  800 },
                {  700, 1100,  800, 1100 },
                {  740, 1100, 1100,  900 },
                {  900, 1150,  900, 1000 },
                {  900, 1030, 1000,  900 },

                {  800, 1100,  900,  880 },
                {  880, 1050,  880, 1020 },
                {  990, 1100, 1020,  990 },
                {  990, 1100,  990, 1000 },
                { 1000,  800, 1000,  900 },

                { 1000,  800,  900,  900 }

            };

            //
            // 貼り付けたChartコントロールには
            // 初期値のデータがセットされているので、一旦クリアします
            //
            chart1.ChartAreas.Clear();
            chart1.Series.Clear();

            // 「chartArea」という名前のエリアを生成します
            ChartArea chartAria = new ChartArea("chartArea");

            // 生成したエリアをChartコントロールに追加します。
            chart1.ChartAreas.Add(chartAria);

            // Series(系列)を生成します
            Series series = new Series();

            // 系列の種類をローソク足に設定します
            series.ChartType = SeriesChartType.Candlestick;

            // ローソク足の線の太さを太くします
            series.BorderWidth = 3;

            // X軸の値を日付としてセットします
            series.XValueType = ChartValueType.DateTime;

            // X軸のフォーマットを設定します
            chart1.ChartAreas["chartArea"].AxisX.LabelStyle.Format = "MM/dd hh:mm";

            // 前場・後場の隙間をなくします
            series.IsXValueIndexed = true;


            // サンプルデータの数だけループします
            for (int i = 0; i < 11; i++)
            {
                // 日付を「DateTime型」から「数値型」に変換します
                double dateNumber = timeList[i].ToOADate();

                // 株価データからローソク足1つ分データをコピーします
                double[] price = new double;
                price[0] = priceList[i, 0];
                price = priceList[i, 1];
                price = priceList[i, 2];
                price = priceList[i, 3];

                // 日付と株価でローソク足1本分を作ります
                DataPoint dp = new DataPoint(dateNumber, price);

                // 系列にローソク足を追加します
                series.Points.Add(dp);

            }

            // チャートに系列をセットします
            chart1.Series.Add(series);

        }
    }
}

コードのポイント

株価データの作成

ローソク足は、高値・安値・始値・終値の「値動きの情報」と、「日時の情報」で構成されるため、グラフに表示するデータを最初にまとめて作成します。データは30分足としています。

            //
            // サンプル用の日付データです
            //
            DateTime[] timeList = new DateTime[12];

            timeList[0] = new DateTime(2023, 5, 1, 9, 00, 00);
            timeList = new DateTime(2023, 5, 1, 9, 30, 00);
            timeList = new DateTime(2023, 5, 1, 10, 00, 00);
            timeList = new DateTime(2023, 5, 1, 10, 30, 00);
            timeList = new DateTime(2023, 5, 1, 11, 00, 00);

            // 11:30(前場) ~ 12:30(後場) の間の取引はありません

            timeList[5] = new DateTime(2023, 5, 1, 12, 30, 00);

            // ~~~~~ 中略 ~~~~~

            //
            // サンプル用の株価データ(2次元配列)を作ります。 
            //
            double[,] priceList = new double[,]
            {
                //
                // 以下の順番で並べます
                // Low, hight, open, close
                //
                {  800, 1000,  900,  800 },
                {  700, 1100,  800, 1100 },
                {  740, 1100, 1100,  900 },

                 // ~~~~~ 中略 ~~~~

            };

グラフをローソク足に設定

散布図などと同じようにseries(系列)の種類を「ローソク足」に設定します。ローソク足でのX軸(横軸)は日時になるので、X軸が日時となるように設定します。

デフォルトの設定では、日付表示が「2023/05/01」表示されて時刻がでないため、LabelStyle.Formatプロパティを使って、「日付と時刻」が表示されるようにフォーマットを指定します。

ローソク足の太さはお好みですが、デフォルトでは以下のように縦横のグリッドと重なって見づらいので太めに指定しています。

デフォルトん太さで表示したグラフの画像
デフォルトの太さで表示したグラフ


            // 系列の種類をローソク足に設定します
            series.ChartType = SeriesChartType.Candlestick;

            // ローソク足の線の太さを太くします
            series.BorderWidth = 3;

            // X軸の値を日付としてセットします
            series.XValueType = ChartValueType.DateTime;

            // X軸のフォーマットを設定します
            chart1.ChartAreas["chartArea"].AxisX.LabelStyle.Format = "MM/dd hh:mm";

前場・後場の隙間をなくす

前場・後場の間は1時間空くため、そのままグラフ表示すると、30分足だと2本分の隙間が空いてしまいます。

前場と後場の間で隙間が空いた状態のグラフの画像

IsXValueIndexedプロパティをtrueに設定すると、上の隙間を詰めて表示することができます。
日足で、土日を含む期間を表示する場合も隙間ができるので、長期間のグラフを作る際もおすすめです。

            // 前場・後場の隙間をなくします
            series.IsXValueIndexed = true;

ローソク足1本分のデータを作成する

散布図でグラフをプロットする場合、XとY座標の2つの値をdouble型で設定していましたが、ローソク足の場合は、以下の5つの情報を持ったDataPoint型で設定します。

項目 変数名 内容
日付 dateNumber double型の日付情報です。
値動き price[ 0 ] double配列の値動き情報です。 安値(Low)
price[ 1 ] 高値(High)
price[ 2 ] 始値(Open)
price[ 3 ] 終値(Close)

                // 日付を「DateTime型」から「数値型」に変換します
                double dateNumber = timeList[i].ToOADate();

                // 株価データからローソク足1つ分データをコピーします
                double[] price = new double;
                price[ 0 ] = priceList[i, 0];
                price[ 1 ] = priceList[i, 1];
                price[ 2 ] = priceList[i, 2];
                price[ 3 ] = priceList[i, 3];

                // 日付と株価でローソク足1本分を作ります
                DataPoint dp = new DataPoint( dateNumber, price );

                // 系列にローソク足を追加します
                series.Points.Add(dp);

まとめ

Chartコントロールでローソク足のグラフを表示させる方法を解説しました。

ネット上でも、Chartでローソク足を扱う情報はも少なく、質問者さんのように困っている人も多いのではないでしょうか。

簡単な内容ですが、この記事が皆様のお役に立てばうれしいです。

お知らせ

今月号の『Software Design』はドメイン駆動設計(DDD)。実例を交えたDDDの手法の解説が特集されています。

編集:Software Design 編集部
¥1,562 (2024/02/21 06:29時点 | Amazon調べ)

質問・要望 大歓迎です

「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。

使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。

ABOUT ME
えす
現役のソフトウェアエンジニアです。 C++ C# Python を使ってます。10年ちょい設計/開発部門にいましたが、今はQAエンジニアっぽいことをしています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Index