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>
83 lines
2.1 KiB
Python
83 lines
2.1 KiB
Python
#!/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 sma(values: list[float], window: int) -> float:
|
||
return sum(values[-window:]) / window
|
||
|
||
|
||
def main() -> None:
|
||
symbol = sys.argv[1] if len(sys.argv) > 1 else "00922.TW"
|
||
closes = fetch_closes(symbol)
|
||
|
||
if len(closes) < 60:
|
||
print(f"{symbol} 資料不足:至少需要 60 筆日收盤,當前 {len(closes)}")
|
||
return
|
||
|
||
price = closes[-1]
|
||
ma5 = sma(closes, 5)
|
||
ma10 = sma(closes, 10)
|
||
ma20 = sma(closes, 20)
|
||
ma60 = sma(closes, 60)
|
||
|
||
bias20 = ((price - ma20) / ma20) * 100
|
||
|
||
print(f"{symbol} 均線摘要")
|
||
print(f"- 收盤:{price:.2f}")
|
||
print(f"- MA5 :{ma5:.2f}")
|
||
print(f"- MA10:{ma10:.2f}")
|
||
print(f"- MA20:{ma20:.2f}")
|
||
print(f"- MA60:{ma60:.2f}")
|
||
print(f"- 20日乖離:{bias20:.2f}%")
|
||
|
||
# 簡單判讀
|
||
trend = []
|
||
if price > ma20:
|
||
trend.append("站上月線")
|
||
else:
|
||
trend.append("跌破月線")
|
||
|
||
if ma20 > ma60:
|
||
trend.append("中期偏多")
|
||
else:
|
||
trend.append("中期偏弱")
|
||
|
||
if ma5 > ma20:
|
||
trend.append("短線強於月線")
|
||
else:
|
||
trend.append("短線弱於月線")
|
||
|
||
print(f"- 判讀:{'/'.join(trend)}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|