xiaowei-system/scripts/stock_news.py

143 lines
4.3 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
"""
小唯每日新闻监控 — 宏观+行业+事件(精简版)
==========================================
只使用可靠的快速数据源
用法:
python3 stock_news.py # 获取今日摘要
python3 stock_news.py --push # 获取+推送飞书
"""
import json, sys, urllib.request
from datetime import datetime
from pathlib import Path
OUTPUT = Path.home() / ".hermes" / "stock_backtest"
OUTPUT.mkdir(exist_ok=True)
FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/446db983-e392-4d2c-bfb8-f9060e5df3ad"
def send_feishu(msg):
payload = json.dumps({"msg_type": "text", "content": {"text": msg}}).encode()
req = urllib.request.Request(FEISHU_WEBHOOK, data=payload,
headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req, timeout=8):
pass
except Exception:
pass
def get_url(url, timeout=4, enc="gbk"):
"""快速HTTP GET统一用curl避免urllib在hermes/scripts目录异常"""
import subprocess, shlex, os
env = dict(os.environ)
for k in ["http_proxy", "https_proxy", "HTTP_PROXY", "HTTPS_PROXY"]:
env.pop(k, None)
cmd = ["curl", "-s", "--max-time", str(timeout), url]
try:
r = subprocess.run(cmd, capture_output=True, timeout=timeout + 2, env=env)
return r.stdout.decode(enc, errors="ignore")
except Exception:
return ""
def get_market():
"""大盘上证+沪深300 + 五粮液价格"""
result = {}
for code, name in [("sh000001","上证"), ("sh510300","沪深300"), ("sz000858","五粮液")]:
text = get_url(f"https://qt.gtimg.cn/q={code}")
parts = text.split("~")
if len(parts) > 10:
try:
price = float(parts[3])
yclose = float(parts[4])
chg = (price - yclose) / yclose * 100
result[name] = {"price": price, "change": chg}
except (ValueError, IndexError):
pass
return result
def get_oil():
"""布伦特原油 — 腾讯行情 hf_OIL ✅ 已验证可用"""
try:
url = "https://qt.gtimg.cn/q=hf_OIL"
text = get_url(url)
# hf_OIL 格式: v_hf_OIL="75.23,-1.40,75.22,75.27,77.52,75.22,05:59:59,76.30,76.15,0,77,2,2026-07-11,文字"
# parts[0]="v_hf_OIL=", parts[1]="75.23,-1.40,..."
if "=" in text:
val_part = text.split("=", 1)[1].strip('"; \n')
vals = val_part.split(",")
if len(vals) >= 8:
price = float(vals[0])
yclose = float(vals[7])
return {"value": price, "change": price - yclose}
except Exception:
pass
return None
def build_report(push=False):
today = datetime.now().strftime("%Y-%m-%d %H:%M")
# 1. 大盘+持仓
market = get_market()
# 2. 原油
oil = get_oil()
# 五粮液信号(读取信号文件)
signal = "空仓"
try:
sig_file = OUTPUT / "四维_000858.json"
if sig_file.exists():
with open(sig_file) as f:
d = json.load(f)
signal = d.get("verdict", "空仓").split("")[0].strip()
except Exception:
pass
msg = f"""📰 每日宏观+持仓摘要
【大盘】{today}
"""
for name, data in market.items():
e = "📈" if data["change"] > 0 else "📉"
msg += f"{e} {name}: {data['price']:.2f} ({data['change']:+.2f}%)\n"
msg += f"\n【五粮液持仓信号】{signal}\n"
if oil:
e = "📈" if oil["change"] > 0 else "📉"
msg += f"\n{e} 布伦特原油: {oil['value']} ({oil['change']:+.2f})"
else:
msg += f"\n• 原油: (获取失败)"
msg += f"""
【宏观风险提示】
• 大盘若跌破关键均线 → 空仓信号加强
• 白酒消费数据持续低迷 → 基本面承压
• 人民币贬值预期 → 外资流出白酒板块压力
【五粮液状态】
价格: {market.get('五粮液',{}).get('price','--')} ({market.get('五粮液',{}).get('change',0):+.2f}%)
MA20下方 → 空仓信号,等待金叉
小唯股票投研 · 每日新闻"""
if push:
send_feishu(msg)
# 存档
report_file = OUTPUT / f"news_{datetime.now().strftime('%Y%m%d')}.txt"
with open(report_file, "w") as f:
f.write(msg)
print(msg)
return msg
if __name__ == "__main__":
build_report(push="--push" in sys.argv)