Reactを使って株価チャートを描いてみたいという人がもしかしたらいる?かもしれないのでそんな人のためにReact+Chart.js+投資情報サービスを利用して株価のチャートの描写する方法を説明したいと思います。株に興味がない人も外部のサービスの情報を利用してチャートを表示する方法がどういうものか理解することができます。

縦軸の表示とTooltip
縦軸の表示とTooltip

APIを利用して株価情報を取得することができるサービスが国内にないか探したのですが手軽に始められそうなものを見つけることができませんでした。そのためアメリカのmarketstackというサービスを利用して行いたいと思います。アメリカには無数のサービスがありどれを選ぶか悩むところですが日本はあまりないようです、この違いは一体何なんでしょう??

auカブコム証券のkabu STATION APIだと発注まで行えるサービスを提供しているようなので探せば他にも国内で手軽に利用できる投資情報を提供しているサービスがあるのかもしれません。
fukidashi

利用するサービス

marketstackというグローバルで72の証券取引所をサポートしているアメリカの投資情報サービスを使います。東京証券取引所の株価も情報が取得できると記載されていたのですが残念ながら銘柄検索で東京証券取引所の銘柄がひっかかりませんでした。札幌、名古屋の情報は銘柄検索で表示され銘柄情報はAPI経由で取得することはできても株価は取得できませんでした。

検索項目として東京証券取引所は、Tokyo Stock Exchange(XTKS)と表示されるので何かの理由でサービスを停止しているまた有料のプランにしか対応していないということがあるかもしれません。日本の銘柄に関する扱いについて詳しく調べてないので方法に誤り等があるかもしれません。
fukidashi

1ヶ月4,000リクエストなら無料だということで動作確認程度であれば十分ということでmarketstackというサービスを利用して株価情報を取得したいと思います。本書での動作確認であればリクエストが100件を超えることもないでしょう。

1日の株価の動きやリアルタイムでの株価の情報取得は有料のプランを契約する必要がありそうです。

marketstackのアカウントの作成

marketstackのサイトにアクセスしてアカウントの作成を行います。アカウント作成時にクレジット情報の登録などは必要ありませんが、請求先の住所のみ入力を求められます。

marketstackにアクセスすると画面左側に”GET API KEY”ボタンが表示されているので、そのボタンをクリックします。右上にある”SIGN UP FREE”ボタンでもアカウントを作成できますが、”SIGN UP FREE”の場合はプランを選択する画面が表示されます。

marketstackトップページ
marketstackトップページ

Free Planでアカウントを作成することが可能なので必要な情報を入力してください。

サインアップ画面
サインアップ画面

サインアップが完了するとアクセスに必要なAPIのアクセスキーが表示されます。

APIアクセスキーが表示される
APIアクセスキーが表示される

情報取得の方法

ドキュメンテーションを見るとAPIのアクセストークンの利用方法を確認することができます。 “Run API Request”ボタンをクリックするとリクエストのJSONデータが表示されます。access_keyには取得したAPIアクセスキーが利用されるので実行すると1回のリクエストとしてカウントされます。

APIの利用方法
APIの利用方法

リクエストの実行結果が表示されます。

リクエストで戻されるJSONデータ
リクエストで戻されるJSONデータ

JavaScript(Node.js)を利用した場合のコードの記述例についても公開されているのでコードの記述に迷うこともありません。

Node.jsによるコードの記述例
Node.jsによるコードの記述例

利用するサービスの準備ができたのでReactのプロジェクトを作成します。

Reactプロジェクトの作成

任意のプロジェクト名をつけてReactプロジェクトを作成してください。ここではstockという名前にしています。


 % npx create-react-app stock 

プロジェクト作成後、プロジェクトのstockフォルダに移動してnpm startコマンドを実行してください。


 % cd robinhood_clone 
 % npm start
React初期画面
React初期画面

srcフォルダに移動して、App.jsファイルを開いてロゴなど必要のないコードを削除します。削除後は下記のようになります。


import './App.css';

function App() {
  return (
    <div className="App">
    </div>
  );
}

export default App;

srcフォルダにあるApp.test.js, log.svg, setupTests.jsなど利用しないファイルも削除します。これは必須の作業ではありません。

App.cssファイルを開いて記述されているCSSを削除して下記を設定します。背景をブラック、文字を白に設定しています。


