import sys
import io
import pandas as pd
import matplotlib.pyplot as plta
from datetime import datetime, timedelta
import tushare as ts
import tkinter as tk
from tkinter import ttk, messagebox
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class StockAnalysisApp:
def __init__(self, root):
self.root = root
self.root.title("股票分析系统")
self.root.geometry("600x500")
# 初始化参数
self.stock_code = '002108'
self.days = 30
self.ma_periods = [5, 10, 20]
self.create_widgets()
def create_widgets(self):
# 股票代码输入
ttk.Label(self.root, text="股票代码:").pack(pady=5)
self.code_entry = ttk.Entry(self.root)
self.code_entry.insert(0, self.stock_code)
self.code_entry.pack(pady=5)
# 天数输入
ttk.Label(self.root, text="分析天数:").pack(pady=5)
self.days_entry = ttk.Entry(self.root)
self.days_entry.insert(0, str(self.days))
self.days_entry.pack(pady=5)
# 均线周期输入
ttk.Label(self.root, text="均线周期(逗号分隔):").pack(pady=5)
self.ma_entry = ttk.Entry(self.root)
self.ma_entry.insert(0, ','.join(map(str, self.ma_periods)))
self.ma_entry.pack(pady=5)
# 运行按钮
self.run_btn = ttk.Button(self.root, text="运行分析", command=self.run_analysis)
self.run_btn.pack(pady=20)
# 结果显示区域
ttk.Label(self.root, text="分析结果:").pack(pady=5)
self.result_text = tk.Text(self.root, height=10, width=70)
self.result_text.pack(pady=5)
def run_analysis(self):
try:
# 获取参数
self.stock_code = self.code_entry.get().strip()
self.days = int(self.days_entry.get().strip())
self.ma_periods = list(map(int, [x.strip() for x in self.ma_entry.get().strip().split(',')]))
# 获取数据
stock_data = self.get_stock_data()
if stock_data is not None:
# 计算均线
for period in self.ma_periods:
stock_data[f'MA{period}'] = stock_data['close'].rolling(window=period).mean()
# 计算跌幅
first_close = stock_data['close'].iloc[0]
last_close = stock_data['close'].iloc[-1]
total_drop = ((last_close - first_close) / first_close) * 100
max_daily_drop = stock_data['Daily_Return'].min() * 100
max_drop_date = stock_data['Daily_Return'].idxmin().strftime('%Y-%m-%d')
# 显示结果
result = f"""
股票{self.stock_code}分析结果:
========================
总跌幅: {total_drop:.2f}%
最大单日跌幅: {max_daily_drop:.2f}% (日期: {max_drop_date})
起始价格: {first_close:.2f}元
结束价格: {last_close:.2f}元
分析天数: {self.days}天
均线周期: {', '.join(map(str, self.ma_periods))}
"""
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, result)
# 保存结果到文件
self.save_result_to_file(result)
# 绘制图表
self.plot_chart(stock_data)
except Exception as e:
messagebox.showerror("错误", f"运行出错: {str(e)}")
def save_result_to_file(self, result):
try:
# 保存结果到文本文件
filename = f'股票{self.stock_code}_分析结果.txt'
with open(filename, 'w', encoding='utf-8') as f:
f.write(result)
messagebox.showinfo("成功", f"分析结果已保存到 '{filename}' 文件")
except Exception as e:
messagebox.showerror("错误", f"保存文件失败: {str(e)}")
def get_stock_data(self):
try:
end_date = datetime.now()
start_date = end_date - timedelta(days=self.days)
start_str = start_date.strftime('%Y%m%d')
end_str = end_date.strftime('%Y%m%d')
ts.set_token('866b8c22a26277af04f65c453d61300c740217a4ee2e57b33c7cd199_aubb')
pro = ts.pro_api()
# 根据股票代码判断交易所
if self.stock_code.startswith('6'):
ts_code_full = self.stock_code + '.SH'
else:
ts_code_full = self.stock_code + '.SZ'
stock_data = pro.daily(ts_code=ts_code_full, start_date=start_str, end_date=end_str)
if stock_data.empty:
messagebox.showwarning("警告", "无法获取股票数据,请检查股票代码是否正确")
return None
stock_data['trade_date'] = pd.to_datetime(stock_data['trade_date'])
stock_data = stock_data.sort_values('trade_date')
stock_data.set_index('trade_date', inplace=True)
stock_data['Daily_Return'] = stock_data['close'].pct_change()
return stock_data
except Exception as e:
messagebox.showerror("错误", f"获取数据失败: {str(e)}")
return None
def plot_chart(self, stock_data):
plt.figure(figsize=(14, 8))
# 绘制收盘价
plt.plot(stock_data.index, stock_data['close'], label='收盘价', color='blue', linewidth=2)
# 绘制均线
colors = ['red', 'green', 'orange', 'purple', 'brown']
for i, period in enumerate(self.ma_periods):
plt.plot(stock_data.index, stock_data[f'MA{period}'],
label=f'MA{period}', color=colors[i % len(colors)], linewidth=1.5)
plt.title(f'股票{self.stock_code}价格走势及均线', fontsize=16)
plt.xlabel('日期', fontsize=12)
plt.ylabel('价格 (元)', fontsize=12)
plt.grid(True, alpha=0.3)
plt.legend(fontsize=10)
plt.tight_layout()
chart_path = f'股票{self.stock_code}_走势图_均线版.png'
plt.savefig(chart_path, dpi=150)
plt.show()
if __name__ == "__main__":
root = tk.Tk()
app = StockAnalysisApp(root)
root.mainloop()

股票601688分析结果:
总跌幅: -27.43%
最大单日跌幅: -5.04% (日期: 2026-01-08)
起始价格: 24.35元
结束价格: 17.67元
分析天数: 90天
均线周期: 5, 10, 20

