ドル円レートの取得

ドル円レートの取得

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()

として実行

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

yfinanceで金価格の取得

yfinanceで金価格の取得

mkdir yfianace 
vim gold.py

内容を

import yfinance as yf
import datetime

# 金先物のティッカー
ticker = "GC=F"

# 非常に古い日付から現在まで取得
start_date = "1900-01-01"  # yfinanceが対応している限界に挑戦
end_date = datetime.datetime.today().strftime('%Y-%m-%d')

# データの取得(日足)
gold_data = yf.download(ticker, start=start_date, end=end_date, interval="1d")

# 結果の表示
print(gold_data.head())  # 最初の5件
print(gold_data.tail())  # 最新の5件
print(f"\n最古のデータ: {gold_data.index[0]}")
print(f"最新のデータ: {gold_data.index[-1]}")

として保存

これを実行

/Users/snowpool/aw10s/yfinance/gold.py:12: FutureWarning: YF.download() has changed argument auto_adjust default to True
  gold_data = yf.download(ticker, start=start_date, end=end_date, interval="1d")
[*********************100%***********************]  1 of 1 completed
Price            Close        High         Low        Open Volume
Ticker            GC=F        GC=F        GC=F        GC=F   GC=F
Date                                                             
2000-08-30  273.899994  273.899994  273.899994  273.899994      0
2000-08-31  278.299988  278.299988  274.799988  274.799988      0
2000-09-01  277.000000  277.000000  277.000000  277.000000      0
2000-09-05  275.799988  275.799988  275.799988  275.799988      2
2000-09-06  274.200012  274.200012  274.200012  274.200012      0
Price             Close         High          Low         Open  Volume
Ticker             GC=F         GC=F         GC=F         GC=F    GC=F
Date                                                                  
2025-07-21  3401.899902  3411.699951  3350.300049  3350.300049      53
2025-07-22  3439.199951  3441.000000  3395.600098  3411.000000      39
2025-07-23  3394.100098  3433.899902  3388.100098  3430.300049      63
2025-07-24  3371.000000  3371.000000  3367.000000  3367.000000      63
2025-07-25  3332.300049  3376.600098  3328.899902  3372.100098  156194

最古のデータ: 2000-08-30 00:00:00
最新のデータ: 2025-07-25 00:00:00

これを他で使えるようにcsvに保存する

import yfinance as yf
import datetime

# 金先物のティッカー
ticker = "GC=F"

# 非常に古い日付から現在まで取得
start_date = "1900-01-01"
end_date = datetime.datetime.today().strftime('%Y-%m-%d')

# データの取得(日足)
gold_data = yf.download(ticker, start=start_date, end=end_date, interval="1d")

# 結果の表示(最初と最後の数件)
print("=== 最初の5行 ===")
print(gold_data.head())
print("\n=== 最後の5行 ===")
print(gold_data.tail())

# 最古と最新のデータ日付
print(f"\n最古のデータ: {gold_data.index[0].date()}")
print(f"最新のデータ: {gold_data.index[-1].date()}")

# CSVに保存
csv_file = "gold_price_gc_f.csv"
gold_data.to_csv(csv_file)
print(f"\n✅ CSVファイルとして保存完了: {csv_file}")

実行すると

 python gold_csv.py 
/Users/snowpool/aw10s/yfinance/gold_csv.py:12: FutureWarning: YF.download() has changed argument auto_adjust default to True
  gold_data = yf.download(ticker, start=start_date, end=end_date, interval="1d")
[*********************100%***********************]  1 of 1 completed
=== 最初の5行 ===
Price            Close        High         Low        Open Volume
Ticker            GC=F        GC=F        GC=F        GC=F   GC=F
Date                                                             
2000-08-30  273.899994  273.899994  273.899994  273.899994      0
2000-08-31  278.299988  278.299988  274.799988  274.799988      0
2000-09-01  277.000000  277.000000  277.000000  277.000000      0
2000-09-05  275.799988  275.799988  275.799988  275.799988      2
2000-09-06  274.200012  274.200012  274.200012  274.200012      0

