107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
行云科技(300209) 自动盯盘脚本
|
|
- 每5分钟拉一次新浪行情,解析现价
|
|
- 对照关键价位触发 macOS 通知提醒
|
|
- 仅在交易时段运行
|
|
"""
|
|
import subprocess
|
|
import time
|
|
import datetime
|
|
import sys
|
|
|
|
# ===== 你的持仓与关键价位配置 =====
|
|
STOCK_CODE = "sz300209" # 新浪代码
|
|
STOCK_NAME = "行云科技"
|
|
HOLD_QTY = 5000 # 持仓数量
|
|
COST = 30.052 # 持仓成本
|
|
PRESSURE1 = 35.34 # 第一压力(筹码成本)
|
|
PRESSURE2 = 39.30 # 强压力
|
|
SUPPORT1 = 32.50 # 第一支撑
|
|
SUPPORT2 = 31.19 # 强支撑(止损)
|
|
|
|
# 已提醒标记,避免同一条件反复弹窗(每个交易日内)
|
|
_alerted = set()
|
|
|
|
|
|
def now_price():
|
|
"""从新浪接口取现价,返回 (price, ts_str) 或 (None, '')"""
|
|
try:
|
|
url = f"https://hq.sinajs.cn/list={STOCK_CODE}"
|
|
out = subprocess.run(
|
|
["curl", "-s", "--max-time", "8", url,
|
|
"-H", "Referer: https://finance.sina.com.cn"],
|
|
capture_output=True, text=True, timeout=12
|
|
).stdout
|
|
# 格式: var hq_str_sz300209="名称,今开,昨收,现价,最高,最低,买一,...,时间,...,";
|
|
if "hq_str_" not in out:
|
|
return None, ""
|
|
seg = out.split('"')[1]
|
|
f = seg.split(",")
|
|
if len(f) < 32:
|
|
return None, ""
|
|
price = float(f[3])
|
|
ts = f[30] + " " + f[31]
|
|
return price, ts
|
|
except Exception:
|
|
return None, ""
|
|
|
|
|
|
def in_trading_time():
|
|
"""判断当前是否交易时段(周一~周五 9:30-11:30, 13:00-15:00)"""
|
|
now = datetime.datetime.now()
|
|
if now.weekday() >= 5: # 周六日
|
|
return False
|
|
t = now.time()
|
|
am = datetime.time(9, 30) <= t <= datetime.time(11, 30)
|
|
pm = datetime.time(13, 0) <= t <= datetime.time(15, 0)
|
|
return am or pm
|
|
|
|
|
|
def notify(title, msg):
|
|
script = f'display notification "{msg}" with title "{title}" sound name "Glass"'
|
|
subprocess.run(["osascript", "-e", script])
|
|
|
|
|
|
def check(price, ts):
|
|
global _alerted
|
|
# 每个自然日重置提醒标记
|
|
today = datetime.date.today().isoformat()
|
|
if _alerted and list(_alerted)[0].startswith("__day__"):
|
|
if not list(_alerted)[0].endswith(today):
|
|
_alerted.clear()
|
|
_alerted.add(f"__day__{today}")
|
|
|
|
pnl = (price - COST) * HOLD_QTY
|
|
base = f"{STOCK_NAME}(300209) 现价{price} 盈亏{plnl:+.0f} | {ts}"
|
|
|
|
triggers = []
|
|
if price >= PRESSURE1:
|
|
triggers.append(("减仓", f"触及压力位{PRESSURE1},缩量滞涨可减仓1/3~1/2"))
|
|
if price >= PRESSURE2:
|
|
triggers.append(("高位", f"触及强压力{PRESSURE2},接近前高,不追"))
|
|
if price <= SUPPORT2:
|
|
triggers.append(("止损", f"跌破强支撑{SUPPORT2},建议止损清仓!"))
|
|
elif price <= SUPPORT1:
|
|
triggers.append(("减仓", f"跌破支撑{SUPPORT1},建议减至1/3仓"))
|
|
|
|
for tag, tip in triggers:
|
|
key = f"{tag}_{today}"
|
|
if key not in _alerted:
|
|
_alerted.add(key)
|
|
notify(f"[{tag}] {STOCK_NAME}", f"{base} | {tip}")
|
|
|
|
|
|
def main():
|
|
if not in_trading_time():
|
|
sys.exit(0)
|
|
price, ts = now_price()
|
|
if price is None:
|
|
sys.exit(0)
|
|
check(price, ts)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|