import yfinance as yf import numpy as np import torch import timesfm import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from datetime import datetime, timedelta # 1. 获取 AAPL 近 1 年收盘价 print("下载 AAPL 股票数据...", flush=True) end = datetime.now() start = end - timedelta(days=365) df = yf.download("AAPL", start=start.strftime("%Y-%m-%d"), end=end.strftime("%Y-%m-%d"), progress=False) close = df["Close"].values.flatten().astype(np.float32) dates = df.index print(f"获取到 {len(close)} 个交易日", flush=True) print(f"价格范围: {close.min():.2f} ~ {close.max():.2f}", flush=True) print(f"最近 5 日收盘价: {close[-5:]}", flush=True) # 2. 加载 TimesFM 模型 print() print("加载 TimesFM 模型...", flush=True) torch.set_float32_matmul_precision("high") model = timesfm.TimesFM_2p5_200M_torch.from_pretrained( "google/timesfm-2.5-200m-pytorch", torch_compile=False ) print("模型加载完成", flush=True) # 3. 编译并预测未来 20 个交易日 HORIZON = 20 model.compile( timesfm.ForecastConfig( max_context=512, max_horizon=128, normalize_inputs=True, use_continuous_quantile_head=True, force_flip_invariance=False, infer_is_positive=True, fix_quantile_crossing=True, ) ) print("编译完成,开始预测...", flush=True) pf, qf = model.forecast(horizon=HORIZON, inputs=[close]) print("预测完成!", flush=True) # 4. 输出结果 print() print("=== AAPL 未来 20 个交易日预测 ===", flush=True) print(f"当前价格: {close[-1]:.2f}", flush=True) print() print(" 日期(估计) 点预测 q10(低) q90(高)", flush=True) last_date = dates[-1] for i in range(HORIZON): est_date = last_date + timedelta(days=i + 1) print( f" {est_date.strftime('%Y-%m-%d')} {pf[0][i]:7.2f} {qf[0][i,1]:7.2f} {qf[0][i,9]:7.2f}", flush=True, ) print() print(f"预测均价: {pf[0].mean():.2f}", flush=True) print(f"预测涨跌: {(pf[0][-1] - close[-1]) / close[-1] * 100:+.2f}%", flush=True) print(f"80%置信区间: {qf[0,-1,1]:.2f} ~ {qf[0,-1,9]:.2f}", flush=True) # 5. 画图 fig, ax = plt.subplots(figsize=(14, 6)) show_n = min(60, len(close)) ax.plot(range(show_n), close[-show_n:], label="历史收盘价", color="steelblue", linewidth=1.5) x_fc = range(show_n, show_n + HORIZON) ax.plot(x_fc, pf[0], label="点预测(中位数)", color="tomato", linewidth=2) ax.fill_between(x_fc, qf[0, :, 1], qf[0, :, 9], alpha=0.2, color="tomato", label="80% 置信区间") ax.fill_between(x_fc, qf[0, :, 3], qf[0, :, 7], alpha=0.35, color="tomato", label="40% 置信区间") ax.axvline(x=show_n - 1, color="gray", linestyle="--", alpha=0.5, label="预测起点") ax.set_title("AAPL 收盘价预测 (TimesFM 2.5)", fontsize=14) ax.set_xlabel("交易日") ax.set_ylabel("价格 (USD)") ax.legend(loc="upper left") plt.tight_layout() plt.savefig("aapl_forecast.png", dpi=150) print() print("图表已保存: aapl_forecast.png", flush=True) print("✅ 完成!", flush=True)