=== 最後の5行 ===
Price             Close         High          Low         Open  Volume
Ticker             GC=F         GC=F         GC=F         GC=F    GC=F
Date                                                                  
2025-07-21  3401.899902  3411.699951  3350.300049  3350.300049      53
2025-07-22  3439.199951  3441.000000  3395.600098  3411.000000      39
2025-07-23  3394.100098  3433.899902  3388.100098  3430.300049      63
2025-07-24  3371.000000  3371.000000  3367.000000  3367.000000      63
2025-07-25  3328.899902  3376.600098  3328.100098  3372.100098  157705

最古のデータ: 2000-08-30
最新のデータ: 2025-07-25

✅ CSVファイルとして保存完了: gold_price_gc_f.csv

となってcsvが保存される

次にSqlite へ登録する

しかし

import sqlite3
import pandas as pd

# CSV読み込み
df = pd.read_csv("gold_price_gc_f.csv", parse_dates=["Date"])

# SQLiteに保存
conn = sqlite3.connect("commodity_data.db")
df.to_sql("gold_price_daily", conn, if_exists="replace", index=False)
conn.close()
print("✅ SQLiteに保存完了: gold_price_daily テーブル")

だとエラーになる


Traceback (most recent call last):
  File "/Users/snowpool/aw10s/yfinance/add_sqldb.py", line 5, in <module>
    df = pd.read_csv("gold_price_gc_f.csv", parse_dates=["Date"])
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  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 1898, in _make_engine
    return mapping[engine](f, **self.options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/parsers/c_parser_wrapper.py", line 161, in __init__
    self._validate_parse_dates_presence(self.names)  # type: ignore[has-type]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/io/parsers/base_parser.py", line 243, in _validate_parse_dates_presence
    raise ValueError(
ValueError: Missing column provided to 'parse_dates': 'Date'

これは
行目にティッカー情報の行が含まれており、本来のヘッダーが1行目 になっていないため、pandas.read_csv()がうまく処理できていないのが原因

このため
2行目スキップして1行目をヘッダーとして読み込むように変更

import sqlite3
import pandas as pd

# 2行目(ティッカー行)をスキップし、1行目をヘッダーとして使用
df = pd.read_csv("gold_price_gc_f.csv", skiprows=[1], parse_dates=["Price"])
df.rename(columns={"Price": "Date"}, inplace=True)  # Date列として扱う

# SQLiteに保存
conn = sqlite3.connect("commodity_data.db")
df.to_sql("gold_price_daily", conn, if_exists="replace", index=False)
conn.close()

print("✅ SQLiteに保存完了: gold_price_daily テーブル")

これを実行すると

 python add_sqldb.py
/Users/snowpool/aw10s/yfinance/add_sqldb.py:5: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.
  df = pd.read_csv("gold_price_gc_f.csv", skiprows=[1], parse_dates=["Price"])
✅ SQLiteに保存完了: gold_price_daily テーブル

となる

これにより

* Price 列 → Date に名前変更(DateTime型として扱える)
* SQLite テーブル名:gold_price_daily
* 後続のクエリや可視化処理が簡単になります
となる

保存後に確認したいのなら

# 保存したDBの中身を確認(任意)
conn = sqlite3.connect("commodity_data.db")
df_check = pd.read_sql("SELECT * FROM gold_price_daily LIMIT 5", conn)
print(df_check)
conn.close()

を追加すると良い

WTI原油、ドル円の過去レートの取得

WTI原油、ドル円の過去レートの取得

yfinance 経由で取得できる WTI原油(CL=F)やドル円(JPY=X) のデータは、Yahoo Finance に基づき、以下のようにかなり長期間に渡って利用可能

✅ 取得可能な過去データの期間(概算)
資産 シンボル 開始可能な年 備考
WTI原油先物 CL=F 1983年頃〜現在 日足・週足・月足データあり
ドル円(USD/JPY) JPY=X 1971年頃〜現在 固定相場制移行後のデータあり

GPTで

 pip install yfinance pandas matplotlib sqlite3

で必要ならライブラリインストール
とあったが

ERROR: Could not find a version that satisfies the requirement sqlite3 (from versions: none)
ERROR: No matching distribution found for sqlite3

となる

sqlite3 は Pythonに標準で内蔵されているライブラリ なので、pip install sqlite3 は不要

Python で最古の日付を確認する

 vim earliest_rate.py

内容を

import yfinance as yf

# 1銘柄ずつ最大データ期間を確認
wti = yf.download("CL=F", period="max")
usdjpy = yf.download("JPY=X", period="max")

print("WTI最古の日付:", wti.index.min())
print("ドル円最古の日付:", usdjpy.index.min())

しかし
これだと

[*********************100%***********************]  1 of 1 completed

1 Failed download:
['CL=F']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')
[*********************100%***********************]  1 of 1 completed

1 Failed download:
['JPY=X']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')
WTI最古の日付: NaT
ドル円最古の日付: NaT

となって
ahoo Finance の yfinance ライブラリが アクセス制限(レートリミット) に引っかかる

なので期間を限定する

import yfinance as yf

def get_earliest_date(symbol):
    try:
        df = yf.download(symbol, start="1900-01-01", end="1975-01-01", interval="1mo", progress=False)
        if df.empty:
            df = yf.download(symbol, start="1970-01-01", end="1990-01-01", interval="1mo", progress=False)
        return df.index.min()
    except Exception as e:
        print(f"{symbol} の取得でエラー: {e}")
        return None

# 実行
wti_start = get_earliest_date("CL=F")
jpy_start = get_earliest_date("JPY=X")

print("WTI原油の最古日:", wti_start)
print("ドル円の最古日:", jpy_start)

としたが

1 Failed download:
['CL=F']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')

1 Failed download:
['CL=F']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')

1 Failed download:
['JPY=X']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')

1 Failed download:
['JPY=X']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')
WTI原油の最古日: NaT
ドル円の最古日: NaT

となる

これだと変わらないので
Csvをダウンロードしようとしたが
現在CSVダウンロードはできない

WTI原油先物(CL=F)」ではなく、W&T Offshore, Inc.(ティッカー: WTI) という個別株の履歴ページがるので注意

項目 正しいWTI原油先物 間違いやすいW&T Offshore株
正式名称 WTI Crude Oil Futures W&T Offshore, Inc.
シンボル CL=F WTI
内容 原油先物価格(NYMEX) エネルギー会社の株価
利用目的 原油価格の分析 企業株の投資分析

Yahoo Finance の WTI原油先物(CL=F) に関する正しいデータであり、取得可能な最古の日付は 2000年8月23日

試しに
yfinance api で一番古いデータから3カ月分だけ取得する

import yfinance as yf
import pandas as pd
import sqlite3

# === データ取得範囲 ===
start_date = pd.Timestamp("2000-08-23")
end_date = start_date + pd.Timedelta(days=90)

# === データ取得 ===
df = yf.download("CL=F", start=start_date, end=end_date, progress=False)

# 日付インデックスをリセットして通常の列に
df.reset_index(inplace=True)

# === SQLiteに保存 ===
db_path = "commodities.db"
table_name = "wti_first_3months"

# 不要なNaN行削除
df = df.dropna(subset=["Date"])

with sqlite3.connect(db_path) as conn:
    df.to_sql(table_name, conn, if_exists="replace", index=False)

print(f"{len(df)} 件のWTI原油データを {db_path} の {table_name} に保存しました。")

を実行すると

1 Failed download:
['CL=F']: YFRateLimitError('Too Many Requests. Rate limited. Try after a while.')
Traceback (most recent call last):
  File "/Users/snowpool/aw10s/wti/earliest_rate.py", line 20, in <module>
    df = df.dropna(subset=["Date"])
         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages/pandas/core/frame.py", line 6670, in dropna
    raise KeyError(np.array(subset)[check].tolist())
KeyError: ['Date']

これを元に修正する

import yfinance as yf
import pandas as pd
import sqlite3

# === データ取得範囲 ===
start_date = pd.Timestamp("2000-08-23")
end_date = start_date + pd.Timedelta(days=90)

# === データ取得 ===
try:
    df = yf.download("CL=F", start=start_date, end=end_date, progress=False)

    if df.empty:
        print("⚠ データ取得に失敗しました(アクセス制限などの可能性あり)")
    else:
        df.reset_index(inplace=True)

        # 安全に 'Date' カラムの存在確認
        if "Date" in df.columns:
            df = df.dropna(subset=["Date"])
        else:
            print("⚠ 'Date' カラムが見つかりません。保存せず終了します。")
            exit()

        # === SQLiteに保存 ===
        db_path = "commodities.db"
        table_name = "wti_first_3months"

        with sqlite3.connect(db_path) as conn:
            df.to_sql(table_name, conn, if_exists="replace", index=False)

        print(f"✅ {len(df)} 件のWTI原油データを {db_path} の {table_name} に保存しました。")

except Exception as e:
    print(f"❌ 予期せぬエラー: {e}")

データが古すぎて取れない可能性がある

調べた結果、

https://web-dev.hatenablog.com/entry/python/yfinance/error/rate-limit
yfinance エラー対応方法「Too Many Requests. Rate limited.」
にあるように

pip install --upgrade yfinance

を実行しバージョンをアップすると解決した

実行時のログは

Installing collected packages: curl_cffi, yfinance
  Attempting uninstall: yfinance
    Found existing installation: yfinance 0.2.52
    Uninstalling yfinance-0.2.52:
      Successfully uninstalled yfinance-0.2.52
Successfully installed curl_cffi-0.12.0 yfinance-0.2.65

どうやら 0.2.52だとエラーになるが
0.2.65だと解決しているらしい

試しに

import yfinance as yf

# リアルタイムのWTI価格を取得(1分間隔の最新データ)
wti = yf.Ticker("CL=F")
data = wti.history(period="1d", interval="1m").tail(1)  # 最新の1分データ
price = data['Close'].iloc[-1]  # 最新の終値
print(f"Current WTI Price: ${price}")

を実行

python wti.py  
Current WTI Price: $65.51000213623047

となって最新のWTI価格を取得できる

原油と金価格の取得

自国と各国の経済指標とかをまとめて可視化
為替れーと、原油とか金、ビットコインの推移を見れることが
できるものを作成する

GPTで調べると

以下の要件に基づいて、経済指標や各種市場データをまとめて可視化するツールを作成する方法を提案します。

### **プロジェクト概要**
#### **目的**
– 各国の経済指標や市場データをまとめて可視化。
– 為替レート、原油価格、金価格、ビットコイン価格の推移をリアルタイムで確認可能。

#### **必要な機能**
1. **データ取得**
– 経済指標(GDP、失業率、インフレ率など)
– 為替レート(主要通貨ペア: USD/JPY、EUR/USDなど)
– 原油価格(WTI、ブレント)
– 金価格(トロイオンス単位)
– 仮想通貨(ビットコイン、イーサリアムなど)

2. **データの可視化**
– 時系列グラフ(過去の推移)
– ダッシュボード形式でのリアルタイム表示

3. **通知機能(任意)**
– 為替レートや価格の変動が大きい場合にアラートを送信。

4. **多言語対応(日本語/英語)**

### **開発環境**
#### **プログラミング言語**
– Python(データ取得、可視化に適切)

#### **使用ライブラリ・API**
– **データ取得**
– 為替レート: [ExchangeRate-API](https://www.exchangerate-api.com/) or [Alpha Vantage](https://www.alphavantage.co/)
– 原油・金価格: [Yahoo Finance API](https://rapidapi.com/apidojo/api/yahoo-finance1/)
– 仮想通貨: [CoinGecko API](https://www.coingecko.com/) or [CoinMarketCap API](https://coinmarketcap.com/api/)
– 経済指標: [OECD API](https://data.oecd.org/) or [World Bank API](https://data.worldbank.org/)

– **データ可視化**
– `Plotly`(インタラクティブなグラフ)
– `Dash`(ダッシュボード作成)
– `matplotlib`(簡易な静的グラフ)

– **バックエンド**
– Flask または FastAPI(Webアプリケーションのベース)

– **フロントエンド**
– Dash(Pythonのみで作成可能)

#### **サーバー**
– ローカル開発: PCまたはRaspberry Pi(Pi 5が最適)
– デプロイ: AWS、GCP、Heroku、またはVPS

### **基本的な実装手順**

1. **データ取得モジュールの作成**
– 各APIからデータを取得するPythonモジュールを作成。
– 必要に応じて取得データをCSVまたはデータベース(SQLiteなど)に保存。

2. **データ処理**
– Pandasを使用してデータを加工(例: 日付フォーマットの統一、不要な列の削除)。
– 過去1年分などの期間を指定してデータをフィルタリング。

3. **可視化**
– Plotlyでインタラクティブなグラフを作成。
– 例: 為替レートの時系列推移を折れ線グラフで表示。

4. **ダッシュボードの作成**
– Dashを使い、リアルタイムにデータが更新されるダッシュボードを構築。
– 各市場データをカード形式やグラフで整理。

5. **通知機能(オプション)**
– 適当な閾値を設定し、変動が大きい場合にLINE Notifyやメールでアラート送信。

### **プロジェクトの初期設計例**

#### **ディレクトリ構造**
“`
economy_dashboard/
├── app.py # メインスクリプト
├── data_fetcher/
│ ├── forex.py # 為替データ取得
│ ├── commodities.py # 原油/金価格取得
│ ├── crypto.py # 仮想通貨データ取得
│ └── indicators.py # 経済指標取得
├── templates/ # DashやFlaskのHTMLテンプレート
├── static/ # CSS/JSファイル
└── requirements.txt # 必要ライブラリ
“`

#### **ダッシュボードイメージ**
– **ヘッダー**
– 今日の日付と最新の市場状況(例: USD/JPY、ビットコイン価格など)。
– **メインセクション**
– 為替レート推移グラフ
– 原油価格と金価格の時系列データ
– 仮想通貨の市場状況
– **サイドバー**
– 通知の設定や期間選択。

### **サンプルコード(Dashを使った可視化)**

```python
import dash
from dash import dcc, html
import pandas as pd
import plotly.graph_objects as go

# サンプルデータ
data = {
    "Date": pd.date_range(start="2024-01-01", periods=10, freq="D"),
    "USD_JPY": [130 + i for i in range(10)],
    "Bitcoin": [30000 + i * 500 for i in range(10)],
}
df = pd.DataFrame(data)

# Dashアプリ
app = dash.Dash(__name__)

app.layout = html.Div([
    html.H1("経済指標ダッシュボード"),
    dcc.Graph(
        id="forex_chart",
        figure={
            "data": [
                go.Scatter(x=df["Date"], y=df["USD_JPY"], mode="lines", name="USD/JPY"),
                go.Scatter(x=df["Date"], y=df["Bitcoin"], mode="lines", name="Bitcoin"),
            ],
            "layout": go.Layout(title="為替とビットコインの推移", xaxis_title="日付", yaxis_title="価格"),
        },
    ),
])

if __name__ == "__main__":
    app.run_server(debug=True)
```

### **今後の拡張案**
1. **AI活用**
– 市場予測モデルを構築し、将来のトレンドを予測。
2. **モバイル対応**
– スマホで見やすいUIを設計。
3. **ユーザー設定**
– 関心のある国や通貨ペアを選択可能に。

作成を進める中で質問や具体的な実装サポートが必要であれば、ぜひお知らせください!

となった

まずはWTIからやるので

commodities.py

を作成する

import requests
import datetime

def fetch_commodities_data(api_key, symbol, interval="1d", range="1mo"):
    """
    Fetch commodity prices such as crude oil (WTI/Brent) or gold.

    Parameters:
        api_key (str): API key for the Yahoo Finance or similar API.
        symbol (str): Symbol of the commodity (e.g., CL=F for WTI Crude Oil, GC=F for Gold).
        interval (str): Data interval (e.g., '1d', '1wk').
        range (str): Data range (e.g., '1mo', '3mo', '1y').

    Returns:
        dict: Parsed JSON response containing commodity price data.
    """
    base_url = "https://query1.finance.yahoo.com/v8/finance/chart/"
    url = f"{base_url}{symbol}"

    params = {
        "region": "US",
        "lang": "en",
        "interval": interval,
        "range": range,
    }

    headers = {
        "x-api-key": api_key
    }

    try:
        response = requests.get(url, headers=headers, params=params)
        response.raise_for_status()
        data = response.json()
        return data

    except requests.exceptions.RequestException as e:
        print(f"Error fetching commodity data: {e}")
        return None

# Example usage
if __name__ == "__main__":
    API_KEY = "your_api_key_here"  # Replace with your actual API key
    symbol_wti = "CL=F"  # WTI Crude Oil
    symbol_gold = "GC=F"  # Gold

    # Fetch WTI data
    wti_data = fetch_commodities_data(API_KEY, symbol_wti)
    if wti_data:
        print("WTI Data:", wti_data)

    # Fetch Gold data
    gold_data = fetch_commodities_data(API_KEY, symbol_gold)
    if gold_data:
        print("Gold Data:", gold_data)

というコードが提示された

しかし確かAPIキーなしでも動作する

yfinance API を使って株のデータを取得する

も参考にする

Python で過去の株価データを CSVデータで取得する
でもキーは不要で動く

Pythonでリアルタイムな株価を取得する方法
でも同じ

[解説]Pythonを用いた株価・経済データの取得方法をまとめてみた

でもキーは不要

ということで
原油/金価格取得のため yfinance を使い python で取得したい
というように変更

import yfinance as yf

def fetch_commodities_data(symbol, start_date, end_date):
    """
    Fetch commodity prices such as crude oil (WTI/Brent) or gold using yfinance.

    Parameters:
        symbol (str): Symbol of the commodity (e.g., 'CL=F' for WTI Crude Oil, 'GC=F' for Gold).
        start_date (str): Start date for historical data in 'YYYY-MM-DD' format.
        end_date (str): End date for historical data in 'YYYY-MM-DD' format.

    Returns:
        DataFrame: Pandas DataFrame containing the historical price data.
    """
    try:
        data = yf.download(symbol, start=start_date, end=end_date)
        return data
    except Exception as e:
        print(f"Error fetching commodity data: {e}")
        return None

# Example usage
if __name__ == "__main__":
    symbol_wti = "CL=F"  # WTI Crude Oil
    symbol_gold = "GC=F"  # Gold

    # Define the date range
    start_date = "2023-01-01"
    end_date = "2023-12-31"

    # Fetch WTI data
    wti_data = fetch_commodities_data(symbol_wti, start_date, end_date)
    if wti_data is not None:
        print("WTI Data:")
        print(wti_data)

    # Fetch Gold data
    gold_data = fetch_commodities_data(symbol_gold, start_date, end_date)
    if gold_data is not None:
        print("Gold Data:")
        print(gold_data)

となって実行すると

[*********************100%***********************]  1 of 1 completed
WTI Data:
Price           Close       High        Low       Open  Volume
Ticker           CL=F       CL=F       CL=F       CL=F    CL=F
Date                                                          
2023-01-03  76.930000  81.500000  76.599998  80.570000  338520
2023-01-04  72.839996  77.419998  72.730003  77.250000  352434
2023-01-05  73.669998  74.919998  72.459999  73.250000  300731
2023-01-06  73.769997  75.470001  73.239998  73.970001  258128
2023-01-09  74.629997  76.739998  73.470001  73.470001  329290
...               ...        ...        ...        ...     ...
2023-12-22  73.559998  74.980003  73.389999  73.910004  222600
2023-12-26  75.570000  76.180000  73.129997  73.559998  208715
2023-12-27  74.110001  75.660004  73.769997  75.320000  253323
2023-12-28  71.769997  74.400002  71.720001  73.800003  262748
2023-12-29  71.650002  72.620003  71.250000  71.989998  214486

[250 rows x 5 columns]
[*********************100%***********************]  1 of 1 completed
Gold Data:
Price             Close         High          Low         Open Volume
Ticker             GC=F         GC=F         GC=F         GC=F   GC=F
Date                                                                 
2023-01-03  1839.699951  1839.699951  1836.199951  1836.199951     29
2023-01-04  1852.800049  1859.099976  1845.599976  1845.599976     25
2023-01-05  1834.800049  1855.199951  1834.800049  1855.199951     24
2023-01-06  1864.199951  1868.199951  1835.300049  1838.400024     26
2023-01-09  1872.699951  1880.000000  1867.000000  1867.000000     62
...                 ...          ...          ...          ...    ...
2023-12-22  2057.100098  2068.699951  2052.199951  2055.699951    202
2023-12-26  2058.199951  2060.800049  2054.199951  2060.000000     64
2023-12-27  2081.899902  2081.899902  2064.800049  2067.300049    586
2023-12-28  2073.899902  2087.300049  2066.500000  2081.600098    338
2023-12-29  2062.399902  2068.899902  2062.100098  2068.000000     47

[250 rows x 5 columns]

となる

さらにデータをCSVに保存するので

import yfinance as yf

def fetch_commodities_data(symbol, start_date, end_date):
    """
    Fetch commodity prices such as crude oil (WTI/Brent) or gold using yfinance.

    Parameters:
        symbol (str): Symbol of the commodity (e.g., 'CL=F' for WTI Crude Oil, 'GC=F' for Gold).
        start_date (str): Start date for historical data in 'YYYY-MM-DD' format.
        end_date (str): End date for historical data in 'YYYY-MM-DD' format.

    Returns:
        DataFrame: Pandas DataFrame containing the historical price data.
    """
    try:
        data = yf.download(symbol, start=start_date, end=end_date)
        return data
    except Exception as e:
        print(f"Error fetching commodity data: {e}")
        return None

# Example usage
if __name__ == "__main__":
    symbol_wti = "CL=F"  # WTI Crude Oil
    symbol_gold = "GC=F"  # Gold

    # Define the date range
    start_date = "2023-01-01"
    end_date = "2023-12-31"

    # Fetch WTI data
    wti_data = fetch_commodities_data(symbol_wti, start_date, end_date)
    if wti_data is not None:
        print("WTI Data:")
        print(wti_data)
        wti_data.to_csv("wti_data.csv")

    # Fetch Gold data
    gold_data = fetch_commodities_data(symbol_gold, start_date, end_date)
    if gold_data is not None:
        print("Gold Data:")
        print(gold_data)
        gold_data.to_csv("gold_data.csv")

として実行

とりあえず問題なし

次は経済指標だが
カレンダーは
メルマガから取得するより
Browser use で経済指標カレンダーを取得した方が早いかもしれない

https://fx.minkabu.jp/indicators
へアクセスし、今日の経済指標カレンダーの日程を取得

これで一応は取得できてるみたい

結果を保存したいので
https://fx.minkabu.jp/indicators
へアクセスし、今日の経済指標カレンダーの日程を取得。結果をcalendar.txt へ保存
としたけどできなかった