Highcharts を使ってみました

前回の記事で Chart.js を使って、みんかぶ FX のチャートのレートを折れ線グラフで表示してみました。 今回は、 Highcharts を使って、みんかぶ FX のチャートのレートをローソク足で表示してみました。

環境

  • Highcharts v6.1.0
  • Highstock v6.1.0

Highcharts?

Highcharts is a SVG-based, multi-platform charting library that has been actively developed since 2009. It makes it easy to add interactive, mobile-optimized charts to your web and mobile projects. It features robust documentation, advanced responsiveness and industry-leading accessibility support.

Highcharts Javascript Charting Library – Highcharts

SVG ベースのマルチプラットフォームのチャートライブラリーのようです。

次のような特徴があるようです。

  • Options Optional
  • Responsive & mobile ready
  • Speeeed!

前回使った Chart.js よりも高度なことができるようです。

Licenses

商用利用だと費用がかかるみたいです。

High-five License

Special bootstrap licence for pre-revenue or pre-financing startups.

  • Allows Highcharts, Highstock and Highmaps to be used in SaaS projects, web applications, intranets, and websites.
  • Valid for one year and up to two developers
  • Includes Highcharts Editor and Highcharts Export Server.

USD 50.00

Highcharts JS

High-five License というスタートアップのための特別なライセンスで、 1 年間、 2 開発者のライセンスで、 50 ドルかかるみたいです。

Highcharts Single Developer

Without Premium Support

USD 430.00

Highcharts JS

プレミアムサポートなしの 1 開発者のライセンスで 430.00 ドルかかるみたいです。 個人で契約するとしたら結構高いです。

他にもいくつかライセンスの種類がありました。

商用利用じゃなければ費用はかからないようです。

Installation

npmBower からインストールすることができるようです。 CDN から使うこともできるようです。 今回は、 CDN から使ってみます。

次のように記述して Highcharts のライブラリーを読み込みました。

<script src="//code.highcharts.com/highcharts.js"></script>

Your First Chart

Your First Chart を参考に、棒グラフを表示してみます。

表示領域に <div> を次のように記述しました。

<div id="container" style="width:100%; height:400px;"></div>

Chart.js は <canvas> に表示していましたが、 Highcharts は <div> の中に表示しているようです。

それから <script> を次のように記述しました。

<script>
  window.addEventListener('load', () => {
    const myChart = Highcharts.chart('container', {
      chart: {
        type: 'bar'
      },
      title: {
        text: 'Fruit Consumption'
      },
      xAxis: {
        categories: ['Apples', 'Bananas', 'Oranges']
      },
      yAxis: {
        title: {
          text: 'Fruit eaten'
        }
      },
      series: [{
        name: 'Jane',
        data: [1, 0, 4]
      },
      {
        name: 'John',
        data: [5, 7, 3]
      }]
    });
  });
</script>

ここに棒グラフを表示しました。

ちゃんと表示されているかな。

Chart.js では何も考えずに棒グラフを表示したら、縦に伸びるタイプでしたけど、 Highcharts は横に伸びるタイプみたいです。

Optionally, you can apply a global theme to your charts. A theme is just a set of options that are applied globally through the Highcharts.setOptions method. The download package comes with four predefined themes. To apply a theme from one of these files, add this directly after the highcharts.js file inclusion:

<script type="text/javascript" src="/js/themes/gray.js"></script>

Your First Chart | Highcharts

オプションでチャートのテーマを適用することができるようです。

ローソク足

前回、みんかぶ FX の為替レートを取ってきたので、それをローソク足で表示してみます。

ローソク足は、 Highstock という、 Highcharts とは別のライブラリーで表示することができるようです。 次のような記述をして、 Highstock のライブラリーを読み込みました。

<script src="//code.highcharts.com/stock/highstock.js"></script>

それから、 Highstock にはチャートを印刷したり、データを CSV や Excel でエクスポートする機能があるようす。 次のような記述をして、エクスポートの機能のライブラリーを読み込みました。

<script src="//code.highcharts.com/stock/modules/exporting.js"></script>
<script src="//code.highcharts.com/stock/modules/export-data.js"></script>

インディケーターも表示することができるようです。 せっかくなので、 5 期間と 20 期間の移動平均線 SMA も表示してみます。 次のような記述をして、インディケーターのライブラリーを読み込みました。

<script src="//code.highcharts.com/stock/indicators/indicators.js"></script>

ローソク足を表示するためのスクリプトを次のように記述しました。

<script>
  window.addEventListener('load', () => {
    const dailyjson = [[1496005200000,"111.295","111.467","111.124","111.222"],[1496091600000,"111.265","111.317","110.657","110.827"],[1496178000000,"110.845","111.225","110.484","110.766"],[1496264400000,"110.768","111.481","110.65","111.347"],[1496350800000,"111.334","111.711","110.326","110.43"],[1496610000000,"110.315","110.73","110.303","110.452"],[1496696400000,"110.451","110.512","109.218","109.383"],[1496782800000,"109.411","109.881","109.096","109.81"],[1496869200000,"109.811","110.381","109.378","109.972"],[1496955600000,"109.983","110.812","109.721","110.323"],[1497214800000,"110.311","110.44","109.624","109.931"],[1497301200000,"109.925","110.27","109.786","110.06"],[1497387600000,"110.045","110.343","108.82","109.572"],[1497474000000,"109.554","110.979","109.258","110.911"],[1497560400000,"110.925","111.415","110.637","110.89"],[1497819600000,"110.841","111.601","110.704","111.526"],[1497906000000,"111.514","111.782","111.306","111.454"],[1497992400000,"111.434","111.738","111.035","111.375"],[1498078800000,"111.337","111.446","110.93","111.319"],[1498165200000,"111.32","111.427","111.142","111.226"],[1498424400000,"111.157","111.939","111.101","111.86"],[1498510800000,"111.82","112.464","111.459","112.337"],[1498597200000,"112.337","112.416","111.829","112.28"],[1498683600000,"112.28","112.925","111.804","112.164"],[1498770000000,"112.167","112.6","111.71","112.362"],[1499029200000,"112.1","113.471","112.054","113.376"],[1499115600000,"113.375","113.451","112.743","113.261"],[1499202000000,"113.26","113.686","112.821","113.252"],[1499288400000,"113.255","113.469","112.88","113.208"],[1499374800000,"113.204","114.179","113.056","113.91"],[1499634000000,"113.855","114.298","113.831","114.024"],[1499720400000,"114.025","114.495","113.714","113.93"],[1499806800000,"113.918","113.967","112.925","113.149"],[1499893200000,"113.152","113.522","112.86","113.28"],[1499979600000,"113.275","113.573","112.255","112.528"],[1500238800000,"112.455","112.865","112.321","112.617"],[1500325200000,"112.615","112.682","111.677","112.056"],[1500411600000,"112.015","112.229","111.551","111.93"],[1500498000000,"111.942","112.417","111.48","111.893"],[1500584400000,"111.898","112.079","111.011","111.122"],[1500843600000,"111.106","111.32","110.618","111.081"],[1500930000000,"111.039","111.958","110.828","111.872"],[1501016400000,"111.878","112.193","111.06","111.169"],[1501102800000,"111.158","111.711","110.781","111.266"],[1501189200000,"111.225","111.33","110.547","110.671"],[1501448400000,"110.653","110.773","110.214","110.254"],[1501534800000,"110.25","110.589","109.919","110.387"],[1501621200000,"110.36","110.984","110.283","110.741"],[1501707600000,"110.7","110.829","109.855","110.045"],[1501794000000,"110.031","111.051","109.841","110.655"],[1502053200000,"110.697","110.919","110.647","110.729"],[1502139600000,"110.73","110.829","110.25","110.338"],[1502226000000,"110.33","110.363","109.559","110.056"],[1502312400000,"110.055","110.179","109.153","109.209"],[1502398800000,"109.182","109.404","108.718","109.173"],[1502658000000,"109.153","109.802","109.024","109.652"],[1502744400000,"109.603","110.848","109.603","110.662"],[1502830800000,"110.656","110.949","110.03","110.191"],[1502917200000,"110.182","110.369","109.446","109.553"],[1503003600000,"109.548","109.599","108.603","109.185"],[1503262800000,"109.313","109.422","108.636","108.958"],[1503349200000,"108.967","109.649","108.844","109.552"],[1503435600000,"109.567","109.826","108.924","109.032"],[1503522000000,"109.041","109.605","108.849","109.552"],[1503608400000,"109.554","109.844","109.112","109.322"],[1503867600000,"109.154","109.413","109.026","109.23"],[1503954000000,"109.234","109.902","108.267","109.738"],[1504040400000,"109.63","110.439","109.542","110.228"],[1504126800000,"110.228","110.671","109.88","109.96"],[1504213200000,"109.96","110.465","109.562","110.228"],[1504472400000,"109.498","109.933","109.383","109.696"],[1504558800000,"109.676","109.835","108.63","108.8"],[1504645200000,"108.8","109.398","108.448","109.178"],[1504731600000,"109.178","109.264","108.046","108.426"],[1504818000000,"108.43","108.486","107.318","107.836"],[1505077200000,"108.168","109.506","108.128","109.392"],[1505163600000,"109.39","110.254","109.239","110.15"],[1505250000000,"110.154","110.691","109.903","110.486"],[1505336400000,"110.484","111.04","110.06","110.214"],[1505422800000,"110.216","111.334","109.546","110.83"],[1505682000000,"111.056","111.663","110.993","111.57"],[1505768400000,"111.57","111.881","111.201","111.588"],[1505854800000,"111.586","112.532","111.096","112.21"],[1505941200000,"112.21","112.716","112.135","112.456"],[1506027600000,"112.456","112.556","111.653","111.99"],[1506286800000,"112.148","112.531","111.475","111.722"],[1506373200000,"111.72","112.475","111.498","112.21"],[1506459600000,"112.218","113.257","112.218","112.808"],[1506546000000,"112.808","113.202","112.254","112.322"],[1506632400000,"112.33","112.737","112.213","112.5"],[1506891600000,"112.646","113.058","112.436","112.738"],[1506978000000,"112.744","113.196","112.654","112.844"],[1507064400000,"112.842","112.937","112.323","112.75"],[1507150800000,"112.748","112.918","112.413","112.804"],[1507237200000,"112.804","113.44","112.6","112.6"],[1507496400000,"112.558","112.747","112.33","112.672"],[1507582800000,"112.674","112.827","111.989","112.436"],[1507669200000,"112.44","112.586","112.08","112.472"],[1507755600000,"112.476","112.521","112.126","112.272"],[1507842000000,"112.276","112.305","111.69","111.826"],[1508101200000,"111.748","112.288","111.653","112.182"],[1508187600000,"112.182","112.48","112.036","112.185"],[1508274000000,"112.188","113.05","112.136","112.92"],[1508360400000,"112.924","113.147","112.296","112.536"],[1508446800000,"112.532","113.57","112.461","113.508"],[1508706000000,"113.882","114.1","113.245","113.43"],[1508792400000,"113.436","114.022","113.249","113.892"],[1508878800000,"113.9","114.244","113.48","113.736"],[1508965200000,"113.74","114.077","113.342","113.97"],[1509051600000,"113.972","114.452","113.635","113.635"],[1509310800000,"113.723","113.836","113.026","113.166"],[1509397200000,"113.17","113.732","112.958","113.622"],[1509483600000,"113.627","114.28","113.602","114.178"],[1509570000000,"114.178","114.218","113.538","114.084"],[1509656400000,"114.086","114.426","113.626","114.042"],[1509919200000,"114.001","114.734","113.696","113.698"],[1510005600000,"113.698","114.342","113.698","114.002"],[1510092000000,"114.002","114.008","113.395","113.866"],[1510178400000,"113.874","114.068","113.091","113.454"],[1510264800000,"113.47","113.635","113.221","113.505"],[1510524000000,"113.454","113.713","113.245","113.62"],[1510610400000,"113.622","113.912","113.308","113.45"],[1510696800000,"113.448","113.496","112.478","112.876"],[1510783200000,"112.872","113.333","112.734","113.042"],[1510869600000,"113.038","113.143","111.945","112.085"],[1511128800000,"112.101","112.718","111.886","112.614"],[1511215200000,"112.614","112.704","112.174","112.435"],[1511301600000,"112.435","112.493","111.142","111.208"],[1511388000000,"111.21","111.381","111.068","111.199"],[1511474400000,"111.199","111.622","111.194","111.501"],[1511733600000,"111.488","111.692","110.842","111.082"],[1511820000000,"111.08","111.64","110.931","111.465"],[1511906400000,"111.468","112.15","111.375","111.906"],[1511992800000,"111.91","112.638","111.735","112.536"],[1512079200000,"112.526","112.874","111.406","112.164"],[1512338400000,"112.792","113.09","112.365","112.4"],[1512424800000,"112.392","112.867","112.378","112.579"],[1512511200000,"112.578","112.633","111.992","112.284"],[1512597600000,"112.286","113.158","112.219","113.082"],[1512684000000,"113.08","113.59","113.077","113.448"],[1512943200000,"113.528","113.69","113.243","113.545"],[1513029600000,"113.552","113.751","113.371","113.548"],[1513116000000,"113.542","113.575","112.46","112.526"],[1513202400000,"112.534","112.883","112.065","112.38"],[1513288800000,"112.38","112.744","112.032","112.581"],[1513548000000,"112.72","112.83","112.31","112.538"],[1513634400000,"112.534","113.079","112.511","112.884"],[1513720800000,"112.884","113.466","112.839","113.385"],[1513807200000,"113.384","113.638","113.199","113.315"],[1513893600000,"113.315","113.448","113.24","113.265"],[1514239200000,"113.285","113.332","113.119","113.226"],[1514325600000,"113.23","113.381","113.147","113.34"],[1514412000000,"113.342","113.344","112.662","112.856"],[1514498400000,"112.856","112.969","112.472","112.651"],[1514844000000,"112.691","112.701","112.055","112.273"],[1514930400000,"112.273","112.608","112.172","112.502"],[1515016800000,"112.504","112.864","112.461","112.732"],[1515103200000,"112.734","113.303","112.717","113.018"],[1515362400000,"113.116","113.387","112.882","113.082"],[1515448800000,"113.08","113.18","112.366","112.635"],[1515535200000,"112.634","112.785","111.271","111.424"],[1515621600000,"111.426","111.876","111.044","111.244"],[1515708000000,"111.244","111.698","110.915","110.996"],[1515967200000,"111.081","111.184","110.328","110.525"],[1516053600000,"110.521","110.983","110.246","110.438"],[1516140000000,"110.444","111.347","110.192","111.29"],[1516226400000,"111.271","111.482","110.696","111.092"],[1516312800000,"111.09","111.129","110.49","110.814"],[1516572000000,"110.551","111.223","110.512","110.922"],[1516658400000,"110.914","111.179","110.252","110.3"],[1516744800000,"110.302","110.337","108.968","109.218"],[1516831200000,"109.212","109.702","108.5","109.402"],[1516917600000,"109.402","109.771","108.282","108.589"],[1517176800000,"108.685","109.203","108.51","108.952"],[1517263200000,"108.948","109.205","108.414","108.774"],[1517349600000,"108.772","109.446","108.596","109.188"],[1517436000000,"109.188","109.751","109.094","109.382"],[1517522400000,"109.388","110.482","109.281","110.152"],[1517781600000,"110.196","110.286","108.992","109.064"],[1517868000000,"109.078","109.653","108.456","109.554"],[1517954400000,"109.552","109.712","108.919","109.302"],[1518040800000,"109.309","109.784","108.58","108.736"],[1518127200000,"108.734","109.31","108.046","108.77"],[1518386400000,"108.842","108.885","108.437","108.641"],[1518472800000,"108.641","108.781","107.408","107.81"],[1518559200000,"107.812","107.903","106.723","106.998"],[1518645600000,"106.991","107.0","106.035","106.118"],[1518732000000,"106.118","106.399","105.55","106.272"],[1518991200000,"106.328","106.727","106.096","106.58"],[1519077600000,"106.582","107.377","106.557","107.322"],[1519164000000,"107.322","107.903","107.278","107.77"],[1519250400000,"107.759","107.773","106.594","106.742"],[1519336800000,"106.743","107.133","106.512","106.858"],[1519596000000,"107.15","107.154","106.376","106.907"],[1519682400000,"106.907","107.676","106.784","107.32"],[1519768800000,"107.32","107.528","106.565","106.661"],[1519855200000,"106.661","107.205","106.163","106.222"],[1519941600000,"106.22","106.298","105.25","105.712"],[1520200800000,"105.51","106.238","105.351","106.204"],[1520287200000,"106.204","106.463","105.852","106.128"],[1520373600000,"106.134","106.221","105.456","106.059"],[1520460000000,"106.063","106.315","105.892","106.193"],[1520546400000,"106.186","107.05","106.15","106.814"],[1520802000000,"106.632","106.972","106.31","106.41"],[1520888400000,"106.408","107.293","106.254","106.564"],[1520974800000,"106.569","106.749","106.064","106.316"],[1521061200000,"106.318","106.415","105.785","106.327"],[1521147600000,"106.324","106.374","105.602","105.953"],[1521406800000,"105.905","106.307","105.677","106.084"],[1521493200000,"106.089","106.608","105.929","106.526"],[1521579600000,"106.528","106.64","105.881","106.046"],[1521666000000,"106.048","106.089","105.261","105.27"],[1521752400000,"105.273","105.411","104.636","104.712"],[1522011600000,"104.766","105.482","104.707","105.396"],[1522098000000,"105.398","105.903","105.316","105.328"],[1522184400000,"105.329","107.012","105.325","106.842"],[1522270800000,"106.838","106.933","106.267","106.418"],[1522357200000,"106.418","106.537","106.122","106.26"],[1522616400000,"106.237","106.45","105.657","105.877"],[1522702800000,"105.877","106.657","105.693","106.6"],[1522789200000,"106.598","106.848","105.99","106.774"],[1522875600000,"106.774","107.493","106.711","107.376"],[1522962000000,"107.374","107.46","106.776","106.915"],[1523221200000,"106.937","107.203","106.616","106.747"],[1523307600000,"106.754","107.399","106.619","107.188"],[1523394000000,"107.19","107.253","106.65","106.782"],[1523480400000,"106.777","107.43","106.7","107.304"],[1523566800000,"107.294","107.78","107.204","107.338"],[1523826000000,"107.468","107.609","107.035","107.106"],[1523912400000,"107.104","107.213","106.882","106.991"],[1523998800000,"106.991","107.386","106.984","107.225"],[1524085200000,"107.223","107.517","107.181","107.358"],[1524171600000,"107.354","107.856","107.352","107.616"],[1524430800000,"107.768","108.754","107.659","108.7"],[1524517200000,"108.698","109.201","108.543","108.808"],[1524603600000,"108.808","109.455","108.783","109.418"],[1524690000000,"109.418","109.467","109.065","109.294"],[1524776400000,"109.288","109.537","108.97","109.022"],[1525035600000,"109.063","109.452","109.02","109.328"],[1525122000000,"109.332","109.4","109.234","109.38"]];
    const data = dailyjson.map(x => [x[0], Number(x[1]), Number(x[2]), Number(x[3]), Number(x[4])])
    // Create the chart
    Highcharts.stockChart('container2', {
      plotOptions: {
        candlestick: {
          // shared options for all candlestick series
          tooltip: {
            dateTimeLabelFormats: {
              millisecond: '%A, %b %e, %Y',
              second: '%A, %b %e, %Y',
              minute: '%A, %b %e, %Y',
              hour: '%A, %b %e, %Y',
              day: '%A, %b %e, %Y',
              week: 'Week from %A, %b %e, %Y',
              month: '%B %Y',
              year: '%Y'
            }
          }
        },
        series: {
          // general options for all series
        },
        sma: {
          enableMouseTracking: false,
          lineWidth: 1,
          marker: {
            radius: 0
          }
        }
      },
      rangeSelector: {
        selected: 5
      },
      series: [
        {
          data: data,
          id: 'USDJPY',
          name: '米ドル/円',
          type: 'candlestick'
        },
        {
          linkedTo: 'USDJPY',
          params: {
            index: 3,
            period: 5
          },
          type: 'sma'
        },
        {
          linkedTo: 'USDJPY',
          params: {
            index: 3,
            period: 20
          },
          type: 'sma'
        }
      ],
      time: {
        timezoneOffset: (new Date).getTimezoneOffset()
      },
      title: {
        text: '米ドル/円'
      }
    });
  });