* {
  margin: 0;
  padding: 0;
}

body {
  background-color: #191919;
  color: white;
}

株価チャートの作成

銘柄と株価の表示

銘柄と株価をブラウザ上に表示します。Teslaの株価を表示させるため、銘柄名と株価をまずは手動で設定し表示させます。後ほどmarketstackから取得したデータで表示を行います。


import './App.css';

function App() {
  return (
    <div className="App">
      <h1>TSLA</h1>
      <h2>$633.25</h2>
    </div>
  );
}

export default App;

App.cssファイルでAppクラスにCSSを適用します。


.App {
  width: 1024px;
  margin-top: 100px;
  margin-right: auto;
  margin-left: auto;
}

ブラウザで確認すると下記のように表示されます。

銘柄名と株価を表示
銘柄名と株価を表示

axiosを利用してmarketstackから会社名と本日の株価の情報を取得します。axiosはpromiseベースのHTTPクライアントで、axiosを利用すると外部サービスからデータの取得を効率的に行うことができます。

axiosのインストール

npmコマンドでaxiosのライブラリをインストールします。


 % npm install axios

marketstackからのデータ取得

marketstackにアカウント作成するとアクセスキーを取得することができました。銘柄の情報を取得するために取得したアクセスキーを利用してmarketstackにアクセスしますがどの銘柄の情報を取得するかsymbolを設定する必要があります。


http://api.marketstack.com/v1/tickers/{symbol}?access_key={api_access_key}

marketstackのStock SearchのメニューからSymbolを確認することができます。株になれていない人だとsymbolがすぐにわからないと思いますが各銘柄に4桁のアルファベットが割り振られているようです。AppleならAAPL、AmazonならAMZNといった感じです。

Stock SearchでSymbolを探す
Stock SearchでSymbolを探す

TeslaのSymbolはTSLAなのでTSLAを利用してTeslaの情報を取得します。

URLとACCESS_KEYを定義し、アクセスするURLとAPI ACCESS KEYを設定します。API ACCESS KEYは各自が取得したキーを設定します。marketstackにログインすればダッシュボードページから確認できます。


