Files
stocks-query/scripts/yahoo-macd-signal.py
Timmy 7d72aed984 restore and rebuild all stock query scripts
Recover 7 existing scripts from remote repo and rebuild 5 missing ones:
- twse-margin-trading.py (融資融券)
- twse-day-trading.py (當沖交易)
- twse-foreign-holdings.py (外資持股)
- yahoo-dividend-browserless.py (股利資訊)
- yahoo-broker-trading-browserless.py (主力券商進出)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:07:31 +08:00

92 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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()