pythonのライブラリ機能で遊ぼう

「株価予想(+自動売買)python」

作ろうと思った理由

アイデアを出す段階で以下のものが上がっていた。
そこで株価予想と自動売買につながるような
pythonコードを書こうと考えた。

実際のコード

2021年01月01日〜2023年11月05日現在のチャート

  1. import datetime
  2. import pandas_datareader.data as web
  3. import yfinance
  4. # 株価データを取得する関数
  5. def get_stock_data(meigara_cd:str, from_date:str, to_date:str):
  6.     
  7.     """
  8.     ====================================================
  9.     引数情報
  10.     ・meigara_cd(str): 銘柄コード
  11.     ・from_date(str): 株価取得期間(開始日)
  12.     ・to_date(str): 株価取得期間(終了日)
  13.     ====================================================
  14.     """
  15.     # 株価データを取得
  16.     df = web.DataReader(name = meigara_cd + ".jp", # 銘柄コード
  17.                         data_source = 'stooq', # 株価データソース
  18.                         start = from_date, # 株価取得期間(開始日)
  19.                         end = to_date, # 株価取得期間(終了日)
  20.                        )
  21.     
  22.     return df
  23. # 本日日付を取得する関数
  24. def today() -> str:
  25.     return str(datetime.date.today())
  26.     # ==========================================================
  27. # 関数実行
  28. # ==========================================================
  29. # 引数情報
  30. meigara_cd = "6758" # Sony銘柄
  31. from_date = "2021-01-01" # 開始日
  32. to_date = today() # 終了日
  33. # 関数実行
  34. data = get_stock_data(meigara_cd,from_date,to_date)
  35. # ==========================================================
  36. # 結果確認
  37. # ==========================================================
  38. # 出力
  39. print(data)
  40. # 出力イメージ
  41. # Open High Low Close Volume
  42. # Date
  43. # 2023-08-17 12000 12140 11920 12130 2960800
  44. # 2023-08-16 12200 12205 12010 12010 3069300
  45. # 2023-08-15 12285 12320 12195 12220 3326700
  46. # 2023-08-14 12415 12490 12075 12175 6287400
  47. # 2023-08-10 12385 12635 12115 12565 7794900
  48. import matplotlib.pyplot as plt
  49. # ==========================================================
  50. # データ取得
  51. # ==========================================================
  52. # 引数情報
  53. meigara_cd = "6758" # Sony銘柄
  54. from_date = "2021-01-01" # 開始日
  55. to_date = today() # 終了日
  56. # 関数実行
  57. data = get_stock_data(meigara_cd,from_date,to_date)
  58. # ==========================================================
  59. # グラフ可視化
  60. # ==========================================================
  61. # グラフ描画
  62. plt.plot_date(data.index, data["Close"], linestyle='solid')
  63. # 書式設定
  64. plt.xlabel("Date") # X軸ラベル
  65. plt.ylabel("Stock (yen)") # Y軸ラベル
  66. plt.gcf().autofmt_xdate() # X軸値を45度回転
  67. plt.show() # グラフ表示

【過去予想】2021年01月01日〜2023年11月05日現在のチャート

  1. import datetime
  2. import pandas_datareader.data as web
  3. # 株価データを取得する関数
  4. def get_stock_data(meigara_cd:str, from_date:str, to_date:str):
  5.     
  6.     """
  7.     ====================================================
  8.     引数情報
  9.     ・meigara_cd(str): 銘柄コード
  10.     ・from_date(str): 株価取得期間(開始日)
  11.     ・to_date(str): 株価取得期間(終了日)
  12.     ====================================================
  13.     """
  14.     # 株価データを取得
  15.     df = web.DataReader(name = meigara_cd + ".jp", # 銘柄コード
  16.                         data_source = 'stooq', # 株価データソース
  17.                         start = from_date, # 株価取得期間(開始日)
  18.                         end = to_date, # 株価取得期間(終了日)
  19.                        )
  20.     
  21.     return df
  22. # 本日日付を取得する関数
  23. def today() -> str:
  24.     return str(datetime.date.today())
  25.     # ==========================================================
  26. # 関数実行
  27. # ==========================================================
  28. # 引数情報
  29. meigara_cd = "6758" # Sony銘柄
  30. from_date = "2023-01-01" # 開始日
  31. to_date = today() # 終了日
  32. # 関数実行
  33. data = get_stock_data(meigara_cd,from_date,to_date)
  34. # ==========================================================
  35. # 結果確認
  36. # ==========================================================
  37. # 出力
  38. print(data)
  39. # 出力イメージ
  40. # Open High Low Close Volume
  41. # Date
  42. # 2023-08-17 12000 12140 11920 12130 2960800
  43. # 2023-08-16 12200 12205 12010 12010 3069300
  44. # 2023-08-15 12285 12320 12195 12220 3326700
  45. # 2023-08-14 12415 12490 12075 12175 6287400
  46. # 2023-08-10 12385 12635 12115 12565 7794900
  47. import matplotlib.pyplot as plt
  48. # ==========================================================
  49. # データ取得
  50. # ==========================================================
  51. # 引数情報
  52. meigara_cd = "6758" # <-ここに銘柄コード四桁を入れましょう
  53. from_date = "2021-01-01" # <-開始日(チャートの一番左端の日を設定しましょう)
  54. to_date = today() # 終了日(ここにチャートの右端の日を設定しましょう)
  55. # 関数実行
  56. data = get_stock_data(meigara_cd,from_date,to_date)
  57. # ==========================================================
  58. # グラフ可視化
  59. # ==========================================================
  60. # グラフ描画
  61. plt.plot_date(data.index, data["Close"], linestyle='solid')
  62. # 書式設定
  63. plt.xlabel("Date") # X軸ラベル
  64. plt.ylabel("Stock (yen)") # Y軸ラベル
  65. plt.gcf().autofmt_xdate() # X軸値を45度回転
  66. plt.show() # グラフ表示
  67. from prophet import Prophet
  68. import pandas as pd
  69. from prophet.plot import plot_plotly
  70. import plotly.offline as py
  71. # ==========================================================
  72. # データ取得
  73. # ==========================================================
  74. # 引数情報
  75. meigara_cd = "6758" # <-ここに銘柄コード四桁を入れましょう
  76. from_date = "2022-01-01" # <-開始日(チャートの一番左端の日を設定しましょう)
  77. to_date = today() # 終了日(ここにチャートの右端の日を設定しましょう)
  78. # 関数実行
  79. data = get_stock_data(meigara_cd,from_date,to_date)
  80. # Prophet投入用インプットデータ作成
  81. df = pd.DataFrame({"ds":data.index, "y":data["Close"]}).reset_index(drop=True)
  82. # ==========================================================
  83. # 時系列モデル作成
  84. # ==========================================================
  85. # モデルインスタンス
  86. proph = Prophet()
  87. # モデル学習
  88. proph.fit(df)
  89. # ==========================================================
  90. # 予測
  91. # ==========================================================
  92. # 未来予測用のデータフレーム
  93. future = proph.make_future_dataframe(periods=365)
  94. # 時系列を予測
  95. forecast = proph.predict(future)
  96. # ==========================================================
  97. # 予測(可視化)
  98. # ==========================================================
  99. py.init_notebook_mode()
  100. figure = plot_plotly(proph, # 時系列モデル
  101.                      forecast, # 予測結果
  102.                     )
  103. # 出力
  104. py.iplot(figure)
