

数据是个宝,研究少烦恼
挖的深,看的远,找规律
做笔记,练盘感,多总结

★★★★★博文原创不易,源码使用过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以点赞+收藏分享+置顶,小红牛在此表示感谢。★★★★★
股票热点数据分类统计系统3.0(padans+matplotlib+sqlite3)
量化教程: 教你快速上车,通达信量化平台(TdxQuant太强了,真香啊)
Python处理复盘系统中,sqlite3数据库中的json热点和行业字段
模拟炒股K线训练系统2.0(threading+mplfinance)
通达信指标公式34:避雷参考,选股前,必须优先排除有垃圾属性的股。
通达信指标公式33:严重异动提醒,计算10/30日的涨跌幅偏离值
Excel转通达信自定义数据工具2.0 使用说明书
一、软件功能:将Excel表格中的数据转换为通达信软件可识别的自定义数据格式(外部数据/序列数据),支持自动处理股票代码前缀及市场类型。
需要安装的模块,时间久了忘了pandas里面是否包含openpyxl,如果不包含自己安装一下。
pip install pandaspip install openpyxl
二、操作步骤

完整源码如下
# -*- coding: utf-8 -*-# @Author : 小红牛# 微信公众号:gxzfp888import tkinter as tkfrom tkinter import filedialog, messagebox, scrolledtextfrom datetime import datetime, timedeltaimport pandas as pdimport osclass StockDataProcessor:def __init__(self, root):self.root = rootself.root.title("Excel转通达信自定义数据工具2.0——小红牛微信公众号:gxzfp888")self.root.geometry("1000x700")self.root.resizable(True, True)# 数据变量self.df_data = Noneself.current_headers = []self.excel_path = ""# 模式变量self.data_type = tk.StringVar(value="external")# 构建界面self.create_widgets()# ---------- 工具函数 ----------@staticmethoddef extract_code(s):"""从 'sh600519' 或 '600519.sh' 中提取6位数字代码"""if s[0].isalpha(): # 前缀格式,如 sh600519return s[-6:] # 取右边6个字符elif s[-1].isalpha(): # 后缀格式,如 600519.shreturn s[:6] # 取左边6个字符else:return s # 已经是纯数字@staticmethoddef get_stock_type(code):if code.startswith(('60', '68')):return '1'elif code.startswith(('30', '00')):return '0'elif code.startswith('92'):return '2'else:return '3'# 处理股票代码前后缀+类型def fm_stock_code(self, raw_code):code = self.extract_code(raw_code)return f"{self.get_stock_type(code)}|{code}"@staticmethoddef get_workday_today():today = datetime.today().date()if today.weekday() == 5: # 周六return today - timedelta(days=1)elif today.weekday() == 6: # 周日return today - timedelta(days=2)else:return today@staticmethoddef format_date(date_obj):return date_obj.strftime("%Y%m%d")# ---------- 业务逻辑 ----------def load_excel(self):file_path = filedialog.askopenfilename(title="选择Excel文件",filetypes=[("Excel files", "*.xlsx *.xls"), ("All files", "*.*")])if not file_path:returntry:self.df_data = pd.read_excel(file_path)self.current_headers = self.df_data.columns.tolist()# 更新 Listboxself.listbox.delete(0, tk.END)for h in self.current_headers:self.listbox.insert(tk.END, h)# 更新路径显示self.excel_path = file_pathself.entry_path.delete(0, tk.END)self.entry_path.insert(0, file_path)messagebox.showinfo("成功", f"已加载 {len(self.df_data)} 行,{len(self.current_headers)} 列")except Exception as e:messagebox.showerror("错误", f"读取Excel失败:{e}")self.df_data = Nonedef preview_and_save(self):"""处理数据并直接保存(含预览)"""if self.df_data is None:messagebox.showerror("错误", "请先加载 Excel 文件")returnselected = self.listbox.curselection()if not selected:messagebox.showerror("错误", "请先在列表中选中一个数据列")returncol_index = selected[0]col_name = self.current_headers[col_index]# 第一列为股票代码列first_col = self.df_data.columns[0]stock_codes_raw = self.df_data[first_col]data_col = self.df_data[col_name]# 获取日期(用于文件名)date_val = self.entry_date.get().strip()if not date_val:date_val = self.format_date(self.get_workday_today())if not (len(date_val) == 8 and date_val.isdigit()):messagebox.showerror("错误", "时间标签应为8位数字(YYYYMMDD),请修正日期输入框")returnmode = self.data_type.get()lines = []if mode == "external":for raw_code, val in zip(stock_codes_raw, data_col):if pd.isna(raw_code) or pd.isna(val):continuecode = self.fm_stock_code(raw_code)lines.append(f"{code}|{val}\n|0.000")if not lines:messagebox.showwarning("警告", "没有有效数据行,未保存")return# 预览self.text_display.delete(1.0, tk.END)self.text_display.insert(tk.END, "\n".join(lines))# 保存文件:使用选项值+外部+日期+基础名base_name = os.path.splitext(os.path.basename(self.excel_path))[0]filename = f"{col_name}外部{date_val}_{base_name}.txt"with open(filename, "w", encoding="utf-8") as f:f.write("\n".join(lines))messagebox.showinfo("保存成功", f"外部数据已保存至:{filename}")elif mode == "sequence":# 序列数据使用日期输入框的值作为数据标签seq_date = date_val # 与文件名中的日期保持一致for raw_code, val in zip(stock_codes_raw, data_col):if pd.isna(raw_code) or pd.isna(val):continuecode = self.fm_stock_code(raw_code)lines.append(f"{code}|{seq_date}|{val}")if not lines:messagebox.showwarning("警告", "没有有效数据行,未保存")return# 预览self.text_display.delete(1.0, tk.END)self.text_display.insert(tk.END, "\n".join(lines))base_name = os.path.splitext(os.path.basename(self.excel_path))[0]filename = f"{col_name}序列{date_val}_{base_name}.txt"with open(filename, "w", encoding="utf-8") as f:f.write("\n".join(lines))messagebox.showinfo("保存成功", f"序列数据已保存至:{filename}")else:messagebox.showerror("错误", "未知模式")# ---------- 界面布局(优化版)----------def create_widgets(self):# 顶部:文件路径区域top_frame = tk.Frame(self.root)top_frame.pack(fill=tk.X, padx=10, pady=5)tk.Label(top_frame, text="Excel文件:").pack(side=tk.LEFT, padx=5)self.entry_path = tk.Entry(top_frame, relief=tk.SUNKEN, bg="white")self.entry_path.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)btn_load = tk.Button(top_frame, text="读取Excel数据", command=self.load_excel, width=12)btn_load.pack(side=tk.LEFT, padx=5)# 中间:左右分区(左侧列名列表,右侧模式与保存)middle_frame = tk.Frame(self.root)middle_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)# 左侧:数据列标题列表框left_frame = tk.LabelFrame(middle_frame, text="选择数据列标题(单击选中一列)", padx=5, pady=5)left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)listbox_frame = tk.Frame(left_frame)listbox_frame.pack(fill=tk.BOTH, expand=True)self.listbox = tk.Listbox(listbox_frame, height=15)scrollbar = tk.Scrollbar(listbox_frame, orient=tk.VERTICAL, command=self.listbox.yview)self.listbox.configure(yscrollcommand=scrollbar.set)self.listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)# 右侧:输出模式 + 日期输入 + 保存按钮right_frame = tk.LabelFrame(middle_frame, text="参数设置", padx=10, pady=10)right_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=5)# 模式选择tk.Label(right_frame, text="输出模式:", anchor="w").pack(anchor=tk.W, pady=(0,5))rb_external = tk.Radiobutton(right_frame, text="外部数据(代码|数值或文本|0.000)",variable=self.data_type, value="external")rb_external.pack(anchor=tk.W, pady=2)rb_sequence = tk.Radiobutton(right_frame, text="序列数据(代码|日期|数值)",variable=self.data_type, value="sequence")rb_sequence.pack(anchor=tk.W, pady=2)# 日期输入(始终显示)date_frame = tk.Frame(right_frame)date_frame.pack(fill=tk.X, pady=10)tk.Label(date_frame, text="设置序列数据日期 (YYYYMMDD):").pack(side=tk.LEFT)default_date = self.format_date(self.get_workday_today())self.entry_date = tk.Entry(date_frame, width=12)self.entry_date.insert(0, default_date)self.entry_date.pack(side=tk.RIGHT)# 保存按钮(放在右侧底部)btn_save = tk.Button(right_frame, text="预览并保存", command=self.preview_and_save,bg="lightblue", font=("微软雅黑", 10), width=15)btn_save.pack(pady=15)# 底部:结果预览区域preview_frame = tk.LabelFrame(self.root, text="预览结果", padx=5, pady=5)preview_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)self.text_display = scrolledtext.ScrolledText(preview_frame, height=12, wrap=tk.WORD)self.text_display.pack(fill=tk.BOTH, expand=True)if __name__ == "__main__":root = tk.Tk()app = StockDataProcessor(root)root.mainloop()
温馨提示:股市有风险,投资需谨慎。本文所写内容仅供粉丝们参考使用,仅为个人研究观点表述,股友们须自己思考与分析股市。
-!! 完毕 ,感谢您的收看!!-
-------★★历史博文集合★★------

夜雨聆风