吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2918|回复: 78
上一主题 下一主题
收起左侧

[其他原创] 【黄金行情监控神器】-价格监控+阈值提醒+异动检测+邮件提醒+透明摸鱼

  [复制链接]
跳转到指定楼层
楼主
Lkkxi 发表于 2026-3-18 22:31 回帖奖励

软件简介

最近入手了积存金,由于波动较为剧烈,为了方便在办公(摸鱼)时第一时间掌握行情,闲暇时间写了这个 Gold Monitor基于自写整体框架后使用AI进行细节优化完成。它是一个常驻桌面的微型悬浮窗,设计风格参考现代化卡片 UI,主打:轻量、透明、不占地、响应快。  


核心功能

实时双金行情

  • 同时获取 沪金 (AU)国际金 (XAUUSD) 的实时报价  
  • 数据源:京东金融(接口失效可替换抓取函数)  

极致视觉体验

  • 支持 0.2 ~ 1.0 透明度调节,融入任何桌面背景  
  • DPI 适配:4K 屏不模糊(兼容不同 Windows DPI API)  
  • 任意位置拖拽 + 位置记忆:拖动后保存窗口坐标,重启仍保持位置  
  • 无边框置顶悬浮显示,不占用任务栏空间  

智能异动预警

价格预设(阈值提醒)

  • 支持 AU / 国际金 上破 / 下破 阈值  
  • 触发后系统托盘气泡通知  
  • 内置防骚扰:穿越触发锁 + 冷却时间,避免阈值附近来回波动刷屏  

波动监测(异动提醒)

  • 监控指定窗口(默认 5 分钟,可自定义)内的异常涨跌  
  • 触发后悬浮卡片以 红 / 绿 闪烁提示(上涨红、下跌绿)  
  • 内置异动冷却时间,避免连续触发影响体验  

离线邮件提醒(可选)

  • 配置 SMTP 后可离线接收提醒邮件  
  • 默认适配 163 SMTP(SSL 465)  
  • 支持界面一键发送测试邮件确认配置可用  

配置持久化

  • 所有设置均保存在本地 config.json  
  • 包含:刷新间隔、透明度、阈值、异动窗口/阈值、冷却时间、邮件配置、窗口坐标等  

关键代码(满足版块要求)

1) 两路行情抓取(沪金 / 国际金)

def _fetch_au(self):
    """沪金价格:GET pcQueryGoldProduct,取 priceValue 字段。"""
    url     = "https://ms.jr.jd.com/gw2/generic/CreatorSer/pc/m/pcQueryGoldProduct"
    params  = {"reqData": '{"goldType":"2"}'}
    headers = {"Origin": "https://jdjr.jd.com", "Referer": "https://jdjr.jd.com/"}
    try:
        res = self.session.get(url, params=params, headers=headers, timeout=2)
        res.raise_for_status()
        return float(res.json()["resultData"]["data"]["priceValue"])
    except Exception:
        return None

def _fetch_intl(self):
    """国际金价格:POST getQuoteExtendUseUniqueCodeWithCache,取 lastPrice 字段。"""
    url     = "https://ms.jr.jd.com/gw2/generic/CaiFuPC/pc/m/getQuoteExtendUseUniqueCodeWithCache"
    payload = {"ticket": "jd-jr-pc", "uniqueCode": "WG-XAUUSD"}
    try:
        res = self.session.post(url, json=payload, timeout=2)
        res.raise_for_status()
        return float(json.loads(res.json()["resultData"]["data"])["lastPrice"])
    except Exception:
        return None

2) 后台线程轮询 + 主线程刷新(避免 Tk 跨线程)

def _data_fetch_loop(self):
    """后台线程:轮询价格。禁止在此调用任何 tkinter 对象。"""
    while True:
        new_au   = self._fetch_au()
        new_intl = self._fetch_intl()

        if new_au is not None:
            with self._price_lock:
                self.prev_au = self.au
                self.au      = new_au
            self._check_alert(new_au, "AU")
            self._track_au_extreme(new_au)

        if new_intl is not None:
            with self._price_lock:
                self.prev_intl = self.intl
                self.intl      = new_intl
            self._check_alert(new_intl, "INTL")
            self._track_intl_extreme(new_intl)

        time.sleep(self.interval + random.uniform(0.08, 0.7))

def _update_ui_cycle(self):
    """主线程:消费 action 队列 + 刷新价格显示(每 200 ms)。"""
    try:
        while True:
            action = self._action_queue.get_nowait()
            if action[0] == "flash":
                self._flash_text(action[1], action[2])
    except queue.Empty:
        pass

    with self._price_lock:
        au        = self.au
        prev_au   = self.prev_au
        intl      = self.intl
        prev_intl = self.prev_intl

    if au is not None:
        self.canvas.itemconfig(self.au_value_text, text=f"{au:.2f}")
        if prev_au is not None:
            arrow = "↑" if au > prev_au else ("↓" if au < prev_au else "•")
            clr   = self.up_color if au > prev_au else (self.down_color if au < prev_au else self.muted_color)
            self.canvas.itemconfig(self.au_arrow_text, text=arrow, fill=clr)

    if intl is not None:
        self.canvas.itemconfig(self.intl_value_text, text=f"{intl:.2f}")
        if prev_intl is not None:
            arrow = "↑" if intl > prev_intl else ("↓" if intl < prev_intl else "•")
            clr   = self.up_color if intl > prev_intl else (self.down_color if intl < prev_intl else self.muted_color)
            self.canvas.itemconfig(self.intl_arrow_text, text=arrow, fill=clr)

    self.root.after(200, self._update_ui_cycle)

3) 阈值穿越提醒(触发锁 + 冷却防骚扰)

def _check_alert(self, price, symbol):
    """价格阈值穿越检测:单次穿越只通知一次 + 冷却时间防止刷屏。"""
    if price is None:
        return
    now = time.time()

    if symbol == "AU":
        if self.au_upper_target is not None:
            if price >= self.au_upper_target and not self.au_upper_triggered:
                if now - self.au_upper_last_ts >= self.alert_cooldown_sec:
                    msg = f"Au {self.au_upper_target},当前价格:{price:.2f}"
                    self._notify(msg)
                    self._send_alert_email("沪金提醒 — 上破", msg)
                    self.au_upper_last_ts = now
                self.au_upper_triggered = True
            if price < self.au_upper_target:
                self.au_upper_triggered = False

        if self.au_lower_target is not None:
            if price <= self.au_lower_target and not self.au_lower_triggered:
                if now - self.au_lower_last_ts >= self.alert_cooldown_sec:
                    msg = f"Au {self.au_lower_target},当前价格:{price:.2f}"
                    self._notify(msg)
                    self._send_alert_email("沪金提醒 — 下破", msg)
                    self.au_lower_last_ts = now
                self.au_lower_triggered = True
            if price > self.au_lower_target:
                self.au_lower_triggered = False

4) 异动检测(窗口内涨跌超过阈值触发闪烁)

def _track_au_extreme(self, price):
    if not self.extreme_enabled:
        return
    now = time.time()
    self.au_history.append((now, price))
    cutoff = now - self.extreme_window_sec
    while self.au_history and self.au_history[0][0] < cutoff:
        self.au_history.popleft()
    if len(self.au_history) < 2:
        return

    delta = price - self.au_history[0][1]
    if abs(delta) < self.extreme_threshold:
        return
    if now - self.extreme_last_ts < self.extreme_cooldown_sec:
        return

    self.extreme_last_ts = now
    self._action_queue.put(("flash", self.up_color if delta > 0 else self.down_color, self.extreme_flash_times))

5) 邮件提醒(163 SMTP SSL,异步发送不阻塞)

def send_email(self, sender, password, receiver, subject, body):
    """163 SMTP SSL 发送邮件。返回 (True, '') 成功;(False, err) 失败。"""
    try:
        msg            = MIMEText(body, "plain", "utf-8")
        msg["Subject"] = subject
        msg["From"]    = sender
        msg["To"]      = receiver
        with smtplib.SMTP_SSL("smtp.163.com", 465, timeout=10) as smtp:
            smtp.login(sender, password)
            smtp.sendmail(sender, [receiver], msg.as_string())
        return True, ""
    except Exception as e:
        return False, str(e)

def _send_alert_email(self, subject, body):
    """异步发送提醒邮件,不阻塞 fetch 循环。"""
    if not self.email_enabled:
        return
    if not all([self.email_sender, self.email_password, self.email_receiver]):
        return
    threading.Thread(
        target=self.send_email,
        args=(self.email_sender, self.email_password, self.email_receiver, subject, body),
        daemon=True
    ).start()

技术细节

  • GUI 底座: 原生 tkinter + Canvas 绘制卡片;托盘图标使用 PIL 绘制  
  • 并发逻辑: 主线程 UI 负责渲染与消费动作队列;后台线程轮询请求,保证网络不阻塞界面  
  • 避坑指南: 处理了 SetProcessDpiAwareness 的系统兼容性,且托盘菜单回调通过 root.after(...) 切回 Tk 主线程  
  • 防骚扰机制: 触发锁 + 冷却时间戳,避免阈值附近反复波动导致频繁提醒  
  • 动态刷新频率: interval + random.uniform(0.08, 0.7) 增加随机抖动  

使用说明

  • 运行环境: Python 3.8+(Windows)  
  • 依赖安装: pip install requests pystray pillow  
  • 配置文件: 首次运行会生成 config.json,也可通过界面“设置”直接修改并保存应用  
  • 邮件功能: 建议使用 163 邮箱,开启 SMTP 并使用授权码(非登录密码)  
  • 数据来源: 京东金融公开数据;如接口失效可替换 _fetch_au / _fetch_intl  

软件预览


gold.zip (9 KB, 下载次数: 362)


免责声明

本工具仅供学习交流使用,数据实时性受网络影响,不作为任何投资建议。股市(金市)有风险,入场需谨慎!

免费评分

参与人数 9吾爱币 +18 热心值 +7 收起 理由
xhl_1203 + 1 + 1 谢谢@Thanks!
landa + 1 我很赞同!
晨曦恋 + 1 + 1 谢谢@Thanks!
x60039 + 1 谢谢@Thanks!
CEXO3574 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 10 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
mask694794101 + 1 + 1 我很赞同!
ysq151 + 1 + 1 牛呀
lsb2pojie + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

来自 42#
 楼主| Lkkxi 发表于 2026-3-19 15:10 |楼主
到范围阈值成功提醒,两点这一波真够吓人啊

002.png (17.87 KB, 下载次数: 5)

002.png
推荐
不羁de流年 发表于 2026-3-27 15:18
改了一下支持另一种通知方式和GUI里面配置邮箱信息

Snipaste_2026-03-27_15-17-06.jpg (39.08 KB, 下载次数: 1)

Snipaste_2026-03-27_15-17-06.jpg

免费评分

参与人数 1热心值 +1 收起 理由
Lkkxi + 1 用心讨论,共获提升!

查看全部评分

推荐
StarTrek 发表于 2026-3-19 09:54
这个有点强了,有黄金需求的这个是真实用。
推荐
winwoo 发表于 2026-3-19 09:52
希望楼主多多发财
沙发
bgwu666 发表于 2026-3-19 01:08
试一试 感谢楼主
3#
l1438825156 发表于 2026-3-19 01:46
感谢作者分享,太强了,我去测试一下,正好有这方面需求
4#
lmyx2008 发表于 2026-3-19 02:09
积存金当定投
5#
aqcn 发表于 2026-3-19 03:58
多谢作者提供,下来试试看
6#
moabc1860 发表于 2026-3-19 05:46
楼主真是大好人非常好用的小软件
7#
woyaonide 发表于 2026-3-19 06:25
这个太好了,挂在山顶正需要这个,谢谢楼主
8#
chnhc 发表于 2026-3-19 07:50
步骤好详细,感谢作者分享
9#
lxm7888 发表于 2026-3-19 07:55
感谢分享,挺好用
10#
whitetiger28 发表于 2026-3-19 08:22
感谢分享。。。。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-17 01:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表