Created
December 31, 2025 00:32
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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