はじめに
株式市場は気まぐれで、よく変化します。人間は歴史の中で雄牛を飼い慣らそうとしてきたが、決して成功しなかった。株式市場の予測が難しいのは、あまりにも多くの要因が絡み合っているからであり、そのような分散を考慮したモデルを作成することはほとんど不可能です。しかし、近年の機械学習やコンピューティングの進歩により、機械が大量のデータを処理できるようになりました。これにより、過去の証券取引所のデータを利用し、トレンドを分析することができるようになります。この記事では、pythonとGridDBを活用して、Googleの過去1年間の株価データを分析します。
株価は毎日保存されます。そのため、日々の株価データは非常に大きくなります。データを保存するデータベースとして、大規模なデータセットをうまく扱えることで知られているGridDBを使用します。GridDBは、スケーラブルで信頼性が高いと同時に、高いパフォーマンスを保証します。GridDBは使いやすく、ほとんどの最新プログラミング言語で動作します。今回の記事では、pythonを使ってファンダメンタルな株価分析を行い、その結果を視覚化してみます。
セットアップ
GridDBのセットアップ
GridDBのpythonクライアントのセットアップはこちらのビデオをご覧ください。始める前に、以下のエンドポイントが正しく定義されている必要があります。
export LIBRARY_PATH=<span class="hljs-variable">$LIBRARY_PATH</span><span class="hljs-symbol">:/usr/share/doc/griddb-c-client</span> [insert path to c_client]
export PYTHONPATH=<span class="hljs-variable">$PYTHONPATH</span><span class="hljs-symbol">:</span>[insert path to python_client]
export LIBRARY_PATH=<span class="hljs-variable">$LD_LIBRARY_PATH</span><span class="hljs-symbol">:</span>[insert path to c_client/bin]
Pythonライブラリ
今回の解析にはpython 3.6
を使用します。ライブラリのインストールにはpip
を使用します。
pip <span class="hljs-keyword">install</span> pandas
pip <span class="hljs-keyword">install</span> plotly
データ収集
GridDBは、データにアクセスするための優れたインターフェースを提供します。GridDB python client blogでは、GridDBデータベースをリンクし、すべてのデータをpandasのデータフレームにプッシュする方法を詳しく説明しています。ここではyahoo financeを使ってGoogle stockのデータを取得します。Yahoo! Finance 1年分のデータをGOOG.csv
に保存します。
このデータをSQLクエリでGridDBに挿入・取得することができます。
データを挿入するには:
<span class="hljs-built_in">import</span> griddb_python as griddb
<span class="hljs-built_in">import</span> pandas as pd
<span class="hljs-comment"># Initialize container</span>
<span class="hljs-attr">gridstore</span> = factory.get_store(<span class="hljs-attr">host=</span> host, <span class="hljs-attr">port=port,</span>
<span class="hljs-attr">cluster_name=cluster_name,</span> <span class="hljs-attr">username=uname,</span>
<span class="hljs-attr">password=pwd)</span>
<span class="hljs-attr">conInfo</span> = griddb.ContainerInfo(<span class="hljs-string">"GOOGL"</span>,
[[<span class="hljs-string">"Date"</span>, griddb.Type.TIMESTAMP],
[<span class="hljs-string">"Open"</span>,griddb.Type.LONG],
[<span class="hljs-string">"High"</span>, griddb.Type.LONG],
[<span class="hljs-string">"Low"</span>,griddb.Type.LONG]
[<span class="hljs-string">"Close"</span>, griddb.Type.LONG]
[<span class="hljs-string">"Adj. Close"</span>, griddb.Type.LONG]
[<span class="hljs-string">"Volume"</span>, griddb.Type.LONG]],
griddb.ContainerType.COLLECTION, True)
<span class="hljs-attr">cont</span> = gridstore.put_container(conInfo)
cont.create_index(<span class="hljs-string">"Date"</span>, griddb.IndexType.DEFAULT)
<span class="hljs-attr">data</span> = pd.read.csv(<span class="hljs-string">"GOOG.csv"</span>)
<span class="hljs-comment">#Add data</span>
for i <span class="hljs-keyword">in</span> range(len(data)):
<span class="hljs-attr">ret</span> = cont.put(data.iloc[i, :])
なお、このプロセスは、Yahoo Finacneからの定期的な問い合わせにも自動化することができます。 以下のSQLクエリを使用して、GridDBからデータを取得することができます。
query = cont.query("<span class="hljs-keyword">select</span> * <span class="hljs-keyword">where</span> <span class="hljs-built_in">Date</span> > <span class="hljs-keyword">TIMESTAMPADD</span>(<span class="hljs-keyword">YEAR</span>, <span class="hljs-keyword">NOW</span>(), <span class="hljs-number">-1</span>)<span class="hljs-string">")</span>
データ分析
pandas
を使ってデータを読み込むことができます。
<span class="hljs-keyword">import</span> pandas <span class="hljs-built_in">as</span> pd
googf = pd.read_csv(<span class="hljs-string">"GOOG.csv"</span>)
これがストックデータのイメージです:
それぞれの列は以下のように解釈します:
- Date: 取引日の日付
- Open: Dateの最初の取引価格
- High: Dateで取引されている株式の最高値
- Low: Dateで取引されている株式の最低価格
- Close: Dateの最後の取引価格
- Adj Close: これは、すべての配当金が分割された後の終値と定義されます
- Volume: Dateに取引された株式数
まず、そのデータを折れ線グラフで可視化します。pandasのプロット機能を使って、終値と取引量をプロットします。
googf<span class="hljs-string">[["Close"]]</span>.plot()
googf<span class="hljs-string">[["Volume"]]</span>.plot()
取引量と終値には逆の関係があることがわかります。この関係は、金融の世界ではよくあることです。株価の終値が下がった場合、人々は特定の銘柄を取引する可能性が高くなります。しかし、このデータは非常にスパイキーであることがわかります。このスパイキーさは、価格変動を導く微妙な市場の力があるからです。
次に、OHLCチャートを使ってデータを視覚化してみましょう。OLHC(open, high, low, and close)チャートは、ある日付のオープン値、ハイ値、ロー値、クローズ値を記述した金融チャートです。
水平方向のセグメントはオープン値とクローズ値を、線の先端はロー値とハイ値を表しています。閉鎖値が開放値よりも高いポイントを上昇(緑)、閉鎖値が開放値よりも低いポイントを下降(赤)と呼びます。
これをplotlyを使ってプロットしていきます。
<span class="hljs-keyword">import</span> plotly.graph_objects <span class="hljs-keyword">as</span> go
<span class="hljs-title">fig</span> = go.<span class="hljs-type">Figure</span>(<span class="hljs-class"><span class="hljs-keyword">data</span>=go.<span class="hljs-type">Ohlc</span>(<span class="hljs-title">x</span>=<span class="hljs-title">googf</span>['<span class="hljs-type">Date</span>'],
<span class="hljs-title">open</span>=<span class="hljs-title">googf</span>['<span class="hljs-type">Open</span>'],
<span class="hljs-title">high</span>=<span class="hljs-title">googf</span>['<span class="hljs-type">High</span>'],
<span class="hljs-title">low</span>=<span class="hljs-title">googf</span>['<span class="hljs-type">Low</span>'],
<span class="hljs-title">close</span>=<span class="hljs-title">googf</span>['<span class="hljs-type">Close</span>']))</span>
<span class="hljs-title">fig</span>.show()
3月にgoogle株の下落があったことがわかります。さらに、赤線は後半よりも前半の方が目立っています。これは、例えばCOVIDの流行のような複数の要因が考えられます。後日の記事では、Covidのスプレッドデータを使って株価の動向を分析してみたいと思います。
次に、範囲スライダを使って3月にズームインします。
縦棒が長くなり、始値と終値の差が大きくなっていることがわかります。これは、当時の市場に大きな変動があったことを示しています。 これらのチャートは、通常のラインプロットよりもはるかに直感的です。
市場動向の分析
移動平均線
次に、移動平均を計算します。株式の移動平均は、継続的に更新される平均価格を作成しています。移動平均は、トレンドの変化を確認するために使用され、将来の予測には使用されません。
短期、中期、長期の移動平均を算出し、市場の動向を分析することができます。
- 短期: タイムフレームは5~20日で、数日から数週間続くトレンドを見極めるために使用されます。
- 中期: 時間枠は20~65日で、数ヶ月続くトレンドを見極めるために使用されます。
- 長期: 時間枠は65~200日で、数年に及ぶトレンドを見極めるために使用されます。
1年分のデータしかないので、短いトレンドを見ていきます。5日、20日、50日の移動平均を計算し、それを使ってトレンドを分析していきます。
pythonで移動平均を計算するには、rolling関数を使います。
単純移動平均
N日間の単純移動平均は、N日間の終値の平均値として定義することができます。期間を1日ずらして、N個の範囲ごとに平均値を計算します。以下はそのコードです。
googf[<span class="hljs-string">'SMA5'</span>] = googf<span class="hljs-selector-class">.Close</span><span class="hljs-selector-class">.rolling</span>(<span class="hljs-number">5</span>).mean()
googf[<span class="hljs-string">'SMA20'</span>] = googf<span class="hljs-selector-class">.Close</span><span class="hljs-selector-class">.rolling</span>(<span class="hljs-number">20</span>).mean()
googf[<span class="hljs-string">'SMA50'</span>] = googf<span class="hljs-selector-class">.Close</span><span class="hljs-selector-class">.rolling</span>(<span class="hljs-number">50</span>).mean()
fig = go.Figure(data=[go.Ohlc(x=googf[<span class="hljs-string">'Date'</span>],
open=googf[<span class="hljs-string">'Open'</span>],
high=googf[<span class="hljs-string">'High'</span>],
low=googf[<span class="hljs-string">'Low'</span>],
close=googf[<span class="hljs-string">'Close'</span>], name = <span class="hljs-string">"OHLC"</span>),
go.Scatter(x=googf<span class="hljs-selector-class">.Date</span>, y=googf<span class="hljs-selector-class">.SMA5</span>, line=dict(<span class="hljs-attribute">color</span>=<span class="hljs-string">'orange'</span>, width=<span class="hljs-number">1</span>), name=<span class="hljs-string">"SMA5"</span>),
go.Scatter(x=googf<span class="hljs-selector-class">.Date</span>, y=googf<span class="hljs-selector-class">.SMA20</span>, line=dict(<span class="hljs-attribute">color</span>=<span class="hljs-string">'green'</span>, width=<span class="hljs-number">1</span>), name=<span class="hljs-string">"SMA20"</span>),
go.Scatter(x=googf<span class="hljs-selector-class">.Date</span>, y=googf<span class="hljs-selector-class">.SMA50</span>, line=dict(<span class="hljs-attribute">color</span>=<span class="hljs-string">'blue'</span>, width=<span class="hljs-number">1</span>), name=<span class="hljs-string">"SMA50"</span>)])
fig.show()
黄色の線は5日間の移動平均、緑の線は20日間のトレンド、青の線は50日間のトレンドを示しています。再び3月にズームインしてみましょう。3月の初めと終わりにクロスオーバーが見られます。つまり、青線が緑線を上回り、3月の終わりには再び下降しています。これは、3月の初めに市場が弱気になり、その後、再び持ち直したことを示しています。
単純移動平均は、大きな価格変動に対する反応が遅いことがあります。この効果を測るために、投資家は指数移動平均を使用します。
指数移動平均
指数移動平均は、再度平均値を計算しますが、より最近のデータを重視します。
ewm関数を使い、5日、20日、50日の指数移動平均を取得します。以下はそのコードです。
googf[<span class="hljs-string">'EMA5'</span>] = googf<span class="hljs-selector-class">.Close</span><span class="hljs-selector-class">.ewm</span>(span=<span class="hljs-number">5</span>, adjust=False).mean()
googf[<span class="hljs-string">'EMA20'</span>] = googf<span class="hljs-selector-class">.Close</span><span class="hljs-selector-class">.ewm</span>(span=<span class="hljs-number">20</span>, adjust=False).mean()
fig = go.Figure(data=[go.Ohlc(x=googf[<span class="hljs-string">'Date'</span>],
open=googf[<span class="hljs-string">'Open'</span>],
high=googf[<span class="hljs-string">'High'</span>],
low=googf[<span class="hljs-string">'Low'</span>],
close=googf[<span class="hljs-string">'Close'</span>], name = <span class="hljs-string">"OHLC"</span>),
go.Scatter(x=googf<span class="hljs-selector-class">.Date</span>, y=googf<span class="hljs-selector-class">.EMA5</span>, line=dict(<span class="hljs-attribute">color</span>=<span class="hljs-string">'orange'</span>, width=<span class="hljs-number">1</span>), name=<span class="hljs-string">"EMA5"</span>),
go.Scatter(x=googf<span class="hljs-selector-class">.Date</span>, y=googf<span class="hljs-selector-class">.EMA20</span>, line=dict(<span class="hljs-attribute">color</span>=<span class="hljs-string">'green'</span>, width=<span class="hljs-number">1</span>), name=<span class="hljs-string">"EMA20"</span>)])
fig.show()
ここでは、3月の初めと終わりに、再び同じようなダブルクロスオーバーが見られます。しかし、そのギャップはそれほど大きくありません。これは、市場のトレンドが思ったよりも安定していることを示唆しています。
移動平均は簡単に計算できますが、過去のデータに基づいているため限界があります。変動の激しい銘柄にはあまり役に立たないでしょう。
結論
この記事では、まずGridDBとpythonを使って市場のトレンド分析を行う方法を学びました。OHLPプロットと移動平均の分析を行いました。
移動平均線については、こちら。
ソースコード
ブログの内容について疑問や質問がある場合は Q&A サイトである Stack Overflow に質問を投稿しましょう。 GridDB 開発者やエンジニアから速やかな回答が得られるようにするためにも "griddb" タグをつけることをお忘れなく。 https://stackoverflow.com/questions/ask?tags=griddb