6041e3ff27
Python package build / build (push) Has been cancelled
- stock_forecast.py: Basic AAPL price forecast - stock_backtest.py: V1 original price prediction backtest - stock_backtest_optimized.py: V2 log-return + ensemble optimization - stock_backtest_xreg.py: V3 XReg covariates (volume/RSI/SPY) - stock_backtest_trick.py: V4 SPY trend guidance + volatility adjustment - Visualization charts for all versions
85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
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)
|