#!/usr/bin/env python3 # -*- coding: utf-8 -*- from __future__ import annotations import json import sys import urllib.parse import urllib.request def fetch_closes(symbol: str, range_: str = "6mo", interval: str = "1d") -> list[float]: base = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}" params = {"range": range_, "interval": interval} url = f"{base}?{urllib.parse.urlencode(params)}" req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) with urllib.request.urlopen(req, timeout=30) as resp: data = json.loads(resp.read().decode("utf-8", errors="replace")) result = data.get("chart", {}).get("result", []) if not result: return [] quote = result[0].get("indicators", {}).get("quote", []) if not quote: return [] closes = quote[0].get("close", []) return [float(x) for x in closes if x is not None] def ema(values: list[float], period: int) -> list[float]: if not values: return [] k = 2 / (period + 1) out = [values[0]] for v in values[1:]: out.append(v * k + out[-1] * (1 - k)) return out def macd(closes: list[float]) -> tuple[list[float], list[float], list[float]]: ema12 = ema(closes, 12) ema26 = ema(closes, 26) dif = [a - b for a, b in zip(ema12, ema26)] dea = ema(dif, 9) hist = [d - s for d, s in zip(dif, dea)] return dif, dea, hist def main() -> None: symbol = sys.argv[1] if len(sys.argv) > 1 else "00922.TW" closes = fetch_closes(symbol) if len(closes) < 35: print(f"{symbol} 資料不足,無法判斷 MACD(至少 35 筆,當前 {len(closes)})") return dif, dea, hist = macd(closes) d0, d1 = dif[-1], dif[-2] s0, s1 = dea[-1], dea[-2] h0, h1 = hist[-1], hist[-2] golden_cross = d1 <= s1 and d0 > s0 death_cross = d1 >= s1 and d0 < s0 low_zone = d0 < 0 and s0 < 0 if golden_cross and low_zone: signal = "✅ 低位金叉:偏多訊號" elif golden_cross: signal = "✅ 金叉:短線轉強" elif death_cross: signal = "⚠️ 死叉:短線轉弱" elif h0 > h1 and h0 > 0: signal = "📈 多頭延續(柱體擴大)" elif h0 < h1 and h0 < 0: signal = "📉 空頭延續(柱體擴大)" else: signal = "👀 MACD 震盪中,先觀察" print(f"{symbol} MACD 摘要") print(f"- DIF:{d0:.4f}") print(f"- DEA:{s0:.4f}") print(f"- HIST:{h0:.4f}") print(f"- 訊號:{signal}") if __name__ == "__main__": main()