-
Notifications
You must be signed in to change notification settings - Fork 572
Expand file tree
/
Copy pathmonitor_ui.py
More file actions
244 lines (195 loc) · 8.77 KB
/
Copy pathmonitor_ui.py
File metadata and controls
244 lines (195 loc) · 8.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
import streamlit as st
from datetime import datetime
from typing import Dict, List
from monitor_db import monitor_db
from monitor_service import monitor_service
from notification_service import notification_service
def display_monitor_panel():
"""显示监测面板"""
st.markdown("## 📊 实时监测面板")
# 监测服务控制
col1, col2, col3, col4 = st.columns([1, 1, 1, 1])
with col1:
if st.button("▶️ 启动监测服务", type="primary"):
monitor_service.start_monitoring()
with col2:
if st.button("⏹️ 停止监测服务"):
monitor_service.stop_monitoring()
with col3:
if st.button("🔄 手动更新所有"):
stocks = monitor_service.get_stocks_needing_update()
for stock in stocks:
monitor_service.manual_update_stock(stock['id'])
st.success(f"✅ 已手动更新 {len(stocks)} 只股票")
with col4:
# 显示定时调度状态
try:
scheduler = monitor_service.get_scheduler()
status = scheduler.get_status()
if status['scheduler_running']:
st.success("⏰ 定时已启用")
else:
st.info("⏰ 定时未启用")
except:
st.info("⏰ 定时未配置")
# 显示通知
display_notifications()
# 显示监测股票
display_monitored_stocks()
def display_notifications():
"""显示通知"""
notifications = notification_service.get_streamlit_notifications()
if notifications:
st.markdown("### 🔔 最新提醒")
for notification in notifications[-5:]: # 只显示最近5条
notification_type = notification['type']
color_map = {
'entry': '🟢',
'take_profit': '🟡',
'stop_loss': '🔴'
}
icon = color_map.get(notification_type, '🔵')
st.info(f"{icon} **{notification['symbol']}** - {notification['message']}")
if st.button("清空提醒"):
notification_service.clear_streamlit_notifications()
st.rerun()
def display_monitored_stocks():
"""显示监测股票卡片"""
stocks = monitor_db.get_monitored_stocks()
if not stocks:
st.info("📋 暂无监测股票,请在分析完成后点击'加入监测'按钮添加")
return
st.markdown(f"### 📈 监测中 ({len(stocks)} 只)")
# 每行显示3个卡片
cols = st.columns(3)
for i, stock in enumerate(stocks):
col_idx = i % 3
with cols[col_idx]:
display_stock_card(stock)
def display_stock_card(stock: Dict):
"""显示单个股票监测卡片(显示交易时段设置)"""
with st.container():
# 标题行:添加交易时段标识
trading_badge = "🕒仅交易时段" if stock.get('trading_hours_only', True) else "🌐全时段"
st.markdown(f"### {stock['symbol']} - {stock['name']} {trading_badge}")
# 评级和状态
col1, col2 = st.columns([1, 1])
with col1:
rating_color = {
'买入': '🟢',
'持有': '🟡',
'卖出': '🔴'
}
st.metric("评级", f"{rating_color.get(stock['rating'], '⚪')} {stock['rating']}")
with col2:
if stock['current_price'] and stock['current_price'] != 'N/A':
st.metric("当前价格", f"¥{stock['current_price']}")
else:
st.metric("当前价格", "等待更新")
# 关键价位
entry_range = stock['entry_range']
st.info(f"**进场区间**: ¥{entry_range['min']} - ¥{entry_range['max']}")
if stock['take_profit']:
st.success(f"**止盈位**: ¥{stock['take_profit']}")
if stock['stop_loss']:
st.error(f"**止损位**: ¥{stock['stop_loss']}")
# 最后更新时间和监控模式
if stock['last_checked']:
last_checked = datetime.fromisoformat(stock['last_checked'])
st.caption(f"最后更新: {last_checked.strftime('%m-%d %H:%M')}")
# 监控模式提示
if stock.get('trading_hours_only', True):
st.caption("⏰ 监控模式:交易日 9:30-11:30, 13:00-15:00")
else:
st.caption("🌐 监控模式:全天候")
# 操作按钮
col1, col2 = st.columns([1, 1])
with col1:
if st.button("🔄 更新", key=f"update_{stock['id']}"):
if monitor_service.manual_update_stock(stock['id']):
st.success("✅ 更新成功")
else:
st.error("❌ 更新失败")
with col2:
if st.button("🗑️ 移除", key=f"remove_{stock['id']}"):
monitor_db.remove_monitored_stock(stock['id'])
st.success("✅ 已移除监测")
st.rerun()
def add_to_monitor_dialog(stock_info: Dict, analysis_result: Dict):
"""显示添加到监测的对话框(支持交易时段选项)"""
st.markdown("---")
st.markdown("## 📈 添加到实时监测")
# 从分析结果中提取关键数据
final_decision = analysis_result.get('final_decision', {})
rating = final_decision.get('rating', '持有')
reasoning = final_decision.get('reasoning', '')
# 生成唯一的session标识符
import uuid
import time
session_id = f"{stock_info.get('symbol', 'unknown')}_{int(time.time())}_{uuid.uuid4().hex[:6]}"
# 解析关键价位(从分析结果中提取或手动输入)
col1, col2 = st.columns([1, 1])
with col1:
# 进场区间
st.subheader("🎯 进场区间")
entry_min = st.number_input("最低进场价", value=0.0, key=f"entry_min_{session_id}")
entry_max = st.number_input("最高进场价", value=0.0, key=f"entry_max_{session_id}")
if entry_min > 0 and entry_max > 0 and entry_max > entry_min:
entry_range = {"min": entry_min, "max": entry_max}
else:
st.warning("请输入有效的进场区间")
entry_range = None
with col2:
# 止盈止损
st.subheader("⚖️ 风险控制")
take_profit = st.number_input("止盈价位", value=0.0, key=f"take_profit_{session_id}")
stop_loss = st.number_input("止损价位", value=0.0, key=f"stop_loss_{session_id}")
if take_profit > 0:
st.success(f"止盈位: ¥{take_profit}")
if stop_loss > 0:
st.error(f"止损位: ¥{stop_loss}")
# 监测设置
st.subheader("⏰ 监测设置")
col3, col4 = st.columns([1, 1])
with col3:
check_interval = st.slider("监测间隔(分钟)", 5, 120, 30, key=f"check_interval_{session_id}")
notification_enabled = st.checkbox("启用提醒", value=True, key=f"notification_enabled_{session_id}")
with col4:
trading_hours_only = st.checkbox(
"仅交易时段监控",
value=True,
key=f"trading_hours_only_{session_id}",
help="开启后,只在交易日的交易时段(9:30-11:30, 13:00-15:00)进行AI分析和监控"
)
st.info("💡 推荐开启,节省资源且更高效")
# 添加按钮
if st.button("✅ 确认加入监测", type="primary", key=f"add_monitor_{session_id}"):
if entry_range:
# 添加到监测数据库
stock_id = monitor_db.add_monitored_stock(
symbol=stock_info.get('symbol'),
name=stock_info.get('name'),
rating=rating,
entry_range=entry_range,
take_profit=take_profit if take_profit > 0 else None,
stop_loss=stop_loss if stop_loss > 0 else None,
check_interval=check_interval,
notification_enabled=notification_enabled,
trading_hours_only=trading_hours_only
)
st.success(f"✅ 已成功将 {stock_info.get('symbol')} 加入实时监测")
st.balloons()
# 立即更新一次价格
monitor_service.manual_update_stock(stock_id)
else:
st.error("❌ 请设置有效的进场区间")
def get_monitor_summary() -> Dict:
"""获取监测摘要信息"""
stocks = monitor_db.get_monitored_stocks()
summary = {
'total_stocks': len(stocks),
'stocks_needing_update': len(monitor_service.get_stocks_needing_update()),
'pending_notifications': len(monitor_db.get_pending_notifications()),
'active_monitoring': monitor_service.running
}
return summary