Skip to content

Commit 41c4764

Browse files
44-99claude
andcommitted
@
chore: update docs, auto paper scheduling, and gitignore - scheduler.py: add pre-market (8:30) and post-market (15:05) paper engine auto start/stop with trading calendar guard and dedup sentinel - docs/project-comparison.md: mark removed Phase 3 features as evaluated and rejected; update cc-connect comparison table to reflect current state - .gitignore: add .codegraph/, egg-info/, uv.lock, .idea/ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> @
1 parent 938bfb2 commit 41c4764

3 files changed

Lines changed: 131 additions & 24 deletions

File tree

‎.gitignore‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,14 @@ data/*.json
2222
data/*.md
2323
*.log
2424

25+
# Code intelligence
26+
.codegraph/
27+
28+
# Build artifacts
29+
src/alphaclaude.egg-info/
30+
31+
# uv
32+
uv.lock
33+
34+
# IDE
2535
.idea/

‎docs/project-comparison.md‎

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,8 @@ Vibe-Trading/
211211
- 问题:quote+technical+news+fundamental四合一调用时注入~2000 tokens
212212
- 方案:学Vibe-Trading第2层(纯字符串折叠),对工具输出做无损压缩后再注入
213213

214-
4. **统一工具注册表**
215-
- 当前:包内 CLI 工具表仍需手动维护,新增工具需手动更新 CLAUDE.md 表格
216-
- 方案:类似 Vibe-Trading 的 BaseTool 自动发现,`src/alphaclaude/tools/` 下每个工具带 metadata.json,CLAUDE.md 表格自动生成
214+
4. **统一工具注册表** ❌ 已移除
215+
- 评估结论:19 个工具新增频率 ~1次/月,手动更新 CLAUDE.md 表格只需 30 秒。auto-discovery 投入产出为负
217216

218217
**P2 — 远期储备:**
219218

@@ -430,14 +429,17 @@ cc-connect 的飞书适配器支持了 AlphaClaude 目前的飞书集成中缺
430429
| 能力 | AlphaClaude 当前 | cc-connect |
431430
|------|-----------------|------------|
432431
| 纯文本回复 | ✅ | ✅ |
433-
| 流式消息(逐 token 更新) | ❌ | ✅ |
434-
| 富交互卡片(按钮/图表/表单) | ❌ | ✅ |
432+
| 流式消息(逐 token 更新) | ✅ | ✅ |
433+
| 富交互卡片(按钮/图表/表单) | ❌ 已评估·不采用 | ✅ |
435434
| inline 按钮(消息内操作) | ❌ | ✅ |
436-
| 消息内 /mode 切换 | ❌ | ✅ |
435+
| 消息内 /mode 切换 | ❌ 已评估·不采用 | ✅ |
437436
| 多 Agent 群聊编排 | ❌ | ✅ |
438-
| 进度压缩模式(full/compact/quiet) | ❌ | ✅ |
437+
| 进度压缩模式(full/compact/quiet) | ❌ 已评估·不采用 | ✅ |
439438

440-
**最值得学的**是 **流式消息**——AlphaClaude 当前是等 Claude Code 返回全文后一次性发送,用户等待时间长。改为流式推送可以极大改善体验。
439+
**最值得学的**是 **流式消息**(已实现)和 **Session 自动轮转**(已实现)。以下三个被评估后放弃:
440+
- **冗长度模式**:单用户场景不需要持久化模式切换,说"简短点"即可
441+
- **富交互卡片**:实盘确认用纯文本 Y/N 二次确认更简单可靠
442+
- **进度压缩模式**:同上,单用户直接要求即可
441443

442444
#### 3. Session 自动轮转
443445

@@ -460,7 +462,7 @@ on_permission_denied = "notify-admin"
460462

461463
AlphaClaude 的 scheduler 有类似概念(morning/midday/closing analysis),但 Hook 更灵活——可以在任意事件上挂任意动作。
462464

463-
#### 5. 进度压缩模式
465+
#### 5. 进度压缩模式(已评估·不采用)
464466

465467
三种显示模式控制 Agent 输出在聊天中的冗长度:
466468

@@ -470,7 +472,7 @@ AlphaClaude 的 scheduler 有类似概念(morning/midday/closing analysis)
470472
| `compact` | 只显示工具调用摘要 + 最终回复 |
471473
| `quiet` | 只显示最终回复 |
472474

473-
AlphaClaude 当前相当于"full"模式,但很多场景(如手机查看)用户只想要结论。这个三层模式直接可用。
475+
> ⚠️ 2026-06-01 评估后放弃:AlphaClaude 是单用户系统,用户直接说"简短点"即可实现相同效果,不需要持久化模式状态。
474476
475477
#### 6. Web Admin UI 嵌入单二进制
476478

@@ -497,16 +499,13 @@ AlphaClaude 目前完全无 UI,如果要加一个轻量的引擎状态仪表
497499
- 改进:可配置的 idle_timeout(比如 30 分钟或 50 轮对话)后自动提示重置
498500
- 防止 Claude Code 上下文膨胀导致的响应质量下降
499501

500-
**P1 — 体验提升:**
502+
**P1 — 体验提升(全部评估后放弃):**
501503

502-
3. **回复冗长度控制**
503-
- 当前:所有分析同等详细(大量数据注入)
504-
- 改进:用户可选择 /mode compact(只显示结论+关键价位)或 /mode quiet(极简)
505-
- 股票分析场景特别适合——有时候只要"买/卖/观望"的结论
504+
3. **回复冗长度控制** ❌ 已移除
505+
- 评估结论:单用户场景,直接告诉 AI 精简回复即可,不需要持久化的 /mode 切换系统
506506

507-
4. **Feishu 富卡片**
508-
- 股票分析结果用卡片展示:表头=股票名+代码+评级,主体=关键技术指标表格,按钮="看详情"/"加入自选"
509-
- 比当前的纯文本 dump 美观很多
507+
4. **Feishu 富卡片** ❌ 已移除
508+
- 评估结论:纯文本"确认买入 XX?回复 Y/N"比卡片按钮更简单可靠,且不需要维护卡片模板代码
510509

511510
**P2 — 远期架构优化:**
512511

@@ -698,10 +697,10 @@ AlphaClaude 的 API+Tool Use 没有降级路径——Tool Use 失败直接报错
698697
- **[TradingAgents]** 风控辩论(新 3.10)→ 大额交易前 Aggressive/Conservative/Neutral 3 人辩论 + 仓位建议
699698
- **[TradingAgents]** 双模型分层 → Phase 0 子智能体用便宜模型,Phase 1-3 决策用贵模型
700699
- **[FinceptTerminal]** DataHub 设计 → 给 CLI 工具加内存缓存,避免同一股票在同一次 Claude Code 会话中重复请求行情
701-
- **[cc-connect]** 回复冗长度控制 → /mode compact(只显示结论+关键价位)/ quiet(极简)
702-
- **[cc-connect]** Feishu 富卡片 → 股票分析结果用卡片展示(股票名+K线概览+关键指标),替代纯文本 dump
700+
- ~~[cc-connect] 回复冗长度控制~~ → 已评估·不采用(单用户直接要求简约回复即可)
701+
- ~~[cc-connect] Feishu 富卡片~~ → 已评估·不采用(纯文本确认更简单可靠)
703702
- **[Vibe-Trading]** 工具输出压缩 → 学第2层 context collapse(零成本字符串折叠),减少注入 Claude Code 的冗余数据
704-
- **[Vibe-Trading]** 统一工具注册表 → `src/alphaclaude/tools/` 下每个工具带 metadata.json,CLAUDE.md 表格自动生成
703+
- ~~[Vibe-Trading] 统一工具注册表~~ → 已评估·不采用(投入产出为负)
705704
- **[AI-Trader]** 工具预计算快照 → 盘前/盘中/盘后定时预拉 19 个工具的核心输出,缓存为 JSON,减少 Claude Code 会话等待时间
706705

707706
**长期(Phase 4+)—— 建立壁垒:**

‎scheduler.py‎

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
import json
55
import logging
66
import os
7+
import subprocess
8+
import sys
79
import uuid
8-
from datetime import datetime
10+
from datetime import date, datetime
911

1012
from apscheduler.schedulers.background import BackgroundScheduler
1113
from apscheduler.triggers.cron import CronTrigger
@@ -237,6 +239,97 @@ def run_memory_consolidation() -> None:
237239
logger.error("记忆整理任务失败: %s", e, exc_info=True, extra={"category": "dream"})
238240

239241

242+
# === Paper engine scheduling ===
243+
244+
_PROJECT_ROOT = os.path.dirname(STOCK_DATA_DIR)
245+
246+
247+
def _pre_market_paper() -> None:
248+
"""盘前自动启动模拟盘引擎:检查交易日 → 停旧 → 起新"""
249+
_today = date.today()
250+
from alphaclaude.engine.trading_calendar import is_trading_day
251+
252+
if not is_trading_day(_today):
253+
logger.info("今日非交易日,跳过模拟盘启动", extra={"category": "paper"})
254+
return
255+
256+
# 防重复:同一天只启动一次
257+
_sentinel = os.path.join(STOCK_DATA_DIR, "state", ".paper_last_start")
258+
_today_str = _today.isoformat()
259+
if os.path.exists(_sentinel):
260+
try:
261+
if open(_sentinel).read().strip() == _today_str:
262+
logger.info("今日模拟盘已启动过,跳过", extra={"category": "paper"})
263+
return
264+
except OSError:
265+
pass
266+
267+
logger.info("盘前模拟盘启动开始", extra={"category": "paper"})
268+
try:
269+
# Step 1: 停止所有运行中的 paper 引擎
270+
_r1 = subprocess.run(
271+
[sys.executable, "-m", "alphaclaude.engine.cli",
272+
"--stop-running", "--mode", "paper"],
273+
capture_output=True, text=True, timeout=30,
274+
cwd=_PROJECT_ROOT,
275+
)
276+
_stdout = _r1.stdout.strip() if _r1.stdout else ""
277+
logger.info("停旧模拟盘: %s", _stdout or "无运行中进程", extra={"category": "paper"})
278+
279+
# Step 2: 启动新的 paper daemon
280+
_r2 = subprocess.run(
281+
[sys.executable, "-m", "alphaclaude.engine.cli",
282+
"--mode", "paper", "--daemon"],
283+
capture_output=True, text=True, timeout=30,
284+
cwd=_PROJECT_ROOT,
285+
)
286+
_stdout2 = _r2.stdout.strip() if _r2.stdout else ""
287+
logger.info("新模拟盘: %s", _stdout2, extra={"category": "paper"})
288+
289+
# 标记今日已启动
290+
os.makedirs(os.path.dirname(_sentinel), exist_ok=True)
291+
with open(_sentinel, "w") as _f:
292+
_f.write(_today_str)
293+
294+
_send_to_all(f"[模拟盘] 今日模拟盘已启动 | {_today_str}")
295+
except Exception as e:
296+
logger.error("模拟盘启动失败: %s", e, exc_info=True, extra={"category": "paper"})
297+
298+
299+
def _post_market_paper() -> None:
300+
"""盘后自动停止模拟盘引擎"""
301+
_today = date.today()
302+
if _today.weekday() >= 5:
303+
return
304+
305+
logger.info("盘后模拟盘停止", extra={"category": "paper"})
306+
try:
307+
_r = subprocess.run(
308+
[sys.executable, "-m", "alphaclaude.engine.cli",
309+
"--stop-running", "--mode", "paper"],
310+
capture_output=True, text=True, timeout=30,
311+
cwd=_PROJECT_ROOT,
312+
)
313+
_stdout = _r.stdout.strip() if _r.stdout else ""
314+
logger.info("停模拟盘: %s", _stdout or "无运行中进程", extra={"category": "paper"})
315+
316+
# 同时生成日报
317+
from alphaclaude.engine.cli import run_registry
318+
_runs = run_registry.list_runs("paper")
319+
if _runs:
320+
_last = _runs[0]
321+
_dr = subprocess.run(
322+
[sys.executable, "-m", "alphaclaude.tools.daily_report",
323+
_last.run_id],
324+
capture_output=True, text=True, timeout=60,
325+
cwd=_PROJECT_ROOT,
326+
)
327+
if _dr.stdout.strip():
328+
_send_to_all(_dr.stdout.strip())
329+
except Exception as e:
330+
logger.error("模拟盘停止失败: %s", e, exc_info=True, extra={"category": "paper"})
331+
332+
240333
def start_scheduler(include_market_jobs: bool = True):
241334
"""Initialize scheduler and restore user-created tasks.
242335
@@ -259,10 +352,15 @@ def start_scheduler(include_market_jobs: bool = True):
259352
id="dream_am", name="记忆整理(凌晨)")
260353
_scheduler.add_job(run_memory_consolidation, CronTrigger(hour=15, minute=17),
261354
id="dream_pm", name="记忆整理(下午)")
355+
# 模拟盘自动调度:盘前 8:30 启动,盘后 15:05 停止(交易日历兜底非交易日跳过)
356+
_scheduler.add_job(_pre_market_paper, CronTrigger(hour=8, minute=30, day_of_week="mon-fri"),
357+
id="paper_start", name="模拟盘启动")
358+
_scheduler.add_job(_post_market_paper, CronTrigger(hour=15, minute=5, day_of_week="mon-fri"),
359+
id="paper_stop", name="模拟盘停止")
262360
_scheduler.start()
263361
if include_market_jobs:
264-
msg = "定时任务已启动: 工作日 9:00/12:00/15:30 + 记忆整理 3:17/15:17"
362+
msg = "定时任务已启动: 模拟盘 8:30/15:05 + 工作日 9:00/12:00/15:30 + 记忆整理 3:17/15:17"
265363
else:
266-
msg = "定时任务已启动: 记忆整理 3:17/15:17 + 自定义任务;内置行情分析由引擎负责"
364+
msg = "定时任务已启动: 模拟盘 8:30/15:05 + 记忆整理 3:17/15:17 + 自定义任务;内置行情分析由引擎负责"
267365
logger.info(msg, extra={"category": "startup"})
268366
restore_dynamic_tasks()

0 commit comments

Comments
 (0)