ドル円レートの取得

ドル円レートの取得

yfinance でドル円は以下のティッカーで取得できます:
* USDJPY=X

gold: 金先物価格(USD/oz)
cpi: 米国の消費者物価指数(FREDから)
oil: WTI原油価格(USD/バレル)
usd_jpy: ドル円為替レート(1 USD = ◯◯ JPY)

取得した結果はcsvに保存し sqliteに保存することで毎回再取得せずに行えるようにしたい

mkdir auto_deel
cd auto_deel 

で作業ディレクトリ作成

 vim fetch_and_save_all.py

でスクリプト作成

import pandas as pd
import pandas_datareader.data as web
import yfinance as yf
import datetime
import os

# 保存先
csv_dir = "csv_data"
os.makedirs(csv_dir, exist_ok=True)

# 日付範囲
start = "2000-01-01"
end = datetime.datetime.today().strftime("%Y-%m-%d")

# 金価格(すでに保存済みのCSVを使用)
gold = pd.read_csv("gold_price_gc_f.csv", skiprows=[1], parse_dates=["Price"])
gold.rename(columns={"Price": "Date", "Close": "gold_price"}, inplace=True)
gold = gold[["Date", "gold_price"]]
gold.to_csv(f"{csv_dir}/gold.csv", index=False)

# CPI
cpi = web.DataReader("CPIAUCSL", "fred", start, end).reset_index()
cpi.columns = ["Date", "cpi"]
cpi.to_csv(f"{csv_dir}/cpi.csv", index=False)

# WTI
oil = web.DataReader("DCOILWTICO", "fred", start, end).reset_index()
oil.columns = ["Date", "oil"]
oil.to_csv(f"{csv_dir}/oil.csv", index=False)

# ドル円
usd_jpy = yf.download("USDJPY=X", start=start, end=end, interval="1d")[["Close"]]
usd_jpy.rename(columns={"Close": "usd_jpy"}, inplace=True)
usd_jpy.reset_index(inplace=True)
usd_jpy.to_csv(f"{csv_dir}/usd_jpy.csv", index=False)

print("✅ すべてのデータをCSVに保存しました。")

これで実行すると

