Python 株価チャートのインジケータで買い時をしりたいのだ!
株の買い時を探るべく、売り買いのサインの参考になりそうなテクニカルインジケーターをチャートに表示してみた。
まぁ、Yahoo Financeを見ればわかる事なので、それほど価値はないが、対象期間の色を変えて見やすくしたり、期間や銘柄を自由にカスタマイズできる点には価値があるかもしれない。また、VIXとか他の指標を合わせて見るのには便利だろう。(あと、これを機能拡張すれば、毎日、自動で動かして、条件にヒットした時にメールを送るみたいなこともできるだろう。)
とは言っても、売り買いの完璧なインジケータなど存在しない。その時々で注視すべきポイントは変わっていくように思う。
まぁ、でも、そんな中で、過去と比較すると、どれくらいの稀な状況にあるのか、みたいな判断の参考程度にはなるように思う。
という注意点を述べた上で、プログラムを公開したい。
では。
0.事前準備
ライブラリのインストール1
pip install yfinance
ライブラリのインストール2
pip install mpl_finance
1.プログラム
下記のプログラムをコピペして実行してください。
期間は「2020/1/1〜現在」です。必要に応じて変更してください。
import yfinance as yf
import datetime
import pandas as pd
import numpy as np
import mpl_finance
import matplotlib.pyplot as plt
%matplotlib inline
start = datetime.date(2020,1,1)
end = datetime.date.today()
# 株価データを取得
df = yf.download('^GSPC', start=start, end=end)
df.insert(0, "index",[X for X in range(len(df))])
df2 = pd.DataFrame(yf.download('^VIX', start=start, end=end)["Adj Close"])
df2.insert(0, "index",[X for X in range(len(df2))])
def macd(df):
FastEMA_period = 12 # 短期EMA
SlowEMA_period = 26 # 長期EMA
SignalSMA_period = 9 # SMA
df["MACD"] = df["Adj Close"].ewm(span=FastEMA_period, adjust=False, min_periods=FastEMA_period).mean() - df["Adj Close"].ewm(span=SlowEMA_period, adjust=False, min_periods=SlowEMA_period).mean()
df["Signal"] = df["MACD"].ewm(span=SignalSMA_period, adjust=False, min_periods=SignalSMA_period).mean()
df['MACD_h'] = df["MACD"] - df["Signal"]
return df
def rsi(df):
window_length=14
delta = df['Adj Close'].diff()
# Get rid of the first row, which is NaN since it did not have a previous
# row to calculate the differences
delta = delta[1:]
# Make the positive gains (up) and negative gains (down) Series
up, down = delta.clip(lower=0), delta.clip(upper=0).abs()
# Calculate the RSI based on RMA/SMMA/MMA
# Reminder: Try to provide at least `window_length * 4` data points!
# Note: This should most closely match TradingView.
alpha = 1 / window_length
roll_up = up.ewm(alpha=alpha).mean()
roll_down = down.ewm(alpha=alpha).mean()
rs = roll_up / roll_down
df["RSI"] = 100.0 - (100.0 / (1.0 + rs))
return df
# MACD算出
df = macd(df)
# RSI算出
df = rsi(df)
# チャート定義
fig, ax = plt.subplots(4, figsize=(16, 10), sharex=True, gridspec_kw={'height_ratios': [6,2,2,2]})
mpl_finance.candlestick_ohlc(ax[0], df.values, width=0.5, colorup='r', colordown='b' )
# MACDをプロット
ax[1].plot(df["index"], df["MACD"], label="MACD")
ax[1].plot(df["index"], df["Signal"], label="Signal")
# RSIをプロット
ax[2].plot(df["index"].iloc[14:], df["RSI"].iloc[14:], label="RSI")
# VIXをプロット
ax[3].plot(df["index"], df2["Adj Close"], label="VIX")
# 対象期間の塗りつぶし(RSI)
for i in range(len(df)):
if df["RSI"].iloc[i] <= 40:
ax[0].axvline(i ,color='skyblue',linewidth=1 ,alpha=0.3)
ax[2].axvline(i ,color='skyblue',linewidth=1 ,alpha=0.3)
if df["RSI"].iloc[i] >= 70:
ax[0].axvline(i ,color='pink',linewidth=1 ,alpha=0.3)
ax[2].axvline(i ,color='pink',linewidth=1 ,alpha=0.3)
ax[2].axhline(40 ,color='gray',linewidth=1 ,alpha=0.3)
ax[2].axhline(70 ,color='gray',linewidth=1 ,alpha=0.3)
# 対象期間の塗りつぶし(MACD)
for i in range(len(df)-1):
if (df["MACD"].iloc[i+1] < df["Signal"].iloc[i+1] )and (df["MACD"].iloc[i] > df["Signal"].iloc[i] ):
ax[0].axvline(i ,color='red',linewidth=1 ,alpha=1.0)
ax[1].axvline(i ,color='red',linewidth=1 ,alpha=1.0)
if (df["MACD"].iloc[i+1] > df["Signal"].iloc[i+1] )and (df["MACD"].iloc[i] < df["Signal"].iloc[i] ):
ax[0].axvline(i ,color='blue',linewidth=1 ,alpha=1.0)
ax[1].axvline(i ,color='blue',linewidth=1 ,alpha=1.0)
# 対象期間の塗りつぶし(VIX)
for i in range(len(df2)):
if (df2["Adj Close"].iloc[i] >= 30):
ax[0].axvline(i,0,0.1 ,color='orange',linewidth=1 ,alpha=0.8)
ax[3].axvline(i ,color='orange',linewidth=1 ,alpha=0.8)
ax[3].axhline(30 ,color='gray',linewidth=1 ,alpha=0.3)
ax[0].set_title("S&P 500")
ax[1].legend()
ax[2].legend()
ax[3].legend()
ax[3].tick_params(axis='x', labelrotation=45)
# X軸を調整
plt.xticks([x for x in range(0,len(df),20)], [x.strftime('%Y-%m-%d') for x in df.asfreq("28D").index])
fig.autofmt_xdate()
plt.grid(False)
# グラフを表示
plt.show()
display(df.iloc[-5:,7:])
display(df2.iloc[-5:])
2.実行結果
下記のようなチャートが出力されます。
RSIで売られ過ぎ、買われ過ぎの水準の高さを確認し、
MACDで売り買いのタイミングを確認し、
VIXでボラティリティの高さのレアさを確認できます。
つまり、買う時は、オレンジでVIXの高さを確認し、売られ過ぎを薄い青で確認し、青線でMACDのゴールデンクロスが確認できます。
逆に、売る時は、VIXの高さを目視して、買われ過ぎを薄い赤で確認し、赤線でMACDのデッドクロスが確認できます。
一般的に意識されるようなパラメータを設定したつもりですが、必要に応じてパラメータを変更したり、銘柄を変更して使ってみてください。
みなさんに幸がありますように!
3.参考文献
Web上で公開されているRSIやMACDのプログラムは結構あるのだが、Yahoo Financeの値と乖離しているものが多かった。どうやら、指数移動平均(単純移動平均)の計算の仕方で差(誤り)が発生しているようだった。そこで、いくつか試してみた中で、Yahoo Financeの値に近いものを採用する事にした。正しく動作することを確認したつもりですが、まぁ、それでも、誤っている可能性もあるので、気になるタイミングでYahoo Financeなどの信頼できる情報を確認してください。以下、参考にした文献を載せておきます。
参考文献1
参考文献2
4.おまけ
ワクチンを打つと、副作用で体がだるくなるらしいのだが、ここ半年ぐらいやる気がでない。ワクチンを打つ前からずっと副作用がでている状態だ。ワクチン恐るべし!(最近、ワクチン打ちました。)
というのは冗談だけど、これではいけない!と思って、やる気を奮い立たせ、最近はPythonの記事を書いたり、リングフィットやロストジャッジメントやAPEXのゲームをやっている。ゲームと聞いて「のんきだなー」と思うかもしれないが、これが結構、能力主義で上下関係が厳しい世界なのだ!
APEXというのは、三人がパーティーになって、他のパーティと銃で撃ち合いをするゲームなのだが、味方の小学生にボイスチャットで「ヘタクソだなー」とヤジられたり、ダメ出しをされたりしながら肩身を狭くしてゲームし、悔しくて涙で枕を濡らす日々である。
どうやら聞くところによると、小学生の子供たちはゲーム前にZoomでミーティングをして作戦会議をしているらしい。世の中も変わったものだ。
自分の子供時代を思い返して見ると、友達の家に5,6人が集まって、1人がゲームしているのを見ていたことが多かったように思う。
1人がドラゴンクエストをやっているのを、みんなで眺めていたのだ。
そんなある時、ゲームを持っていない私は、よく分からないながら見ていると、何やら「つうこんのいちげき」にみんながどよめいている。何かすごい事が起きているらしい。
いたずら心に火が付いた私は、それなら、みんなを驚かしてやろう!と思って、ファミコンのツーコン(二つめのコントローラー)をこっそり押してみたぐらいの理解度だった。ツーコンのボタンを押せば、「ツーコンの一撃」が出るものだと思ってこっそりとボタンを押したのだ。しかし、それをたまたま見ていた友達がいて「そっちのコントローラは使えないよ。」と冷静に指摘された事があった。
後々、わかったのだが、「つーこんのいちげき」は「痛恨の一撃(つうこんのいちげき)」であって、「ツーコン(2つめのコントローラー)の一撃」ではないのだ。
私の小学生時代はそんなレベルだったのに、今や小学生がZoomで遠隔ミーティングを開いて作戦会議をしてゲームをするというのだから、すごい時代になったものだ。
なんの話かわからなくなりましたが、
「痛恨の一撃」の教訓が、何かの参考になれば幸いです。
では!
追記(2021/12/24)
プログラムをカスタマイズしたので、有料のおまけに付けておきます。
更に追記(2022/1/21)
ストキャスティクスの指標を追加。(後述)
更に追記(2022/2/3)
Price by Volume(価格帯別出来高)の指標を追加。(後述)
更に改修(2022/02/06)
出来高が高い時に色を濃くする機能を追加。(後述)
更に改修(2023/05/05)
Google Cloud のCloud Functions 上でスクリプトが動くようにし、メールでチャートの画像を送信するコーディングを作成してみました。自動で毎日、定刻にチャート画像をメール送付する時に使えると思います。
下記の様なチャートが指定した銘柄分、出力されます。
ここから先は
¥ 500
この記事が気に入ったらチップで応援してみませんか?