kline_app.py
import dearpygui.dearpygui as dpg
import random
from datetime import datetime, timedelta
# 全局变量
kline_data = None
def generate_random_kline_data(num_points=200, timeframe="1D"):
"""生成随机K线数据(A股风格:涨红跌绿)"""
global kline_data
now = datetime.now()
data = []
# 根据时间周期计算时间间隔
if timeframe == "1D":
delta = timedelta(days=1)
elif timeframe == "4H":
delta = timedelta(hours=4)
elif timeframe == "1H":
delta = timedelta(hours=1)
elif timeframe == "15M":
delta = timedelta(minutes=15)
elif timeframe == "5M":
delta = timedelta(minutes=5)
elif timeframe == "1M":
delta = timedelta(minutes=1)
else:
delta = timedelta(days=1)
# 初始价格
open_price = 100.0
for i in range(num_points):
timestamp = now - delta * (num_points - i)
# 随机价格波动
volatility = 0.02
high = open_price * (1 + random.uniform(0, volatility))
low = open_price * (1 - random.uniform(0, volatility))
close = open_price + random.uniform(-volatility * open_price, volatility * open_price)
# 随机成交量
volume = random.randint(1000, 10000)
data.append({
"timestamp": timestamp,
"open": open_price,
"high": high,
"low": low,
"close": close,
"volume": volume
})
open_price = close
kline_data = data
return data
def create_chart_series():
"""创建图表数据序列"""
if kline_data is None:
return
try:
# 提取K线数据
dates = list(range(len(kline_data)))
opens = [d["open"] for d in kline_data]
highs = [d["high"] for d in kline_data]
lows = [d["low"] for d in kline_data]
closes = [d["close"] for d in kline_data]
volumes = [d["volume"] for d in kline_data]
# 创建蜡烛图数据序列
dpg.add_candle_series(
dates=dates,
opens=opens,
closes=closes,
highs=highs,
lows=lows,
tag="candles",
parent="y_axis",
# A股风格:涨红跌绿
bull_color=(255, 0, 0, 255), # 上涨颜色:红色
bear_color=(0, 255, 0, 255) # 下跌颜色:绿色
)
# 创建成交量数据序列
dpg.add_bar_series(
x=dates,
y=volumes,
tag="volumes",
parent="volume_axis"
)
return True
except Exception as e:
print(f"创建图表数据序列错误: {e}")
return False
def regenerate_data():
"""重新生成随机数据"""
try:
generate_random_kline_data()
# 清空现有数据序列
if dpg.does_item_exist("candles"):
dpg.delete_item("candles")
if dpg.does_item_exist("volumes"):
dpg.delete_item("volumes")
# 创建新的数据序列
create_chart_series()
return True
except Exception as e:
print(f"重新生成数据错误: {e}")
return False
def create_main_window():
"""创建主窗口"""
with dpg.window(label="K线图分析系统", tag="main_window", width=1200, height=800):
# 顶部工具栏
with dpg.group(horizontal=True):
dpg.add_text("时间周期:")
dpg.add_radio_button(
["1M", "5M", "15M", "1H", "4H", "1D"],
label="时间周期",
default_value="1D",
tag="timeframe_radio"
)
dpg.add_spacer(width=20)
dpg.add_button(
label="重新生成数据",
callback=regenerate_data,
tag="regenerate_btn",
width=150
)
dpg.add_separator()
# 图表区域
with dpg.child_window(height=-1, width=-1, border=True):
with dpg.plot(width=-1, height=-1, tag="kline_plot"):
# 主图:K线蜡烛图
with dpg.plot_axis(dpg.mvXAxis, label="时间", tag="x_axis"):
pass
with dpg.plot_axis(dpg.mvYAxis, label="价格", tag="y_axis"):
pass
# 副图:成交量柱状图
with dpg.plot_axis(dpg.mvYAxis, label="成交量", tag="volume_axis", opposite=True):
pass
def main():
"""主函数"""
try:
# 初始化Dear PyGui
dpg.create_context()
# 配置主题(深色主题)
with dpg.theme(tag="theme"):
with dpg.theme_component(dpg.mvAll):
dpg.add_theme_color(dpg.mvThemeCol_WindowBg, (30, 30, 30, 255))
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, (40, 40, 40, 255))
dpg.add_theme_color(dpg.mvThemeCol_Text, (255, 255, 255, 255))
dpg.add_theme_style(dpg.mvStyleVar_WindowPadding, 10, 10)
dpg.add_theme_style(dpg.mvStyleVar_FramePadding, 5, 5)
dpg.bind_theme("theme")
# 创建主窗口
create_main_window()
# 生成初始数据
generate_random_kline_data()
# 创建图表数据序列
create_chart_series()
# 创建视图
dpg.create_viewport(title="K线图分析系统", width=1200, height=800)
dpg.setup_dearpygui()
# 显示窗口
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
except Exception as e:
print(f"程序启动错误: {e}")
import traceback
print("完整错误信息:")
print(traceback.format_exc())
finally:
if dpg.does_item_exist("main_window"):
try:
dpg.destroy_context()
except:
pass
if __name__ == "__main__":
main()