Traceback (most recent call last):
  File "/Users/snowpool/aw10s/auto_deel/fetch_and_save_all.py", line 16, in <module>
    gold = pd.read_csv("gold_price_gc_f.csv", skiprows=[1], parse_dates=["Price"])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/parsers/readers.py", line 1026, in read_csv
    return _read(filepath_or_buffer, kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/parsers/readers.py", line 620, in _read
    parser = TextFileReader(filepath_or_buffer, **kwds)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/parsers/readers.py", line 1620, in __init__
    self._engine = self._make_engine(f, self.engine)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/parsers/readers.py", line 1880, in _make_engine
    self.handles = get_handle(
                   ^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/common.py", line 873, in get_handle
    handle = open(
             ^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'gold_price_gc_f.csv'

これは金価格を保存ファイルから読み込んでいるため
新規に作業ディレクトリ作成しているため、これだと動作しない

import pandas as pd
import pandas_datareader.data as web
import yfinance as yf
import datetime
import os

# 保存先ディレクトリ
csv_dir = "csv_data"
os.makedirs(csv_dir, exist_ok=True)

# 期間
start = "2000-01-01"
end = datetime.datetime.today().strftime("%Y-%m-%d")

# ✅ 金価格(GC=F)
gold = yf.download("GC=F", start=start, end=end, interval="1d")[["Close"]]
gold.rename(columns={"Close": "gold_price"}, inplace=True)
gold.reset_index(inplace=True)
gold.to_csv(f"{csv_dir}/gold.csv", index=False)

# ✅ CPI(FRED)
cpi = web.DataReader("CPIAUCSL", "fred", start, end).reset_index()
cpi.columns = ["Date", "cpi"]
cpi.to_csv(f"{csv_dir}/cpi.csv", index=False)

# ✅ 原油(WTI:FRED)
oil = web.DataReader("DCOILWTICO", "fred", start, end).reset_index()
oil.columns = ["Date", "oil"]
oil.to_csv(f"{csv_dir}/oil.csv", index=False)

# ✅ ドル円(USD/JPY)
usd_jpy = yf.download("USDJPY=X", start=start, end=end, interval="1d")[["Close"]]
usd_jpy.rename(columns={"Close": "usd_jpy"}, inplace=True)
usd_jpy.reset_index(inplace=True)
usd_jpy.to_csv(f"{csv_dir}/usd_jpy.csv", index=False)

print("✅ すべてのデータをCSVに保存しました。")

というように全て取得するに修正

これで実行すれば

/Users/snowpool/aw10s/auto_deel/fetch_and_save_all.py:16: FutureWarning: YF.download() has changed argument auto_adjust default to True
  gold = yf.download("GC=F", start=start, end=end, interval="1d")[["Close"]]
[*********************100%***********************]  1 of 1 completed
/Users/snowpool/aw10s/auto_deel/fetch_and_save_all.py:32: FutureWarning: YF.download() has changed argument auto_adjust default to True
  usd_jpy = yf.download("USDJPY=X", start=start, end=end, interval="1d")[["Close"]]
[*********************100%***********************]  1 of 1 completed
✅ すべてのデータをCSVに保存しました。

となって CSVファイルに保存ができる

次に
CSV → SQLite登録スクリプト

vim save_to_sqlite.py  

内容は

import sqlite3
import pandas as pd
import os

csv_dir = "csv_data"
db_path = "commodity_data.db"

conn = sqlite3.connect(db_path)

# 読み込むCSVファイル
datasets = {
    "gold_price": "gold.csv",
    "cpi": "cpi.csv",
    "oil": "oil.csv",
    "usd_jpy": "usd_jpy.csv"
}

for table, file in datasets.items():
    df = pd.read_csv(os.path.join(csv_dir, file), parse_dates=["Date"])
    df.to_sql(table, conn, if_exists="replace", index=False)
    print(f"✅ {table} を保存しました。")

conn.close()
print("✅ すべてのデータを SQLite に保存しました。")

これを実行すると

✅ gold_price を保存しました。
✅ cpi を保存しました。
✅ oil を保存しました。
✅ usd_jpy を保存しました。
✅ すべてのデータを SQLite に保存しました。

次に
SQLiteからデータ読み込んで相関分析する

🔹 対象テーブル
* gold_price
* cpi
* oil
* usd_jpy

SQLite → Pandas データフレーム → 日付で結合
相関分析・ヒートマップの作成

ステップ 説明 優先度
SQLite→Pandas→結合 分析のベースとなる時系列データを生成 ✅必須
相関係数・ヒートマップ 経済指標と金価格の関係性を把握 ✅必須
Prophet予測 簡単・解釈しやすい時系列予測 👍推奨
LSTM予測 複雑だが精度の高い多変量時系列予測 必要に応じて

とりあえず価格予測は置いておいて
相関関係までをやる

SQLite → pandas データ読み込み & 日付で整形

import sqlite3
import pandas as pd

# SQLiteファイルのパス
db_path = "commodity_data.db"

# SQLiteに接続
conn = sqlite3.connect(db_path)

# 各テーブルを読み込み(Dateをdatetime型に)
gold = pd.read_sql("SELECT * FROM gold_price", conn, parse_dates=["Date"])
cpi = pd.read_sql("SELECT * FROM cpi", conn, parse_dates=["Date"])
oil = pd.read_sql("SELECT * FROM oil", conn, parse_dates=["Date"])
usd_jpy = pd.read_sql("SELECT * FROM usd_jpy", conn, parse_dates=["Date"])

conn.close()

日付で結合(内部結合)
# 日付で結合(内部結合:全ての指標が揃っている日付のみ残す)
df = gold.merge(cpi, on="Date") \
         .merge(oil, on="Date") \
         .merge(usd_jpy, on="Date")

# 欠損値を除外
df.dropna(inplace=True)

# 日付順に並べ替え
df.sort_values("Date", inplace=True)

# 結果確認
print(df.head())
print(df.tail())

これを保存
# 必要に応じてCSV保存して後工程へ渡せるように

df.to_csv("merged_commodity_data.csv", index=False)
print("✅ データを merged_commodity_data.csv に保存しました。")

データの中身確認(列構成)

print("📊 列名一覧:", df.columns.tolist())

を行うようにする

結合方式の違い(用途別)
結合方式 使いどころ
how=”inner” 全ての指標が存在する日だけ使いたい(分析用)✅推奨
how=”outer” 欠損があっても全部のデータを残したい場合
how=”left” 特定の指標(例:金価格)を中心に他を揃えたい時

これらを行うスクリプト

sqlite_to_pandas_and_merge.py

を作成

これは
SQLite → pandas → 結合&保存スクリプト

内容は

import sqlite3
import pandas as pd

# SQLiteファイルのパス
db_path = "commodity_data.db"

# SQLiteに接続
conn = sqlite3.connect(db_path)

# 各テーブル読み込み(Date列をdatetime型として読み込む)
gold = pd.read_sql("SELECT * FROM gold_price", conn, parse_dates=["Date"])
cpi = pd.read_sql("SELECT * FROM cpi", conn, parse_dates=["Date"])
oil = pd.read_sql("SELECT * FROM oil", conn, parse_dates=["Date"])
usd_jpy = pd.read_sql("SELECT * FROM usd_jpy", conn, parse_dates=["Date"])

conn.close()

# 日付で内部結合(共通の日付のみ残す)
df = gold.merge(cpi, on="Date") \
         .merge(oil, on="Date") \
         .merge(usd_jpy, on="Date")

# 欠損値を除去
df.dropna(inplace=True)

# 日付順に並べ替え
df.sort_values("Date", inplace=True)

# 結果の確認
print("✅ 結合完了。データの先頭:")
print(df.head())

print("\n📊 列構成:")
print(df.columns.tolist())

# CSVとして保存
df.to_csv("merged_commodity_data.csv", index=False)
print("\n✅ merged_commodity_data.csv に保存完了")


実行結果

python sqlite_to_pandas_and_merge.py 
✅ 結合完了。データの先頭:
        Date          gold_price    cpi    oil             usd_jpy
0 2000-09-01               277.0  173.6  33.42  105.94999694824219
1 2000-11-01   263.8999938964844  174.2  33.14              108.25
2 2000-12-01  268.70001220703125  174.6  32.06  111.19000244140625
3 2001-02-01               268.5  176.0  29.88  115.41999816894531
4 2001-03-01  265.20001220703125  176.1  27.78               117.5

📊 列構成:
['Date', 'gold_price', 'cpi', 'oil', 'usd_jpy']

✅ merged_commodity_data.csv に保存完了

これで
* 📊 相関分析(ヒートマップ)
* 🔮 Prophetで金価格予測(CPI・ドル円あり)
* 🤖 LSTM構築(多変量予測)

ができるらしいのでまずは目的の相関分析を試す

相関分析+ヒートマップ表示のスクリプトを作成

 vim correlation_heatmap.py

内容は

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# CSVファイル読み込み
df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])

# 相関対象の列だけ抽出
corr_df = df[["gold_price", "cpi", "oil", "usd_jpy"]]

# 相関係数を計算
corr_matrix = corr_df.corr(method="pearson")  # 他に "spearman", "kendall" も可能

# 相関係数の表示
print("📊 相関係数:")
print(corr_matrix)

# ヒートマップ描画
plt.figure(figsize=(8, 6))
sns.heatmap(corr_matrix, annot=True, cmap="coolwarm", fmt=".2f", square=True)
plt.title("相関ヒートマップ(金価格・CPI・WTI・ドル円)")
plt.tight_layout()
plt.show()

実行結果は

📊 相関係数:
            gold_price       cpi       oil   usd_jpy
gold_price    1.000000  0.919815  0.541180  0.156031
cpi           0.919815  1.000000  0.445084  0.431734
oil           0.541180  0.445084  1.000000 -0.224121
usd_jpy       0.156031  0.431734 -0.224121  1.000000
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 30456 (\N{CJK UNIFIED IDEOGRAPH-76F8}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 38306 (\N{CJK UNIFIED IDEOGRAPH-95A2}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12498 (\N{KATAKANA LETTER HI}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12540 (\N{KATAKANA-HIRAGANA PROLONGED SOUND MARK}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12488 (\N{KATAKANA LETTER TO}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12510 (\N{KATAKANA LETTER MA}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12483 (\N{KATAKANA LETTER SMALL TU}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12503 (\N{KATAKANA LETTER PU}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 65288 (\N{FULLWIDTH LEFT PARENTHESIS}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 37329 (\N{CJK UNIFIED IDEOGRAPH-91D1}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 20385 (\N{CJK UNIFIED IDEOGRAPH-4FA1}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 26684 (\N{CJK UNIFIED IDEOGRAPH-683C}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12539 (\N{KATAKANA MIDDLE DOT}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12489 (\N{KATAKANA LETTER DO}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 12523 (\N{KATAKANA LETTER RU}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 20870 (\N{CJK UNIFIED IDEOGRAPH-5186}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:22: UserWarning: Glyph 65289 (\N{FULLWIDTH RIGHT PARENTHESIS}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 30456 (\N{CJK UNIFIED IDEOGRAPH-76F8}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 38306 (\N{CJK UNIFIED IDEOGRAPH-95A2}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12498 (\N{KATAKANA LETTER HI}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12540 (\N{KATAKANA-HIRAGANA PROLONGED SOUND MARK}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12488 (\N{KATAKANA LETTER TO}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12510 (\N{KATAKANA LETTER MA}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12483 (\N{KATAKANA LETTER SMALL TU}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12503 (\N{KATAKANA LETTER PU}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 65288 (\N{FULLWIDTH LEFT PARENTHESIS}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 37329 (\N{CJK UNIFIED IDEOGRAPH-91D1}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 20385 (\N{CJK UNIFIED IDEOGRAPH-4FA1}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 26684 (\N{CJK UNIFIED IDEOGRAPH-683C}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12539 (\N{KATAKANA MIDDLE DOT}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12489 (\N{KATAKANA LETTER DO}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 12523 (\N{KATAKANA LETTER RU}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 20870 (\N{CJK UNIFIED IDEOGRAPH-5186}) missing from font(s) DejaVu Sans.
  plt.show()
/Users/snowpool/aw10s/auto_deel/correlation_heatmap.py:23: UserWarning: Glyph 65289 (\N{FULLWIDTH RIGHT PARENTHESIS}) missing from font(s) DejaVu Sans.
  plt.show()

となるが表示されるグラフは文字化けをしている

表示されている 文字化けの原因 は、matplotlib(および seaborn)が 日本語フォント(特にCJK漢字やカタカナ)をサポートしていないフォントを使っているため

macOSの場合、ヒラギノ角ゴ ProN や AppleGothic などを使うと安定するらしい

import matplotlib.font_manager as fm
import platform

# 日本語フォント設定(macOS想定)
if platform.system() == 'Darwin':  # macOS
    plt.rcParams['font.family'] = 'Hiragino Sans'
elif platform.system() == 'Windows':
    plt.rcParams['font.family'] = 'Meiryo'
else:  # Linux(必要ならIPAフォントなど)
    plt.rcParams['font.family'] = 'IPAexGothic'


Import文の後に追加すると解決した

次に
金価格・CPI・原油価格・ドル円 を、日付をX軸にして色分けした折れ線グラフで可視化
economic_indicators_time_series.py:
経済指標の時系列データであることを折れ線グラフで表示するスクリプトの作成

 vim economic_indicators_time_series.py

内容は

import pandas as pd
import matplotlib.pyplot as plt
import platform

# ✅ 日本語フォント設定(macOSなどで文字化け防止)
if platform.system() == 'Darwin':
    plt.rcParams['font.family'] = 'Hiragino Sans'
elif platform.system() == 'Windows':
    plt.rcParams['font.family'] = 'Meiryo'
else:
    plt.rcParams['font.family'] = 'IPAexGothic'

# 📥 CSVファイル読み込み
df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])
df.sort_values("Date", inplace=True)

# 📊 折れ線グラフを描画
plt.figure(figsize=(14, 6))

plt.plot(df["Date"], df["gold_price"], label="金価格", linewidth=2)
plt.plot(df["Date"], df["cpi"], label="CPI", linewidth=2)
plt.plot(df["Date"], df["oil"], label="WTI原油", linewidth=2)
plt.plot(df["Date"], df["usd_jpy"], label="ドル円", linewidth=2)

plt.title("金価格・CPI・WTI原油・ドル円の推移")
plt.xlabel("日付")
plt.ylabel("値")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

これで表示できるけどわかりにくい

株のチャートみたいに 金価格の推移とWTI価格の推移 ドル円レートの推移 CPIの推移が一度にわかるチャートを表示したい

pip install plotly

でインストール

import pandas as pd
from plotly.subplots import make_subplots
import plotly.graph_objects as go

# データ読み込み
df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])
df.sort_values("Date", inplace=True)

# サブプロット作成(4行1列)
fig = make_subplots(
    rows=4, cols=1, shared_xaxes=True,
    subplot_titles=("① 金価格", "② WTI原油価格", "③ ドル円レート", "④ CPI(消費者物価指数)"),
    vertical_spacing=0.02
)

# 金価格
fig.add_trace(go.Scatter(x=df["Date"], y=df["gold_price"], name="金価格", line=dict(color='gold')), row=1, col=1)
# 原油価格
fig.add_trace(go.Scatter(x=df["Date"], y=df["oil"], name="WTI原油", line=dict(color='green')), row=2, col=1)
# ドル円
fig.add_trace(go.Scatter(x=df["Date"], y=df["usd_jpy"], name="ドル円", line=dict(color='red')), row=3, col=1)
# CPI
fig.add_trace(go.Scatter(x=df["Date"], y=df["cpi"], name="CPI", line=dict(color='blue')), row=4, col=1)

# レイアウト
fig.update_layout(
    height=800,
    title="金・原油・ドル円・CPIの推移(マルチチャート)",
    showlegend=False,
    xaxis4=dict(rangeslider=dict(visible=True)),  # ✅ スクロール可能
    template="plotly_white"
)

fig.show()


表示はできたけど、いまいちわかりにくい

マウスオーバーした時に一番上にマウスオーバーした日時の全ての値を表示するようにしたい

hovermode="x unified",  # ✅ ここでマウスオーバー時に全値を表示

を追記

しかしこれだと個々の値にしかならない

なので重ねて表示する

import pandas as pd
import plotly.graph_objects as go

# データ読み込み
df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])
df.sort_values("Date", inplace=True)

# 折れ線グラフを1つの図に重ねて表示
fig = go.Figure()

fig.add_trace(go.Scatter(x=df["Date"], y=df["gold_price"], name="金価格", line=dict(color='gold')))
fig.add_trace(go.Scatter(x=df["Date"], y=df["oil"], name="WTI原油", line=dict(color='green')))
fig.add_trace(go.Scatter(x=df["Date"], y=df["usd_jpy"], name="ドル円", line=dict(color='red')))
fig.add_trace(go.Scatter(x=df["Date"], y=df["cpi"], name="CPI", line=dict(color='blue')))

# レイアウト設定
fig.update_layout(
    title="金価格・WTI原油・ドル円・CPIの重ね表示チャート",
    xaxis_title="日付",
    yaxis_title="値",
    hovermode="x unified",  # ✅ 一括マウスオーバー
    template="plotly_white",
    height=600,
    xaxis=dict(rangeslider=dict(visible=True))  # ✅ スクロール可能
)

fig.show()

これだと全て数値は出るけどグラフが読みにくい

すべて同じグラフに描いても、スケールが違っていて視認しづらい
金価格:2000〜3000(単位:ドル/トロイオンス)
CPI:100〜300
ドル円:100〜150
原油:30〜80

金価格の値が圧倒的に大きく、他の指標が 下に張り付いて見えにくい

解決策:二次Y軸(dual y-axis)または正規化

2軸グラフでスケールの異なる指標を分離表示

Plotlyで金価格とその他を別Y軸で描画する

import pandas as pd
import plotly.graph_objects as go

df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])
df.sort_values("Date", inplace=True)

fig = go.Figure()

# 金価格(左Y軸)
fig.add_trace(go.Scatter(
    x=df["Date"], y=df["gold_price"],
    name="金価格", line=dict(color='gold'),
    yaxis="y1"
))

# その他(右Y軸)
fig.add_trace(go.Scatter(
    x=df["Date"], y=df["cpi"],
    name="CPI", line=dict(color='blue'),
    yaxis="y2"
))

fig.add_trace(go.Scatter(
    x=df["Date"], y=df["usd_jpy"],
    name="ドル円", line=dict(color='red'),
    yaxis="y2"
))

fig.add_trace(go.Scatter(
    x=df["Date"], y=df["oil"],
    name="WTI原油", line=dict(color='green'),
    yaxis="y2"
))

# レイアウト設定
fig.update_layout(
    title="金価格(左軸) vs CPI・WTI・ドル円(右軸)",
    xaxis=dict(title="日付", rangeslider=dict(visible=True)),
    yaxis=dict(title="金価格", side="left"),
    yaxis2=dict(title="他指標", overlaying="y", side="right"),
    hovermode="x unified",
    height=600,
    template="plotly_white"
)

fig.show()

これで
📈 金価格は左Y軸
📉 CPI・ドル円・WTIは右Y軸
🖱 マウスオーバーで全ての値を同時に表示

ただしこれだとCPIが飛び出ているのでわかりにくい

CPIはグラフに線としては描かず、マウスオーバー時の数値表示だけにしたい

指標 グラフ表示 マウスオーバー表示
金価格 ✅ 線あり ✅ 値を表示
WTI原油 ✅ 線あり ✅ 値を表示
ドル円 ✅ 線あり ✅ 値を表示
CPI ❌ 線なし ✅ 値のみ表示

CPIは透明な線として追加(表示されないがホバー時は値が出る)
Plotlyでは line=dict(width=0) や opacity=0 を使うことで実現

コードを

import pandas as pd
import plotly.graph_objects as go

# データ読み込み
df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])
df.sort_values("Date", inplace=True)

fig = go.Figure()

# 金価格(左軸)
fig.add_trace(go.Scatter(
    x=df["Date"], y=df["gold_price"],
    name="金価格", line=dict(color='gold'),
    yaxis="y1"
))

# WTI原油(右軸)
fig.add_trace(go.Scatter(
    x=df["Date"], y=df["oil"],
    name="WTI原油", line=dict(color='green'),
    yaxis="y2"
))

# ドル円(右軸)
fig.add_trace(go.Scatter(
    x=df["Date"], y=df["usd_jpy"],
    name="ドル円", line=dict(color='red'),
    yaxis="y2"
))

# ✅ CPIを透明線で追加(線は非表示、値だけ表示)
fig.add_trace(go.Scatter(
    x=df["Date"], y=df["cpi"],
    name="CPI(表示なし)",
    line=dict(color='rgba(0,0,0,0)'),  # 完全に透明
    yaxis="y2",
    hoverinfo="x+y+name",  # ホバーは有効
    showlegend=False       # 凡例も非表示
))

# レイアウト設定
fig.update_layout(
    title="金価格・WTI・ドル円(CPIは非表示・値のみ)",
    xaxis=dict(title="日付", rangeslider=dict(visible=True)),
    yaxis=dict(title="金価格", side="left"),
    yaxis2=dict(title="WTI・ドル円", overlaying="y", side="right"),
    hovermode="x unified",
    height=600,
    template="plotly_white"
)

fig.show()

として保存

📈 金・WTI・ドル円は見やすく線で表示
🖱 CPIは線は出ないが、マウスオーバーで数値が見える

だいぶわかりやすくなった

次は
正規化して同軸で比較(相対変化に注目)を試す

pip install plotly scikit-learn

でインストール

normalized_economic_indicators_comparison.py

がファイル名

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
import plotly.graph_objects as go

# データ読み込み
df = pd.read_csv("merged_commodity_data.csv", parse_dates=["Date"])
df.sort_values("Date", inplace=True)

# 正規化する対象列
columns_to_normalize = ["gold_price", "oil", "usd_jpy", "cpi"]

# 正規化処理
scaler = MinMaxScaler()
df_normalized = df.copy()
df_normalized[columns_to_normalize] = scaler.fit_transform(df[columns_to_normalize])

# グラフ作成(正規化された値で重ね描き)
fig = go.Figure()

fig.add_trace(go.Scatter(x=df["Date"], y=df_normalized["gold_price"], name="金価格", line=dict(color='gold')))
fig.add_trace(go.Scatter(x=df["Date"], y=df_normalized["oil"], name="WTI原油", line=dict(color='green')))
fig.add_trace(go.Scatter(x=df["Date"], y=df_normalized["usd_jpy"], name="ドル円", line=dict(color='red')))
fig.add_trace(go.Scatter(x=df["Date"], y=df_normalized["cpi"], name="CPI", line=dict(color='blue')))

fig.update_layout(
    title="正規化された金価格・WTI・ドル円・CPIの相対変動比較",
    xaxis_title="日付",
    yaxis_title="正規化値(0〜1)",
    hovermode="x unified",
    xaxis=dict(rangeslider=dict(visible=True)),
    template="plotly_white",
    height=600
)

fig.show()

として実行

これでだいぶ見やすくなった

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です