Skip to content

Instantly share code, notes, and snippets.

@tado
Created December 31, 2025 00:32
Show Gist options
  • Select an option

  • Save tado/6946235812e6202296000753254f4ec3 to your computer and use it in GitHub Desktop.

Select an option

Save tado/6946235812e6202296000753254f4ec3 to your computer and use it in GitHub Desktop.
Downloads 20 years of USDJPY data, fits LOWESS and polynomial/linear regressions, and plots historical prices with 10-year forecast and summary stats.
import yfinance as yf
import matplotlib.pyplot as plt
import matplotlib
from datetime import datetime, timedelta
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import r2_score, mean_squared_error
from scipy import stats
import pandas as pd
from statsmodels.nonparametric.smoothers_lowess import lowess
import warnings
warnings.filterwarnings('ignore')
# 日本語フォントの設定
matplotlib.rcParams['font.family'] = 'MS Gothic'
matplotlib.rcParams['axes.unicode_minus'] = False # マイナス記号の文字化け対策
def analyze_and_plot(symbol: str, pair_label: str):
# 過去20年間のデータを取得
end_date = datetime.now()
start_date = end_date - timedelta(days=365*20)
print(f"{pair_label}データをダウンロード中...")
df = yf.download(symbol, start=start_date, end=end_date)
y = df['Close'].values.flatten()
X = np.arange(len(y)).reshape(-1, 1)
n = len(y)
# 将来10年分の予測
future_days = 252 * 10
X_future = np.arange(len(y) + future_days).reshape(-1, 1)
future_dates = pd.date_range(start=df.index[-1], periods=future_days+1, freq='D')[1:]
all_dates = df.index.append(future_dates)
# LOWESS
lowess_result = lowess(y, X.flatten(), frac=0.1, return_sorted=False)
last_100_points = lowess_result[-100:]
lowess_slope = (last_100_points[-1] - last_100_points[0]) / 100
lowess_future = np.concatenate([
lowess_result,
[lowess_result[-1] + lowess_slope * i for i in range(1, future_days+1)]
])
rmse_lowess = np.sqrt(mean_squared_error(y, lowess_result))
r2_lowess = r2_score(y, lowess_result)
# 線形回帰
linear_model = LinearRegression()
linear_model.fit(X, y)
y_linear = linear_model.predict(X)
y_linear_future = linear_model.predict(X_future)
r2_linear = r2_score(y, y_linear)
rmse_linear = np.sqrt(mean_squared_error(y, y_linear))
df_res_linear = n - 2
f_stat_linear = (r2_linear / 1) / ((1 - r2_linear) / df_res_linear)
p_value_linear = 1 - stats.f.cdf(f_stat_linear, 1, df_res_linear)
# 2次多項式
poly2_features = PolynomialFeatures(degree=2)
X_poly2 = poly2_features.fit_transform(X)
X_poly2_future = poly2_features.fit_transform(X_future)
poly2_model = LinearRegression()
poly2_model.fit(X_poly2, y)
y_poly2 = poly2_model.predict(X_poly2)
y_poly2_future = poly2_model.predict(X_poly2_future)
r2_poly2 = r2_score(y, y_poly2)
rmse_poly2 = np.sqrt(mean_squared_error(y, y_poly2))
df_res_poly2 = n - 3
f_stat_poly2 = (r2_poly2 / 2) / ((1 - r2_poly2) / df_res_poly2)
p_value_poly2 = 1 - stats.f.cdf(f_stat_poly2, 2, df_res_poly2)
# 3次多項式
poly3_features = PolynomialFeatures(degree=3)
X_poly3 = poly3_features.fit_transform(X)
X_poly3_future = poly3_features.fit_transform(X_future)
poly3_model = LinearRegression()
poly3_model.fit(X_poly3, y)
y_poly3 = poly3_model.predict(X_poly3)
y_poly3_future = poly3_model.predict(X_poly3_future)
r2_poly3 = r2_score(y, y_poly3)
rmse_poly3 = np.sqrt(mean_squared_error(y, y_poly3))
df_res_poly3 = n - 4
f_stat_poly3 = (r2_poly3 / 3) / ((1 - r2_poly3) / df_res_poly3)
p_value_poly3 = 1 - stats.f.cdf(f_stat_poly3, 3, df_res_poly3)
# グラフ
plt.figure(figsize=(16, 9))
plt.scatter(df.index, y, s=1.0, label='実際の価格', alpha=0.4, color='gray', zorder=1)
plt.axvline(x=df.index[-1], color='black', linestyle=':', linewidth=1.2, alpha=0.4, label='予測開始点')
plt.plot(all_dates, lowess_future, linewidth=2,
label=f'★LOWESS (R²={r2_lowess:.4f}, RMSE={rmse_lowess:.2f})',
linestyle='-', color='C0', alpha=0.9, zorder=5)
plt.plot(all_dates, y_linear_future, linewidth=2,
label=f'線形回帰 (R²={r2_linear:.4f}, RMSE={rmse_linear:.2f})',
linestyle='--', color='C1', alpha=0.7, zorder=3)
plt.plot(all_dates, y_poly2_future, linewidth=2,
label=f'2次多項式回帰 (R²={r2_poly2:.4f}, RMSE={rmse_poly2:.2f})',
linestyle='--', color='C2', alpha=0.7, zorder=3)
plt.plot(all_dates, y_poly3_future, linewidth=2,
label=f'3次多項式回帰 (R²={r2_poly3:.4f}, RMSE={rmse_poly3:.2f})',
linestyle='--', color='C3', alpha=0.7, zorder=3)
plt.title(f'{pair_label} 為替レート - 回帰分析と10年予測', fontsize=14, fontweight='bold')
plt.xlabel('日付', fontsize=12)
plt.ylabel('価格 (円)', fontsize=12)
plt.legend(loc='best', fontsize=9)
plt.grid(True, alpha=0.3)
plt.tight_layout()
print("グラフを表示中...")
plt.show()
# 結果出力
print(f"\n=== {pair_label} 統計情報 ===")
print(f"期間: {df.index[0].date()} ~ {df.index[-1].date()}")
print(f"最高値: {df['Close'].max():.2f}円")
print(f"最安値: {df['Close'].min():.2f}円")
print(f"平均値: {df['Close'].mean():.2f}円")
print(f"最新値: {df['Close'][-1]:.2f}円")
print(f"\n=== {pair_label} より妥当性の高い分析結果 ===")
print(f"★LOWESS: R²={r2_lowess:.4f}, RMSE={rmse_lowess:.2f}")
print(f"\n=== {pair_label} 従来の回帰分析結果 ===")
print(f"線形: R²={r2_linear:.4f}, RMSE={rmse_linear:.2f}, F={f_stat_linear:.4f}, p={p_value_linear:.2e}")
print(f"2次: R²={r2_poly2:.4f}, RMSE={rmse_poly2:.2f}, F={f_stat_poly2:.4f}, p={p_value_poly2:.2e}")
print(f"3次: R²={r2_poly3:.4f}, RMSE={rmse_poly3:.2f}, F={f_stat_poly3:.4f}, p={p_value_poly3:.2e}")
print(f"\n=== {pair_label} 10年後の予測値 ===")
print(f"LOWESS: {lowess_future[-1]:.2f}円")
print(f"線形回帰: {y_linear_future[-1]:.2f}円")
print(f"2次多項式回帰: {y_poly2_future[-1]:.2f}円")
print(f"3次多項式回帰: {y_poly3_future[-1]:.2f}円")
def main():
analyze_and_plot('USDJPY=X', 'USDJPY (ドル円)')
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment