在黄金投资领域,实时追踪持仓价值、成本计算和金价波动是关键需求。本文分享一个基于Python的GUI工具,使用Tkinter构建界面,集成新浪财经API(通过 gold_sina 模块)实现每10秒刷新金价,并自动计算未卖出黄金的市值。该工具支持数据持久化、编辑和导出,适用于个人投资者或量化爱好者。工具的核心逻辑包括:数据录入、表格显示、总结统计和实时更新。以下从需求分析、技术栈到代码拆解逐步展开。如果你有Python基础,可以直接复制代码运行;否则,可作为学习Tkinter和pandas的案例。- 支持多种黄金规格录入(如1g、1oz),自动转换为克重统一计算。
- 数据使用pandas DataFrame存储,JSON文件持久化。
- GUI:Tkinter(Python标准库,无需额外安装)。
- API调用: gold_sina.getPrice() (假设返回元/克浮点数)。
- 定时任务:Tkinter的 after 方法实现循环刷新。
Python 3.x,需安装pandas( pip install pandas )。API模块需自行实现或替换。工具采用PanedWindow分隔左右框架:左侧输入表单,右侧表格+总结标签。使用Grid布局确保自适应。- 输入使用Entry和Combobox,支持规格下拉选择。
以下按模块拆解完整代码,每段后附解释。代码总计约300行,结构清晰:类初始化、框架创建、数据操作、更新逻辑。from gold_sina import getPriceimport tkinter as tkfrom tkinter import ttk, messageboximport pandas as pdimport jsonimport uuidclassPandaGUI:def__init__(self, root): self.root = root self.root.title("实时计算GUI") self.root.grid_rowconfigure(0, weight=1) self.root.grid_columnconfigure(0, weight=1) self.paned_window = tk.PanedWindow(self.root, orient=tk.HORIZONTAL) self.paned_window.grid(row=0, column=0, sticky="nsew") self.create_input_frame() self.create_table_frame() self.data = pd.DataFrame(columns=["uuid", "买入日期", "标的", "买入价格", "规格", "卖出日期", "卖出价格", "损益"]) self.load_data() self.update_summary() self.update_real_time() self.schedule_update()
解释 :导入必要模块。 init 方法设置根窗口、PanedWindow,并初始化输入/表格框架。创建空DataFrame存储数据,加载历史记录。调用更新方法初始化总结和实时显示,并启动定时刷新。defcreate_input_frame(self): self.input_frame = tk.Frame(self.paned_window) self.paned_window.add(self.input_frame) self.input_frame.grid_rowconfigure(0, weight=1)# ... (类似设置其他行/列权重) self.buy_date_label = tk.Label(self.input_frame, text="买入日期:") self.buy_date_label.grid(row=0, column=0, padx=10, pady=5, sticky="w") self.buy_date_entry = tk.Entry(self.input_frame) self.buy_date_entry.grid(row=0, column=1, padx=10, pady=5, sticky="ew")# 类似添加其他标签和输入框:标的、规格(Combobox)、买入价格、卖出日期、卖出价格 self.submit_button = tk.Button(self.input_frame, text="确认", command=self.add_or_modify_data) self.submit_button.grid(row=6, column=0, padx=10, pady=10, sticky="ew") self.cancel_button = tk.Button(self.input_frame, text="取消", command=self.cancel_selection) self.cancel_button.grid(row=6, column=1, padx=10, pady=10, sticky="ew")
解释 :创建左侧框架,使用Grid布局放置标签和输入控件。规格使用Combobox提供预设选项。按钮绑定新增/修改和取消方法。defcreate_table_frame(self): self.table_frame = tk.Frame(self.paned_window) self.paned_window.add(self.table_frame) self.table_frame.grid_rowconfigure(0, weight=1)# ... (设置权重) self.tree = ttk.Treeview(self.table_frame, columns=("uuid", "买入日期", "标的", "买入价格", "规格", "卖出日期", "卖出价格", "损益"), show="headings")# 设置各列标题 yscroll = ttk.Scrollbar(self.table_frame, orient="vertical", command=self.tree.yview) yscroll.grid(row=0, column=1, sticky="ns") self.tree.configure(yscrollcommand=yscroll.set) xscroll = ttk.Scrollbar(self.table_frame, orient="horizontal", command=self.tree.xview) xscroll.grid(row=1, column=0, sticky="ew") self.tree.configure(xscrollcommand=xscroll.set) self.tree.grid(row=0, column=0, padx=10, pady=10, sticky="nsew") self.tree.bind("<<TreeviewSelect>>", self.on_tree_select) self.summary_label = tk.Label(self.table_frame, text="总克重: 0.0g | 买入总价: 0.0元 | 买入平均价格: 0.0元/g") self.summary_label.grid(row=2, column=0, padx=10, pady=5, sticky="w") self.real_time_label = tk.Label(self.table_frame, text="当前金价: 0.0元/g | 现有黄金价值: 0.0元") self.real_time_label.grid(row=3, column=0, padx=10, pady=5, sticky="w") self.export_button = tk.Button(self.table_frame, text="导出数据", command=self.export_data) self.export_button.grid(row=2, column=1, padx=10, pady=5, sticky="e")
解释 :创建右侧框架,Treeview显示数据表,支持滚动。绑定选中事件填充输入框。添加总结和实时标签,以及导出按钮。defadd_or_modify_data(self):# 获取输入值,校验必填ifnot buy_date ornot symbol ornot buy_price ornot spec: messagebox.showerror("输入错误", "买入日期、标的、买入价格、规格为必填项")return buy_price = float(buy_price)if sell_price: sell_price = float(sell_price) profit_loss = sell_price - buy_priceelse: sell_price = 0 profit_loss = 0 selected_item = self.tree.selection()if selected_item:# 修改逻辑:更新DataFrame和Treeviewelse:# 新增逻辑:生成UUID,追加到DataFrame和Treeview self.save_data()# 清空输入 self.update_summary() self.update_real_time()
解释 :处理确认按钮逻辑。校验输入,计算损益。若选中项存在则修改,否则新增。保存数据,更新显示。defon_tree_select(self, event):# 填充输入框以选中行数据defcancel_selection(self): self.tree.selection_remove(self.tree.selection())# 清空输入框
defsave_data(self):with open("data.json", "w") as f: self.data.to_json(f, orient="records", force_ascii=False)defload_data(self):try:with open("data.json", "r") as f: data = pd.read_json(f, orient="records") self.data = data# 插入到Treeviewexcept FileNotFoundError:passdefexport_data(self):# 导出JSON并提示
解释 :使用pandas的JSON方法保存/加载DataFrame。导出为格式化JSON。defupdate_summary(self): self.total_weight = 0.0 self.total_buy_price = 0.0 self.total_profit = 0.0for index, row in self.data.iterrows():if pd.isna(row["卖出日期"]) or row["卖出日期"] == "":# 根据规格累加克重 self.total_buy_price += float(row["买入价格"]) self.total_profit += float(row["损益"])# 计算平均价,更新标签文本
解释 :遍历DataFrame,仅统计未卖出记录。规格转换为克重(硬编码映射),计算平均。defupdate_real_time(self):try: self.current_price = getPrice('gds_AUTD')except: self.current_price = 0.0 current_value = self.total_weight * self.current_price# 更新实时标签defschedule_update(self): self.update_real_time() self.root.after(10000, self.schedule_update)
解释 :调用API获取金价,计算市值。使用 after 实现10秒循环(非阻塞)。if __name__ == "__main__": root = tk.Tk() app = PandaGUI(root) root.mainloop()
贵金属市场近期的热度再次证明:无论是避险配置还是长期资产保值,黄金、白银始终是许多人资产组合中难以替代的一部分。这个小工具虽然只是个人开发的轻量级记账+实时监控方案,但希望能帮到正在认真管理贵金属持仓的你——少花时间手动计算,多一些精力去判断市场节奏。如果你也对实物贵金属有兴趣(金条、金币、银币、投资级金银产品等),欢迎通过以下方式联系: TB店铺 搜索“爱石钱币” 或 私信咨询,实现您的财富增值与升级无论是刚入门想买几克小金豆,还是已经有一定仓位想再优化配置,都可以来聊聊。实物交割、安全寄送,力求让每一位朋友买得明白、持有安心。代码已开源,欢迎 star / fork / 提建议:https://github.com/shansui525/pythonexample/tree/main/goldtools 祝大家在贵金属的浪潮里,都能抓住属于自己的那份稳健收益。