</script>

ここにローソク足を表示しました。

ちゃんと表示されているかな。

エラー 1

最初、 Highstock を表示しようとしたら、 Firefox のコンソールに次のエラーが表示されて、チャートを表示することができませんでした。

Error: Highcharts error #16: www.highcharts.com/errors/16

コンソールに出力された URL のページを見ると、次のように記載されていました。

Highcharts already defined in the page

www.highcharts.com/errors/16

Highcharts のライブラリーと Highstock のライブラリーをそれぞれ読み込むと、 Highcharts の定義が重複してしまうようでした。 なので、 Highstock のライブラリーだけ読み込むようにしました。

Highstock の内部に Highcharts も持っているのかな。 Highstock を読み込むだけで Highcharts も使えました。

エラー 2

次に、みんかぶ FX の為替レートのデータを Highstock に読み込ませたら、 Firefox のコンソールに次のエラーが表示されて、チャートを表示することができませんでした。

Error: Highcharts error #14: www.highcharts.com/errors/14

コンソールに出力された URL のページを見ると、次のように記載されていました。

String value sent to series.data, expected Number

www.highcharts.com/errors/14

データの型は Number 型を期待しているそうです。 確かに、みんかぶ FX の為替レートは "109.288" のように、 String 型になっています。 なので、 const data = dailyjson.map(x => [x[0], Number(x[1]), Number(x[2]), Number(x[3]), Number(x[4])]) のように、 String 型から Number 型に変換したものを渡しました。

time

Highstock に渡す日時は、 Unix エポックのミリ秒で渡しても大丈夫でした。 が、表示するのに UTC (協定世界時)になってしまっていて、 UTC+9 (日本標準時)になっていないようです。 なので、 timezoneOffset を参考に、 time.timezoneOffset = (new Date).getTimezoneOffset() の設定をしました。

終わり

ローソク足やインディケーターも表示できて便利でした。 でも、ライセンスが高いから使いづらいかもしれません。

それから、 Highcharts は Chart.js に比べてドキュメントが充実しているように感じました。 Chart.js はドキュメントにすべての設定項目が記載されていないようで、サンプルのソースも見ながら手探りで実装したように思います。