kishi0114
@kishi0114

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

pythonコード質問

解決したいこと

python練習中の者です。
日経平均の株価を読み込み、その中の終値(close)について、
指標値(移動平均、ボリンジャーバンド、RSI)を作り、その指標値に対する予測モデルを作ろうとしています。
(自分は株のプロを目指しているのではなく、あくまでpythonに習熟するために練習でコード作成、デバックをしているだけです)

でエラーが起きるので解決策を教えていただきたい次第です。

発生している問題・エラー

以下のようになり、indicator_bb.bollinger_hband().values.flatten()が1次元でないことが原因のようです。

ValueError                                Traceback (most recent call last)
Cell In[30], line 31
      data = data.fillna(method='ffill')

dara['hband']=indicator_bb.bollinger_hband().values.flatten()
data['ave']=indicator_bb.bollinger_mavg().values.flatten()
data['land']=indicator_bb.bollinger_lband().values.flatten()

ValueError: Data must be 1-dimensional, got ndarray of shape (246, 1) instead

該当するソースコード

import yfinance as yf
import pandas as pd
import numpy as np
import ta 
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt

ticker = "^N225"  
data = yf.download(ticker, start="2023-01-01", end="2024-01-01")
data['MA20'] = data['Close'].rolling(window=20).mean()
data['MA50'] = data['Close'].rolling(window=50).mean()
indicator_bb = ta.volatility.BollingerBands(close=data['Close'], window=20, window_dev=2) 

data = data.fillna(method='ffill')
data['UpperBand']=indicator_bb.bollinger_hband().values.flatten()
data['ave']=indicator_bb.bollinger_mavg().values.flatten()
data['LowerBand']=indicator_bb.bollinger_lband().values.flatten()
data['RSI'] = talib.RSI(data['Close'], timeperiod=14)

data = data.dropna()

X = data[['MA20', 'MA50', 'UpperBand', 'LowerBand', 'RSI']]
y = data['Close']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
print(f"Mean Squared Error: {mse}")

plt.figure(figsize=(12, 6))
plt.plot(y_test.index, y_test, label='Actual Close', color='blue')
plt.plot(y_test.index, y_pred, label='Predicted Close', color='red', linestyle='--')
plt.title('Stock Price Prediction: Actual vs Predicted')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.show()

自分で試したこと

以下は試しましたが上と同じ配列サイズオーバーのエラーでした。

indicator_bb.bollinger_hband().values
indicator_bb.bollinger_hband().squeeze()
indicator_bb.bollinger_hband().reset_index(drop=True)

何か、私が根本的にわかっていないような感があるのですが、恐れ入りますが教えていただけるとありがたいです。

0

5Answer

こちらで再現したところ、トレースバックは以下の通りでした。

Traceback (most recent call last):
  File "/(略)/bb.py", line 21, in <module>
    data['UpperBand'] = indicator_bb.bollinger_hband().values.flatten()
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/(略)/.venv/lib/python3.12/site-packages/ta/volatility.py", line 117, in bollinger_hband
    return pd.Series(hband, name="hband")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/(略)/.venv/lib/python3.12/site-packages/pandas/core/series.py", line 584, in __init__
    data = sanitize_array(data, index, dtype, copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/(略)/.venv/lib/python3.12/site-packages/pandas/core/construction.py", line 633, in sanitize_array
    return sanitize_array(
           ^^^^^^^^^^^^^^^
  File "/(略)/.venv/lib/python3.12/site-packages/pandas/core/construction.py", line 659, in sanitize_array
    subarr = _sanitize_ndim(subarr, data, dtype, index, allow_2d=allow_2d)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/(略)/.venv/lib/python3.12/site-packages/pandas/core/construction.py", line 718, in _sanitize_ndim
    raise ValueError(
ValueError: Data must be 1-dimensional, got ndarray of shape (246, 1) instead

bollinger_hband()の呼び出しの際に、ライブラリ内部でエラーになっているため、クラスの初期化時点で渡すデータの次元数に問題があると判断しました。

そこで、ドキュメントを確認すると、Seriesである必要があるようです。
https://technical-analysis-library-in-python.readthedocs.io/en/latest/ta.html#ta.volatility.BollingerBands

よってDataFrameになっているdata['Close']の次元数を落とすために、indicator_bbの生成処理を以下のように修正したところ、該当のエラーが解消しました。

# デバッグ用の次元数確認
print(f"{data['Close'].shape=}")
print(f"{data['Close'].iloc[:, 0].shape=}")
# 修正点
indicator_bb = ta.volatility.BollingerBands(close=data['Close'].iloc[:, 0], window=20, window_dev=2)

蛇足ですが、この修正をしても、talibのimportが漏れていて次はそっちでエラーになるかと思います。
こちらの環境ではさっとtalibライブラリのビルドができなかったので、記載のエラーの修正以外は直せていません。

ご了承ください。

Tipsですが、コードブロックは言語名を入れるとハイライトが効いて幸せになれるのでおすすめです。
参考: https://qiita.com/Qiita/items/c686397e4a0f4f11683d#code---%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%8C%BF%E5%85%A5

3Like

Comments

  1. @kishi0114

    Questioner

    エラーが起きた時の修正ノウハウを垣間みさせていただき、大変勉強になります。また、今度からコードブロックにpythonを入れようと思います。
    @ivixviさんはプロのSEですか?
    ありがとうございます。

  2. お力になれたらなら幸いです。

    「プロ」と表現するとなるとまだまだな気がして気が引けますが、
    職業エンジニアではあります!

控えめに言ってすごく見にくいので、

  • コード、エラーは ```で上下を括ってください。
  • 単純にコードだけ、エラーだけを、まず掲載してほしいです。
  • コメントはありがたいですが、コメント文として、コメントアウトしておいてください

とした方が、回答も得やすいと思います。

1Like

Comments

  1. エラーコードもchatgptに投げると、回答してくれることもありますよ
    事例が多そうな単純な問題であれば解決することが多いです。

該当するソースコード は質問者さんがご自身で全て書かれたものでしょうか?もし元ネタがあるのであればそれも質問に追記ください。そちらを見た方が分かりやすいかもしれません。

1Like

Comments

  1. @kishi0114

    Questioner

    ありがとうございます、dataに書き直しました。(でもエラーでした)

indicator_bb = ta.volatility.BollingerBands(close=data['Close'], window=20, window_dev=2)

これって何か値入ってます?

1Like

Your answer might help someone💌