pythonカスタム関数§02:read_stockdata() 株価ダウンロード

Python便利なカスタム関数

カスタム関数シリーズでは、便利なオリジナル関数を紹介しています。

※カスタム関数は、一般的には「ユーザー定義関数」と呼ばれています

read_stockdata() 無料で株価をダウンロードする関数を作る

株価データをダウンロードして、数値解析をしたり、グラフを描いたりすることはpythonでは簡単にできてしまいます。

まず株価データは、pndas_datareaderというライブラリーを使います。

ライブラリはインストールが必要ですが、pipを使えば、簡単に導入できます

pip install pandas_datareader

でOK。

def read_stockdata(code='7203.JP',start='2015-01-01',end='2020-07-25',graph=True):  # ■株データダウンロード_stooq_J725
    #!pip install pandas_datareader
    from pandas_datareader import data  
    import pandas as pd
    import matplotlib.pyplot as plt
    import numpy as np

    df=data.DataReader(code,'stooq',start,end)
    df=df.sort_index()  #indexの日付をソートする
    
    print(df)
    
    if graph:
        date=df.index
        price=df['Close']
        plt.figure(figsize=(30,10))

        span01=5
        span02=25
        span03=75
        df['sma05']=price.rolling(window=span01).mean()
        df['sma25']=price.rolling(window=span02).mean()
        df['sma30']=price.rolling(window=span03).mean()

        plt.plot(date,price,label='7203',lw=5)
        plt.plot(date,df['sma05'],label='sma05')
        plt.plot(date,df['sma25'],label='sma25')
        plt.plot(date,df['sma30'],label='sma75')
        plt.title(code,color='blue',backgroundcolor='white',size=40,loc='center')
        plt.xlabel('date',color='black',size=30)
        plt.ylabel('price',color='black',size=30)
        plt.grid()
        plt.legend()
        
        plt.plot(date,price)
        plt.show()

    return df

引数の説明:

code=’7203.JP’ → 銘柄コード番号+.JP 文字列で与えます

start=’2015-01-01’ → 株価データの開始年月日

end=’2020-07-25’ → 株価データの終了年月日

graph=True → 株価の終値の推移+移動平均(5日線、25日線、75日線)を折れ線でプロットする場合は、True。グラフを描かない場合はFalseにします。

8行目:

df=data.DataReader(code,'stooq',start,end)

これによって、dfというpandasのデータフレームが戻ります。

データフレームはエクセルの表のような構造をしていて、列と行のデータです。

関数を使ってみる

それでは、この関数の使い方の例ですが、とても簡単ですよ。

def main():
    import datetime

    #今日の日付を指定
    now = datetime.datetime.now()
    end=now.strftime("%Y-%m-%d")

    #code:銘柄コード番号.JP の書式文字列を設定する
    code='7203.JP'
    #start:株価データの先頭期日
    start='2016-01-01'

    print(code,start ,end)
    df=read_stockdata(code,start,end,graph=True)
    #df=read_stockdata(code,start,end,graph=False)

    #最新の株価データ20個を表示させる
    print(df.tail(20))

#■メインプログラム
if __name__  == '__main__':
    main()
    a=input('何かキーを押してください')

この場合、実行するコードをmain()という関数の形で書いていますが、メインプログラムの場所に直接書いても構いません。メインプログラムでは、main()を呼び出して、キー入力待ち状態にしています。input()関数でエンターキーが押されるまで、表示を維持するために使っています。

株価データのグラフを描いてみよう

df=read_stockdata(code,start,end,graph=True)

graphという引数にTrueを入れて実行するとグラフができます。

以下の通り、証券コード7203のトヨタ自動車の株価データをプロットできました。

 

証券コードの部分を変えたり、日付を変えたりすることはもちろん。グラフは、pythonで実行するとズームアップしたり、自由自在に閲覧できるところが優れています。

最近のデータ部分をズームアップしてみましょう。

 

2月の終わりから新型コロナウイルスの感染が増大して、経済が大きな打撃をうけました。ほとんどの株価は暴落してしまいました。5月後半から持ち直してきまていることがわかります。しかし、7月にかけて、ふたたびじわりと下がってるように見えますね。移動平均線25日線と75日線に注目しますと、25日線が75日線を下回って交差する「デッドクロス」が出ると、また株価が低下する可能性が出てきます。

課題:stooqはデータ更新がずれる?

stooqというのは、ポーランドのサイトです。残念ながら、最新データがリアルタイムで更新されないときがあるようです。たとえば、週の終わりのデータは次の週に更新。具体的には金曜日のデータは月曜日以降に更新されるということです。

これでは、週末の休日を使った次週の作戦を立てるのに支障が出ます。これは、なんとかしないといけないので、宿題です。

最新のデータを連結させる方法

なんとか課題を解決する方法を見つけました。

最新のデータだけをスクレイピングで取得して、先のデータに連結することで実現します。詳しい解説は、また今度(^^;)ということで・・・

 

import pandas as pd
import datetime
import numpy as np
from pandas_datareader import data  
import pandas as pd
from urllib.request import urlopen
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
pd.set_option('display.width', 250)         #表示幅を変更
pd.set_option("display.max_columns", 25)    #最大表示列数
pd.set_option("display.max_colwidth", 80)   #列の最大文字数
pd.set_option("display.max_rows", 200)      #最大表示行数


def read_stockdata(code='7203.JP',start='2015-01-01',end='2020-07-25'):  # ■株データダウンロード_stooq_J725
    #!pip install pandas_datareader
    #from pandas_datareader import data  
    #import pandas as pd

    df=data.DataReader(code,'stooq',start,end)
    df=df.sort_index()  #indexの日付をソートする
    
    return df

def append_data(code1):
    #from urllib.request import urlopen
    #from bs4 import BeautifulSoup
    #import pandas as pd

    def cook(code):
      try:
          tgt = 'https://kabutan.jp/stock/kabuka?code=' + str(code)
          html = urlopen(tgt)
          bsObj = BeautifulSoup(html, 'html.parser')
          table = bsObj.findAll('table', {'class':'stock_kabuka0'})[0]
          rows = table.findAll('tr')
          for row in rows:
              rec = []
              for cell in row.findAll(['td', 'th']):
                  rec.append(cell.get_text())
              del rec[5:7]
              rec.insert(0, str(code) + '.JP')
          dish.append(rec)
          return 'Success'
      except Exception as e:
          return str(code) + ': ' + str(e)

    dish=[]
    l=[code1]
    [cook(i) for i in l]

    dish=pd.DataFrame(dish).rename(columns={0: 'code', 1: 'Date', 2:'Open', 3: 'High', 4: 'Low', 5:'Close', 6: 'Volume'})
    
    dish['Date']=pd.to_datetime('20'+dish['Date'],format='%Y-%m-%d %H:%M:%S')
    
    dish=dish.set_index('Date')

    return dish

def stock_graph(df,code_s):
    #import matplotlib.pyplot as plt

    date=df.index
    price=df['Close']
    plt.figure(figsize=(30,10))

    span01=5
    span02=25
    span03=75
    df['sma05']=price.rolling(window=span01).mean()
    df['sma25']=price.rolling(window=span02).mean()
    df['sma30']=price.rolling(window=span03).mean()

    plt.plot(date,price,label='7203',lw=5)
    plt.plot(date,df['sma05'],label='sma05')
    plt.plot(date,df['sma25'],label='sma25')
    plt.plot(date,df['sma30'],label='sma75')
    plt.title(code_s,color='blue',backgroundcolor='white',size=40,loc='center')
    plt.xlabel('date',color='black',size=30)
    plt.ylabel('price',color='black',size=30)
    plt.grid()
    plt.legend()

    plt.plot(date,price)
    plt.show()
    
    return df

def main(code_s='7203.JP',start='2016-01-01',graph_flg=True):
    #import pandas as pd
    #import datetime
    #import numpy as np

    #今日の日付を指定
    now = datetime.datetime.now()
    end=now.strftime("%Y-%m-%d")

    code=int(code_s[0:4])

    print(code_s,start ,end)
    df=read_stockdata(code_s,start,end)
    
    #最新の株価情報を取得
    df2=append_data(code)
    df2["Open"] = df2["Open"].str.replace(',','').astype(np.int)
    df2["High"] = df2["High"].str.replace(',','').astype(np.int)
    df2["Low"] = df2["Low"].str.replace(',','').astype(np.int)
    df2["Close"] = df2["Close"].str.replace(',','').astype(np.int)
    df2["Volume"] = df2["Volume"].str.replace(',','').astype(np.int)
    
    df=pd.concat([df, df2])   #結合
    
    grouped = df.groupby(level=0)  
    df = grouped.last() 

    df=df.drop('code', axis=1)
    #グラフの描画(データフレームとグラフタイトルを渡す)
    if graph_flg:
        df=stock_graph(df,code_s)
    return df
    
        
#■メインプログラム
if __name__  == '__main__':

    #code:銘柄コード番号.JP の書式文字列を設定する
    #start:株価データの先頭期日
    df=main(code_s='7203.JP',start='1999-01-01',graph_flg=True)
    
    ######## ここにはいろいろ解析するコードを入れてもよい ###########
    print(df.head(10))
    print(df.tail(30))
    #################################################################
    
    a=input('何かキーを押してください')

 

ソースコードのダウンロードができます。(.zipファイル)→ 

 

まとめ

このように株価のテクニカル分析(株価データで分析すること)はpythonでさまざまな角度から行えます。もちろんファンダメンタル分析(企業業績などの情報から分析)も重要ですが、デイトレードやスイングトレードのような短期投資では、テクニカル分析がとても有効です。

pandasというデータ分析の徹底解説を以下の記事で紹介していますよ

pandas徹底解説

今回、移動平均を使ったゴールデンクロス、デッドクロスについては詳しく述べませんでしたが、このほか、MACDなど優れた解析方法がありますので、今後掲載していきたいと思います。

コメント

タイトルとURLをコピーしました