また、同じ期間の実際のグラフと過去予想のグラフを、
pythonライブラリ「OpenCV」という画像の差異を検出するツールを使ったところ、
全く違いがなかったので過去予想をすると実際のグラフと同じものを出すことがわかった。
  1. import cv2
  2. # Load images
  3. img1 = cv2.imread('xbp/de12/images/sony_exceptFigure_1.png')
  4. img2 = cv2.imread('xbp/de12/images/sony_real.png')
  5. # Convert images to grayscale
  6. img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
  7. img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
  8. # Calculate absolute difference between the two images
  9. diff = cv2.absdiff(img1_gray, img2_gray)
  10. # Apply threshold to identify significant differences
  11. thresh = 30
  12. diff[diff < thresh] = 0
  13. diff[diff >= thresh] = 255
  14. # Find contours of significant differences
  15. contours, hierarchy = cv2.findContours(diff, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  16. # Draw rectangles around the differences
  17. for contour in contours:
  18.     (x, y, w, h) = cv2.boundingRect(contour)
  19.     cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 0, 255), 2)
  20. # Display the output image with differences highlighted
  21. cv2.imshow('Output', img1)
  22. cv2.waitKey(0)
  23. cv2.destroyAllWindows()
【python】2枚の画像の違いを検出する方法【初心者】 実際に違うと赤文字で指摘される。
上記のサイトを見るとすぐにわかる。
また、文字でも差異を見つけられるそう。
基本的に外部サイトをコピペしたものではあるが、
一部y軸stockの通貨単位がわからなかったので、
改変してある。

未来の株価予想

本題の未来の株価予想だが、
これは、エラーが発生して不可能だった。
以下のが未来の株価予想のコードである。
  1. import numpy as np
  2. import pandas as pd
  3. from sklearn.model_selection import train_test_split
  4. from sklearn.linear_model import LinearRegression
  5. # データを読み込む(例:AAPL株価データ)
  6. data = pd.read_csv('AAPL.csv') # データファイルのパスを指定
  7. # 必要な特徴量を選択
  8. data = data[['Open', 'High', 'Low', 'Volume', 'Adj Close']]
  9. # 予測対象の特徴量を選択(例:Adj Closeを予測)
  10. forecast_col = 'Adj Close'
  11. data['label'] = data[forecast_col].shift(-1)
  12. # 欠損値を削除
  13. data = data.dropna()
  14. # 特徴量とラベルを分割
  15. X = np.array(data.drop(['label'], 1))
  16. y = np.array(data['label'])
  17. # データをトレーニングセットとテストセットに分割
  18. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
  19. # 線形回帰モデルをトレーニング
  20. clf = LinearRegression()
  21. clf.fit(X_train, y_train)
  22. # 未来の株価を予測
  23. forecast_set = clf.predict(X_lately)
  24. # 予測結果を表示
  25. print(forecast_set)
原因はバージョンの違いか、
コードの記述に過不足があったからだと考えている。

まとめ

今回は過去の株価のチャートをある程度正確に表示することには成功した。
検証のために間違い探しのライブラリの活用を経験し成功例を得た。
しかし、未来の株価予測はできなかった。

もし、できるようになった場合は、今度は自動トレードや、
ドルコスト法を使ったシステムを作りたい。

また、コードを書くプログラマーが代替されるのではないかという話を
聞くことがあるが、 今回CHATGPT3.5も使ってもコピーしても未来予想は
実現しなかったので、プログラマーがchatGPT3.5によって完全に代替されるには
まだ時間がかかりそうだと感じた。

chatGPT3.5もこう語っている。
「このコードは単純な株価予測の例であり、
実際の株価予測にはさらに多くの特徴量エンジニアリングや
モデルの最適化が必要です。また、データの前処理、モデルの評価、
モデルの再調整なども含まれます。株価予測は高度なトピックであり、
正確な予測を行うためには熟練したデータサイエンティストや
専門家のアドバイスが必要です。
このコードは教育目的で提供されたものであり、
実際のトレーディングには使用しないでください。」