function App() {
  const URL = "http://api.marketstack.com/v1/tickers";
  const ACCESS_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  //略

コンポーネントがmountする時にmarketstackにアクセスして株価情報を取得するためuseEffectフックを利用します。getStockDataメソッドを追加し、引数にsymbolを設定し、useEffectフックの中でgetStockDataを実行します。


import {useEffect} from 'react'
import './App.css';
import axios from 'axios'

function App() {
  const URL = "http://api.marketstack.com/v1/tickers";
  const ACCESS_KEY = "XXXXXXXXXXXXXXXXXX";

  useEffect(() => {
    const getStockData = (symbol) => {
      axios.get(`${URL}/${symbol}?access_key=${ACCESS_KEY}`)
        .then(response => {
          console.log(response.data);
      });
    }
    getStockData('TSLA');
  },[]);

  return (
    <div className="App">
      <h1>TSLA</h1>
      <h2>$633.25</h2>
    </div>
  );
}

export default App;

デベロッパーツールのコンソールで取得した情報を確認することができます。nameが”TESLA INC”、取引所がNASDAQ Stock Exchange”であることがこの情報からわかります。

marketstackから取得したデータ
marketstackから取得したデータ

取得したデータを保存し、ブラウザ上に表示させるためにuseStateフックを利用します。


const [stockData, setStockData] = useState({})

取得したデータはsetStockDataでstockDataに保存します。


  useEffect(() => {
    const getStockData = (symbol) => {
      axios.get(`${URL}/${symbol}?access_key=${ACCESS_KEY}`)
        .then(response => {
          // console.log(response.data);
          setStockData(response.data)
      });
    }
    getStockData('TSLA');
  },[]);

取得したデータをブラウザ上に表示させるためにstockDataを利用します。


<div className="App">
  <h1>{ stockData.name }</h1>
  <h2>$633.25</h2>
</div>

ブラウザで確認するとmarketstackで取得したデータから会社名を表示させることができます。

取得したデータから会社名を表示
取得したデータから会社名を表示

会社名の下にある現在の株価を表示させたいのですが、先ほど取得したデータには株価が含まれていませんでした。株価の含まれている情報を取得するため再度axiosを利用して下記のURLにアクセスして株価を取得します。


http://api.marketstack.com/v1/tickers/{symbol}/eod/latest?access_key={api_access_key}
/eod/latestはend of dayの最新の情報を意味しており、このURLにアクセスするともっとも直近日の株価情報を取得することができます。
fukidashi

新たに株価を保存するstockPriceをuseStateで定義し、getStockDataメソッドの中にaxiosのgetメソッドを追加します。


const [stockData, setStockData] = useState({})
const [stockPrice, setStockPrice] = useState({});

useEffect(() => {
const getStockData = (symbol) => {
    axios.get(`${URL}/${symbol}?access_key=${ACCESS_KEY}`)
    .then(response => {
        setStockData(response.data)
    });
    axios.get(`${URL}/${symbol}/eod/latest?access_key=${ACCESS_KEY}`)
    .then(response => {
        console.log(response.data)
        setStockPrice(response.data);
    })
}
getStockData('TSLA');
},[]);

デベロッパーツールのコンソールに表示される内容を確認します。symbolがTSLAと表示されているので2020-12-15のTeslaの株価であることがわかります。closeがその日の終値なのでブラウザにcloseを表示させます。他のサービスを利用しても12/15のteslaの株価は633.25であることが確認できました。

取得した株価情報
取得した株価情報

ブラウザ上で取得した株価が表示されるように変更を行います。


<div className="App">
  <h1>{ stockData.name }</h1>
  <h2>${ stockPrice.close }</h2>
</div>

marketstackから取得した株価を表示することができました。

martketstackから取得した情報を表示
martketstackから取得した情報を表示

Chartコンポーネント作成

株価チャート用のコンポーネントChartを追加します。srcフォルダにChart.jsファイルとChart.cssを作成します。


import React from 'react'
import './Chart.css'

function Chart() {
    return (
        <div className="chart">
            株価チャート表示
        </div>
    )
}

export default Chart

App.jsファイルでChartコンポーネントを追加し、株価の下に表示します。


import Chart from './Chart'

<div className="App">
  <h1>{ stockData.name }</h1>
  <h2>${ stockPrice.close }</h2>
  <Chart />
</div>

ブラウザで確認すると下記のように表示されます。

Chartコンポーネントを追加
Chartコンポーネントを追加

Charコンポーネントの中に株価チャートを表示するためのコードを記述していきます。

chart.jsとreact-chartjs-2インストール

ReactでChart.jsを利用するためchart.jsとreact-chartjs-2のライブラリをインストールします。


 % npm install react-chartjs-2 chart.js 

Chart.jsによるチャートの表示

Chart.jsではLine, Bar, Pieなどさまざまなチャートを利用することができますが、株価チャートを描写するためLineチャートを利用します。

Lineチャートを利用するためにインストールしたreact-chartjs-2ライブラリからLineコンポーネントをimportします。


import React from 'react'
import './Chart.css'
import {Line} from "react-chartjs-2"

function Chart() {
    return (
        <div className="chart">
            <Line />
        </div>
    )
}

export default Chart

何もデータを与えていないので線は何も表示されませんが、y軸だけメモリラベルが表示されます。

y軸のみの目盛り表示
y軸のみの目盛り表示

線を表示させるためにはpropsのdataを使ってLineコンポーネントに情報を与える必要があります。

動作確認のためにdataを設定します。


function Chart() {
    const data = {
      labels: ['1月','2月','3月','4月'],
      datasets:[
        {
          borderColor: 'rgba(35,200,153,1)',
          data: [100,120,50,110],
          lineTension: 0,
        }
      ]
    }
    return (
        <div className="chart">
            <Line data={data} />
        </div>
    )
}

export default Chart

これだけの設定を行うだけでブラウザ上に線グラフを表示することができます。図ではわかりににくいですがX軸のラベルにはlabelsの1月,2月..が表示され、Y軸のラベルには50から120までが表示されます。labelsの配列が横軸、dataの配列が縦軸に対応していることがわかります。borderColorは名前の通り、線の色を設定することができます。lineTentionを0に設定すると折れ線グラフのように表示されます。

テストデータでグラフ表示
テストデータでグラフ表示

参考にLineTensionを設定しない場合は直線ではなく曲線でなめらかになります。

lineTensionを設定しない場合
lineTensionを設定しない場合

data以外にLineコンポーネントのoptions propsを利用してグラフの設定を変更することができます。まず、optionsを利用してlegend(凡例:上部に表示されているグラフの説明,設定を行っていないのでundefinedと表示されています)


const options = {
	legend:{
	 display:false,
	},
}

Lineコンポーネントでpropsのoptionsを設定します。


<div className="chart">
	<Line data={data} options={options} />
</div>

optionsを設定することでグラフからlegendが決めました。

legendを非表示に
legendを非表示に

X軸とY軸のラベルの表示・非表示もoptionsで行うことができます。


const options = {
  legend:{
    display:false,
  },
  scales: {
    xAxes: [{
      display: false
    }],
    yAxes: [{
      display: false
    }],
  },
}

xAxes, yAxesのdisplayをfalseにすることでX軸とY軸のラベルが非表示になります。

X軸とY軸のラベル非表示
X軸とY軸のラベル非表示

ここまでの動作確認でLineコンポーネントを利用したグラフの表示方法が理解できたので次はmarketstackから取得したデータを利用してグラフを描写します。

marketstackからヒストリーデータ

marketstackでは期間を指定することでその間の株価を取得することができます。


http://api.marketstack.com/v1/eod?access_key={API_KEY}&symbols={symbol}&date_from={start_date}&date_to={end_date}

先ほどApp.jsでuseEffectでgetStockDataを実行した方法を利用して、Chartコンポーネントからmartketstackにアクセスして1ヶ月のヒストリーデータを取得します。


import React,{ useEffect } from 'react'
import './Chart.css'
import {Line} from "react-chartjs-2"
import axios from 'axios'
//略

const URL = "http://api.marketstack.com/v1/eod";
const API_KEY = "yuour_key";

useEffect(() => {
  const getStockData = (symbol) => {
   axios.get(`${URL}?access_key=${API_KEY}&symbols=${symbol}&date_from=2020-11-17&date_to=2020-12-16&sort=ASC`)
      .then(response => console.log(response.data));
    }
    getStockData('TSLA');
},[]);
sort=ASCを設定し、取得する情報の順番をデフォルトとは逆にしています。
fukidashi

土日などの休業日の情報はないので、20日分のデータとなります(2020-11-17から2020-12-16)。グラフに利用するのは横軸のlabelsに設定するdateと縦軸のdataに設定するcloseになります。

1ヶ月分のデータ
1ヶ月分のデータ

取得したデータを保存するためにuseStateでstockDataを定義します。


import React,{ useState, useEffect } from 'react'
//略
  const [stockData, setStockData] = useState({});

取得したデータを展開してforで展開してdataとlabelsの配列に設定します。またaxiosでデータ取得してからsetStockDataが実行できるようにasync, await関数を利用しています。


useEffect(() => {
	const getStockData = async (symbol) => {
		let data = [];
		let labels = [];
		await axios.get(`${URL}?access_key=${API_KEY}&symbols=${symbol}&date_from=2020-11-17&date_to=2020-12-16&sort=ASC`)
			.then(response => {
				for ( let stock of response.data.data){
					data.push(stock.close)
					labels.push(stock.date)
				}
		});
		setStockData({
			labels: labels,
			datasets:[
				{
					borderColor: 'rgba(35,200,153,1)',
					data: data,
					lineTension: 0,
				}
			]
		})
		}
		getStockData('TSLA');
},[]);

stockDataそのものをLineコンポーネントのpropsのdataに設定します。


<div className="chart">
	<Line data={stockData} options={options} />
</div>

ブラウザで確認すると1ヶ月のTeslaの株価の遷移を確認することができます。

Teslaの1ヶ月の株価の遷移
Teslaの1ヶ月の株価の遷移

GoogleのTeslaの情報と比較すると正しくグラフが表示されていることが確認できます。

Googleの株価データ
Googleの株価データ

縦軸の株価がわかるようにoptionsのyAxesのdisplayを削除してグラフの点にマウスを合わせるとマウスを合わせた日の株価も確認することができます。

縦軸の表示とTooltip
縦軸の表示とTooltip

銘柄変更や期間変更の機能を追加するだけでオリジナルの投資情報サイトを構築することも可能です。本文書の範囲ではアメリカの銘柄しか表示されませんが。。。