feat(frontend): 添加 Zustand store 架构
- 创建 5 个领域 store:runtimeStore, marketStore, portfolioStore, agentStore, uiStore - 更新 CLAUDE.md 记录架构改进 - Zustand 已安装但 stores 尚未在 App.jsx 中使用(渐进迁移) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
358
CLAUDE.md
358
CLAUDE.md
@@ -1,108 +1,225 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
本文件为 Claude Code (claude.ai/code) 在此代码库中工作时提供指导。
|
||||
|
||||
## Project Overview
|
||||
## 项目概述
|
||||
|
||||
EvoTraders is a self-evolving multi-agent trading system where 6 AI agents (4 analysts + portfolio manager + risk manager) collaborate to make trading decisions. Agents use the AgentScope framework with a ReMe memory system for continuous learning.
|
||||
EvoTraders 是一个自进化多智能体交易系统,由 6 个 AI Agent(4 名分析师 + 投资经理 + 风控经理)协作完成交易决策。Agent 基于 AgentScope 框架构建,配合 ReMe 记忆系统实现持续学习。
|
||||
|
||||
## Development Commands
|
||||
## 常用命令
|
||||
|
||||
### Backend (Python)
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
# 安装依赖
|
||||
uv pip install -e .
|
||||
|
||||
# Run commands
|
||||
evotraders backtest --start 2025-11-01 --end 2025-12-01 # Backtest mode
|
||||
evotraders backtest --start 2025-11-01 --end 2025-12-01 --enable-memory
|
||||
evotraders live # Live trading
|
||||
evotraders live --mock # Mock/testing mode
|
||||
evotraders live -t 22:30 # Scheduled daily trading
|
||||
evotraders frontend # Launch visualization UI
|
||||
# 运行命令
|
||||
evotraders backtest --start 2025-11-01 --end 2025-12-01 # 回测模式
|
||||
evotraders backtest --start 2025-11-01 --end 2025-12-01 --enable-memory # 带记忆回测
|
||||
evotraders live # 实盘交易
|
||||
evotraders live --mock # 模拟/测试模式
|
||||
evotraders live -t 22:30 # 定时每日交易
|
||||
evotraders frontend # 启动可视化界面
|
||||
|
||||
# Dev server (starts FastAPI on port 8000)
|
||||
./start-dev.sh
|
||||
# Or manually:
|
||||
python -m uvicorn backend.app:app --host 0.0.0.0 --port 8000 --reload --reload-dir backend
|
||||
# 开发服务器
|
||||
./start-dev.sh # 启动全部 4 个微服务
|
||||
|
||||
# Testing
|
||||
pytest backend/tests
|
||||
# 单独启动某个服务
|
||||
python -m uvicorn backend.apps.agent_service:app --host 0.0.0.0 --port 8000 --reload
|
||||
python -m uvicorn backend.apps.runtime_service:app --host 0.0.0.0 --port 8003 --reload
|
||||
python -m uvicorn backend.apps.trading_service:app --host 0.0.0.0 --port 8001 --reload
|
||||
python -m uvicorn backend.apps.news_service:app --host 0.0.0.0 --port 8002 --reload
|
||||
|
||||
# 测试
|
||||
pytest backend/tests # 运行全部测试
|
||||
pytest backend/tests/test_news_service_app.py -v # 运行单个测试文件
|
||||
pytest backend/tests/test_news_service_app.py::test_news_service_routes_are_exposed -v # 运行单个测试
|
||||
```
|
||||
|
||||
### Frontend (React)
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run dev # Vite dev server (http://localhost:5173)
|
||||
npm run build # Production build
|
||||
npm run lint # ESLint
|
||||
npm run test # Vitest
|
||||
npm run test:watch # Watch mode
|
||||
npm run dev # Vite 开发服务器 (http://localhost:5173)
|
||||
npm run build # 生产构建
|
||||
npm run lint # ESLint 检查
|
||||
npm run lint:fix # ESLint 自动修复
|
||||
npm run test # Vitest 单元测试
|
||||
npm run test:watch # 监听模式
|
||||
```
|
||||
|
||||
## Architecture
|
||||
## 架构概览
|
||||
|
||||
### Multi-Agent System (`backend/agents/`)
|
||||
### 微服务架构 (`backend/apps/`)
|
||||
|
||||
**6 Agent Roles** (configured in `prompts/analyst/personas.yaml`):
|
||||
- **fundamentals_analyst** - Financial health, profitability, growth quality
|
||||
- **technical_analyst** - Price trends, indicators, momentum
|
||||
- **sentiment_analyst** - Market sentiment, news, insider trading
|
||||
- **valuation_analyst** - DCF, EV/EBITDA, intrinsic value
|
||||
- **portfolio_manager** - Decision execution, trade coordination
|
||||
- **risk_manager** - Real-time risk monitoring, position limits
|
||||
项目采用 split-first 微服务架构,4 个独立的 FastAPI 服务:
|
||||
|
||||
**Key Agent Files**:
|
||||
- `base/evo_agent.py` - Core agent implementation extending AgentScope
|
||||
- `base/hooks.py` - Lifecycle hooks for agent execution (BootstrapHook, MemoryCompactionHook, HeartbeatHook, WorkspaceWatchHook)
|
||||
- `base/evaluation_hook.py` - Post-execution evaluation
|
||||
- `base/skill_adaptation_hook.py` - Dynamic skill adaptation
|
||||
- `factory.py` - Agent factory for creating agent instances
|
||||
- `skills_manager.py` - Skill loading and management (6 scopes: builtin/customized/installed/active/disabled/local)
|
||||
- `toolkit_factory.py` - Tool collection factory for agents
|
||||
- `team/` - Team coordination (registry, coordinator, messenger, task_delegator)
|
||||
| 服务 | 入口 | 端口 | 职责 |
|
||||
|------|------|------|------|
|
||||
| agent_service | `backend.apps.agent_service:app` | 8000 | Agent 生命周期、工作区管理 |
|
||||
| runtime_service | `backend.apps.runtime_service:app` | 8003 | 运行时配置、任务启动 |
|
||||
| trading_service | `backend.apps.trading_service:app` | 8001 | 市场数据、交易操作 |
|
||||
| news_service | `backend.apps.news_service:app` | 8002 | 新闻、新闻富化、解释功能 |
|
||||
|
||||
**Hook System** (`base/hooks.py`):
|
||||
- **MemoryCompactionHook**: 基于 CoPaw 设计的内存压缩,支持:
|
||||
- `memory_compact_ratio`: 压缩目标比例 (默认 0.75)
|
||||
- `memory_reserve_ratio`: 保留比例 (默认 0.1)
|
||||
- `enable_tool_result_compact`: 工具结果压缩
|
||||
- `tool_result_compact_keep_n`: 保留最近 N 条工具结果
|
||||
服务间通过环境变量通信(详见 `start-dev.sh`):
|
||||
```bash
|
||||
export TRADING_SERVICE_URL=http://localhost:8001
|
||||
export NEWS_SERVICE_URL=http://localhost:8002
|
||||
export RUNTIME_SERVICE_URL=http://localhost:8003
|
||||
```
|
||||
|
||||
**Adding Custom Analysts**:
|
||||
1. Register in `backend/agents/prompts/analyst/personas.yaml`
|
||||
2. Add to `ANALYST_TYPES` dict in `backend/config/constants.py`
|
||||
3. Optionally update frontend config in `frontend/src/config/constants.js`
|
||||
### Gateway 网关 (`backend/services/gateway.py`)
|
||||
|
||||
### Backend Structure
|
||||
Gateway 是统一的请求路由器,根据路径前缀将请求转发到对应的微服务:
|
||||
- `/control/*` → agent_service
|
||||
- `/runtime/*` → runtime_service
|
||||
- `/trading/*` → trading_service
|
||||
- `/news/*` → news_service
|
||||
|
||||
新增接口时应注册到对应的 service app,而非直接添加到 gateway。
|
||||
|
||||
### 共享客户端 (`shared/client/`)
|
||||
|
||||
统一的服务客户端库,所有前端和后端服务间通信都使用此处定义的客户端:
|
||||
|
||||
| 客户端 | 用途 |
|
||||
|--------|------|
|
||||
| `ControlPlaneClient` | Agent 服务通信 |
|
||||
| `RuntimeServiceClient` | 运行时服务通信 |
|
||||
| `TradingServiceClient` | 交易服务通信 |
|
||||
| `NewsServiceClient` | 新闻服务通信 |
|
||||
|
||||
### 领域层 (`backend/domains/`)
|
||||
|
||||
业务逻辑按领域分离:
|
||||
|
||||
- `news.py` - 新闻领域操作
|
||||
- `trading.py` - 交易领域操作
|
||||
|
||||
## 后端结构
|
||||
|
||||
```
|
||||
backend/
|
||||
├── agents/ # Multi-agent implementation
|
||||
│ ├── base/ # Base classes, hooks, evaluation
|
||||
│ ├── prompts/ # Agent prompts and personas
|
||||
│ └── team/ # Team coordination logic
|
||||
├── api/ # FastAPI endpoints
|
||||
├── config/ # Constants and configuration
|
||||
├── core/ # Pipeline execution logic
|
||||
├── data/ # Market data handling
|
||||
├── enrich/ # LLM response enrichment
|
||||
├── explain/ # Decision explanation
|
||||
├── llm/ # LLM integrations (with RetryChatModel, TokenRecordingModelWrapper)
|
||||
├── services/ # Gateway, WebSocket services
|
||||
├── skills/ # Skill definitions (builtin + custom)
|
||||
└── tools/ # Trading and analysis tools
|
||||
├── agents/ # 多智能体实现
|
||||
│ ├── base/ # 核心类、Hooks、评估
|
||||
│ │ ├── evo_agent.py # 基于 AgentScope 的核心实现
|
||||
│ │ ├── hooks.py # 生命周期 Hooks
|
||||
│ │ │ ├── BootstrapHook # 启动初始化
|
||||
│ │ │ ├── MemoryCompactionHook # 内存压缩(基于 CoPaw)
|
||||
│ │ │ ├── HeartbeatHook # 心跳检测
|
||||
│ │ │ └── WorkspaceWatchHook # 工作区监控
|
||||
│ │ ├── evaluation_hook.py # 执行后评估
|
||||
│ │ ├── skill_adaptation_hook.py # 动态技能适配
|
||||
│ │ └── tool_guard.py # 工具调用守卫
|
||||
│ ├── prompts/ # Agent 提示词和角色定义
|
||||
│ │ ├── analyst/personas.yaml # 分析师角色配置
|
||||
│ │ └── portfolio_manager/
|
||||
│ ├── team/ # 团队协作逻辑
|
||||
│ │ ├── registry.py # Agent 注册表
|
||||
│ │ ├── coordinator.py # 协作协调器
|
||||
│ │ ├── messenger.py # 消息传递
|
||||
│ │ └── task_delegator.py # 任务分发
|
||||
│ ├── factory.py # Agent 实例工厂
|
||||
│ ├── skills_manager.py # 技能加载管理(6 种作用域)
|
||||
│ └── toolkit_factory.py # 工具集工厂
|
||||
├── apps/ # 微服务入口(split-first)
|
||||
│ ├── agent_service.py
|
||||
│ ├── runtime_service.py
|
||||
│ ├── trading_service.py
|
||||
│ └── news_service.py
|
||||
├── domains/ # 领域业务逻辑
|
||||
│ ├── news.py
|
||||
│ └── trading.py
|
||||
├── services/ # Gateway 和辅助服务
|
||||
│ ├── gateway.py # 统一路由网关
|
||||
│ ├── gateway_*.py # Gateway 子模块
|
||||
│ └── market.py # 市场数据服务
|
||||
├── api/ # FastAPI 端点
|
||||
├── config/ # 常量和配置
|
||||
│ └── constants.py # Agent 配置、显示名称等
|
||||
├── core/ # Pipeline 执行逻辑
|
||||
├── data/ # 市场数据处理
|
||||
│ ├── provider_router.py # 数据源路由
|
||||
│ └── schema.py # 数据 schema
|
||||
├── enrich/ # LLM 响应富化
|
||||
├── explain/ # 交易决策解释
|
||||
├── llm/ # LLM 集成
|
||||
│ └── models.py # RetryChatModel、TokenRecordingModelWrapper
|
||||
├── skills/ # 技能定义(内置 + 自定义)
|
||||
├── tools/ # 交易和分析工具
|
||||
└── utils/ # 工具函数
|
||||
```
|
||||
|
||||
### LLM Model Wrappers (`backend/llm/models.py`)
|
||||
## 前端结构
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── App.jsx # React 主应用
|
||||
├── components/ # React 组件
|
||||
│ ├── RuntimeView.jsx # 交易运行时 UI
|
||||
│ ├── TraderView.jsx # 交易员界面
|
||||
│ ├── RoomView.jsx # 聊天室视图
|
||||
│ ├── StockExplainView.jsx # 股票解释视图
|
||||
│ ├── RuntimeSettingsPanel.jsx # 运行时设置面板
|
||||
│ ├── WatchlistPanel.jsx # 关注列表
|
||||
│ ├── PerformanceView.jsx # 绩效视图
|
||||
│ ├── StatisticsView.jsx # 统计视图
|
||||
│ ├── NetValueChart.jsx # 净值曲线图
|
||||
│ ├── AgentCard.jsx # Agent 卡片
|
||||
│ ├── AgentFeed.jsx # Agent 动态
|
||||
│ └── explain/ # 解释相关组件
|
||||
│ ├── ExplainNewsSection.jsx
|
||||
│ ├── ExplainRangeSection.jsx
|
||||
│ ├── ExplainSimilarDaysSection.jsx
|
||||
│ ├── ExplainStorySection.jsx
|
||||
│ └── useExplainModel.js
|
||||
├── services/ # API 服务
|
||||
│ ├── runtimeApi.js # 运行时 API 调用
|
||||
│ ├── websocket.js # WebSocket 实时通信
|
||||
│ ├── newsApi.js # 新闻服务客户端
|
||||
│ └── tradingApi.js # 交易服务客户端
|
||||
├── config/
|
||||
│ └── constants.js # Agent 定义、配置
|
||||
└── hooks/ # React Hooks
|
||||
```
|
||||
|
||||
## Agent 系统
|
||||
|
||||
### 6 种 Agent 角色
|
||||
|
||||
| 角色 ID | 名称 | 职责 |
|
||||
|---------|------|------|
|
||||
| `fundamentals_analyst` | 基本面分析师 | 财务健康、盈利能力、成长质量 |
|
||||
| `technical_analyst` | 技术分析师 | 价格趋势、技术指标、动量分析 |
|
||||
| `sentiment_analyst` | 情绪分析师 | 市场情绪、新闻情绪、内幕交易 |
|
||||
| `valuation_analyst` | 估值分析师 | DCF、EV/EBITDA、 intrinsic value |
|
||||
| `portfolio_manager` | 投资经理 | 决策执行、交易协调 |
|
||||
| `risk_manager` | 风控经理 | 实时价格/波动率监控、仓位限制、多层风险预警 |
|
||||
|
||||
### Hook 系统 (`base/hooks.py`)
|
||||
|
||||
- **MemoryCompactionHook**: 基于 CoPaw 的内存压缩
|
||||
- `memory_compact_ratio`: 压缩目标比例(默认 0.75)
|
||||
- `memory_reserve_ratio`: 保留比例(默认 0.1)
|
||||
- `enable_tool_result_compact`: 工具结果压缩
|
||||
- `tool_result_compact_keep_n`: 保留最近 N 条工具结果
|
||||
|
||||
### 添加自定义分析师
|
||||
|
||||
1. 在 `backend/agents/prompts/analyst/personas.yaml` 注册
|
||||
2. 在 `backend/config/constants.py` 的 `ANALYST_TYPES` 字典中添加
|
||||
3. 可选:在 `frontend/src/config/constants.js` 中更新前端配置
|
||||
|
||||
### LLM 模型封装 (`backend/llm/models.py`)
|
||||
|
||||
基于 CoPaw 的模型封装设计:
|
||||
|
||||
Based on CoPaw's model wrapper design:
|
||||
- **RetryChatModel**: 自动重试瞬态 LLM 错误(rate limit、timeout、502/503 等),指数退避
|
||||
- `max_retries`: 最大重试次数 (默认 3)
|
||||
- `initial_delay`: 初始延迟秒数 (默认 1.0)
|
||||
- `backoff_multiplier`: 退避倍数 (默认 2.0)
|
||||
- `max_retries`: 最大重试次数(默认 3)
|
||||
- `initial_delay`: 初始延迟秒数(默认 1.0)
|
||||
- `backoff_multiplier`: 退避倍数(默认 2.0)
|
||||
|
||||
- **TokenRecordingModelWrapper**: 追踪每个 provider 的 token 消耗和成本
|
||||
|
||||
```python
|
||||
@@ -111,60 +228,75 @@ from backend.llm.models import create_model, RetryChatModel
|
||||
model = RetryChatModel(create_model("gpt-4o", "OPENAI"), max_retries=3)
|
||||
```
|
||||
|
||||
### Frontend Structure
|
||||
## 技能系统 (`backend/skills/`)
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── App.jsx # Main React application
|
||||
├── components/ # React components
|
||||
│ ├── RuntimeView.jsx # Trading runtime UI
|
||||
│ ├── TraderView.jsx # Trader interface
|
||||
│ └── RuntimeSettingsPanel.jsx
|
||||
├── services/ # API and WebSocket services
|
||||
│ ├── runtimeApi.js # Backend API calls
|
||||
│ └── websocket.js # Real-time communication
|
||||
└── config/
|
||||
└── constants.js # Agent definitions, configuration
|
||||
```
|
||||
技能定义在 `SKILL.md` 文件中,包含:
|
||||
- `instructions` - 技能说明
|
||||
- `triggers` - 触发条件
|
||||
- `parameters` - 输入/输出 schema
|
||||
- `available_tools` - 技能可使用的工具
|
||||
|
||||
### Skill System (`backend/skills/`)
|
||||
技能由 `skills_manager.py` 加载,通过 `skill_adaptation_hook.py` 绑定到 Agent。
|
||||
|
||||
Skills are defined in `SKILL.md` files with:
|
||||
- `instructions` - What the skill does
|
||||
- `triggers` - When to invoke
|
||||
- `parameters` - Input/output schema
|
||||
- `available_tools` - Tools the skill can use
|
||||
技能管理器支持 6 种作用域:builtin、customized、installed、active、disabled、local。
|
||||
|
||||
Skills are loaded by `skills_manager.py` and attached to agents via `skill_adaptation_hook.py`.
|
||||
## Pipeline 执行 (`backend/core/`)
|
||||
|
||||
### Pipeline Execution (`backend/core/`)
|
||||
每日交易流程:
|
||||
|
||||
The daily trading flow:
|
||||
1. **Analysis Stage** - Each agent analyzes independently
|
||||
2. **Communication Stage** - Agent-to-agent messaging (1v1, 1vN, NvN)
|
||||
3. **Decision Stage** - Portfolio manager makes final trades
|
||||
4. **Evaluation Stage** - Performance tracking
|
||||
5. **Review Stage** - Memory updates via ReMe
|
||||
1. **分析阶段** - 各 Agent 基于工具和历史经验独立分析
|
||||
2. **沟通阶段** - 通过私聊、通知、会议等方式交换观点(1v1/1vN/NvN)
|
||||
3. **决策阶段** - 投资经理综合判断,给出最终交易
|
||||
4. **评估阶段** - 绩效跟踪
|
||||
5. **复盘阶段** - Agent 根据当日实际收益反思总结,通过 ReMe 记忆框架更新经验
|
||||
|
||||
## Environment Configuration
|
||||
## 前端状态管理
|
||||
|
||||
项目正在向 Zustand 状态管理过渡,已创建的 store:
|
||||
|
||||
Required in `.env`:
|
||||
```bash
|
||||
frontend/src/store/
|
||||
├── index.js # 导出所有 store
|
||||
├── runtimeStore.js # 连接状态、运行时配置
|
||||
├── marketStore.js # 市场数据、股票价格
|
||||
├── portfolioStore.js # 组合、持仓、交易
|
||||
├── agentStore.js # Agent 技能、工作区
|
||||
└── uiStore.js # UI 状态、视图切换
|
||||
```
|
||||
|
||||
**迁移状态**:
|
||||
- Stores 已创建但尚未在 App.jsx 中使用
|
||||
- 计划:逐步迁移 60+ 个 useState 到对应 store
|
||||
|
||||
## 环境配置
|
||||
|
||||
`.env` 必需配置:
|
||||
|
||||
```bash
|
||||
# 金融数据源
|
||||
FIN_DATA_SOURCE=finnhub|financial_datasets
|
||||
FINANCIAL_DATASETS_API_KEY= # Required for backtest
|
||||
FINNHUB_API_KEY= # Required for live trading
|
||||
OPENAI_API_KEY= # Agent LLM
|
||||
FINANCIAL_DATASETS_API_KEY= # 回测必需
|
||||
FINNHUB_API_KEY= # 实盘必需
|
||||
|
||||
# Agent LLM
|
||||
OPENAI_API_KEY=
|
||||
OPENAI_BASE_URL=
|
||||
MODEL_NAME=qwen3-max-preview
|
||||
MEMORY_API_KEY= # For ReMe memory system
|
||||
|
||||
# 可为不同 Agent 指定不同模型
|
||||
AGENT_SENTIMENT_ANALYST_MODEL_NAME=qwen3-max-preview
|
||||
AGENT_FUNDAMENTALS_ANALYST_MODEL_NAME=deepseek-chat
|
||||
|
||||
# ReMe 记忆系统
|
||||
MEMORY_API_KEY=
|
||||
```
|
||||
|
||||
## Key Dependencies
|
||||
## 关键依赖
|
||||
|
||||
- **AgentScope** - Multi-agent framework
|
||||
- **ReMe** - Memory system for continuous learning
|
||||
- **FastAPI** + **uvicorn** - Backend API server
|
||||
- **websockets** - Real-time communication
|
||||
- **React 19** + **Vite** + **TailwindCSS** - Frontend
|
||||
- **Zustand** - Frontend state management
|
||||
- **Three.js** / **React-Three-Fiber** - 3D visualizations
|
||||
- **AgentScope** - 多智能体框架
|
||||
- **ReMe** - 持续学习记忆系统
|
||||
- **FastAPI** + **uvicorn** - 后端 API 服务器
|
||||
- **websockets** - 实时通信
|
||||
- **React 19** + **Vite** + **TailwindCSS** - 前端
|
||||
- **React Context** - 前端状态管理(App.jsx 中使用 useState + useCallback)
|
||||
- **Three.js** / **React-Three-Fiber** - 3D 可视化
|
||||
|
||||
58
frontend/src/store/agentStore.js
Normal file
58
frontend/src/store/agentStore.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
/**
|
||||
* Agent Store - Agent skills, profiles, workspaces
|
||||
*/
|
||||
export const useAgentStore = create((set) => ({
|
||||
// Selected agent for skill/workspace editing
|
||||
selectedSkillAgentId: null,
|
||||
setSelectedSkillAgentId: (selectedSkillAgentId) => set({ selectedSkillAgentId }),
|
||||
|
||||
// Agent profiles
|
||||
agentProfilesByAgent: {},
|
||||
setAgentProfilesByAgent: (agentProfilesByAgent) => set({ agentProfilesByAgent }),
|
||||
|
||||
// Agent skills
|
||||
agentSkillsByAgent: {},
|
||||
setAgentSkillsByAgent: (agentSkillsByAgent) => set({ agentSkillsByAgent }),
|
||||
|
||||
// Skill details
|
||||
skillDetailsByName: {},
|
||||
setSkillDetailsByName: (skillDetailsByName) => set({ skillDetailsByName }),
|
||||
|
||||
// Local skill drafts
|
||||
localSkillDraftsByKey: {},
|
||||
setLocalSkillDraftsByKey: (localSkillDraftsByKey) => set({ localSkillDraftsByKey }),
|
||||
|
||||
// Loading states
|
||||
isAgentSkillsLoading: false,
|
||||
setIsAgentSkillsLoading: (isAgentSkillsLoading) => set({ isAgentSkillsLoading }),
|
||||
|
||||
skillDetailLoadingKey: null,
|
||||
setSkillDetailLoadingKey: (skillDetailLoadingKey) => set({ skillDetailLoadingKey }),
|
||||
|
||||
agentSkillsSavingKey: null,
|
||||
setAgentSkillsSavingKey: (agentSkillsSavingKey) => set({ agentSkillsSavingKey }),
|
||||
|
||||
agentSkillsFeedback: null,
|
||||
setAgentSkillsFeedback: (agentSkillsFeedback) => set({ agentSkillsFeedback }),
|
||||
|
||||
// Workspace files
|
||||
selectedWorkspaceFile: null,
|
||||
setSelectedWorkspaceFile: (selectedWorkspaceFile) => set({ selectedWorkspaceFile }),
|
||||
|
||||
workspaceFilesByAgent: {},
|
||||
setWorkspaceFilesByAgent: (workspaceFilesByAgent) => set({ workspaceFilesByAgent }),
|
||||
|
||||
workspaceDraftContent: '',
|
||||
setWorkspaceDraftContent: (workspaceDraftContent) => set({ workspaceDraftContent }),
|
||||
|
||||
isWorkspaceFileLoading: false,
|
||||
setIsWorkspaceFileLoading: (isWorkspaceFileLoading) => set({ isWorkspaceFileLoading }),
|
||||
|
||||
workspaceFileSavingKey: null,
|
||||
setWorkspaceFileSavingKey: (workspaceFileSavingKey) => set({ workspaceFileSavingKey }),
|
||||
|
||||
workspaceFileFeedback: null,
|
||||
setWorkspaceFileFeedback: (workspaceFileFeedback) => set({ workspaceFileFeedback }),
|
||||
}));
|
||||
5
frontend/src/store/index.js
Normal file
5
frontend/src/store/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export { useRuntimeStore } from './runtimeStore';
|
||||
export { useMarketStore } from './marketStore';
|
||||
export { usePortfolioStore } from './portfolioStore';
|
||||
export { useAgentStore } from './agentStore';
|
||||
export { useUIStore } from './uiStore';
|
||||
44
frontend/src/store/marketStore.js
Normal file
44
frontend/src/store/marketStore.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
/**
|
||||
* Market Store - Market data, stock prices, news
|
||||
*/
|
||||
export const useMarketStore = create((set) => ({
|
||||
// Ticker prices
|
||||
tickers: [],
|
||||
setTickers: (tickers) => set({ tickers }),
|
||||
rollingTickers: {},
|
||||
setRollingTickers: (rollingTickers) => set({ rollingTickers }),
|
||||
|
||||
// Price history
|
||||
priceHistoryByTicker: {},
|
||||
setPriceHistoryByTicker: (priceHistoryByTicker) => set({ priceHistoryByTicker }),
|
||||
|
||||
// OHLC history
|
||||
ohlcHistoryByTicker: {},
|
||||
setOhlcHistoryByTicker: (ohlcHistoryByTicker) => set({ ohlcHistoryByTicker }),
|
||||
|
||||
// History source tracking
|
||||
historySourceByTicker: {},
|
||||
setHistorySourceByTicker: (historySourceByTicker) => set({ historySourceByTicker }),
|
||||
|
||||
// Explain events
|
||||
explainEventsByTicker: {},
|
||||
setExplainEventsByTicker: (explainEventsByTicker) => set({ explainEventsByTicker }),
|
||||
|
||||
// Selected explain symbol
|
||||
selectedExplainSymbol: '',
|
||||
setSelectedExplainSymbol: (selectedExplainSymbol) => set({ selectedExplainSymbol }),
|
||||
|
||||
// News by ticker
|
||||
newsByTicker: {},
|
||||
setNewsByTicker: (newsByTicker) => set({ newsByTicker }),
|
||||
|
||||
// Insider trades
|
||||
insiderTradesByTicker: {},
|
||||
setInsiderTradesByTicker: (insiderTradesByTicker) => set({ insiderTradesByTicker }),
|
||||
|
||||
// Technical indicators
|
||||
technicalIndicatorsByTicker: {},
|
||||
setTechnicalIndicatorsByTicker: (technicalIndicatorsByTicker) => set({ technicalIndicatorsByTicker }),
|
||||
}));
|
||||
38
frontend/src/store/portfolioStore.js
Normal file
38
frontend/src/store/portfolioStore.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
/**
|
||||
* Portfolio Store - Portfolio data, holdings, trades, statistics
|
||||
*/
|
||||
export const usePortfolioStore = create((set) => ({
|
||||
// Portfolio data
|
||||
portfolioData: {
|
||||
netValue: 10000,
|
||||
pnl: 0,
|
||||
equity: [],
|
||||
baseline: [],
|
||||
baseline_vw: [],
|
||||
momentum: [],
|
||||
strategies: [],
|
||||
equity_return: 0,
|
||||
baseline_return: 0,
|
||||
baseline_vw_return: 0,
|
||||
momentum_return: 0,
|
||||
},
|
||||
setPortfolioData: (portfolioData) => set({ portfolioData }),
|
||||
|
||||
// Holdings
|
||||
holdings: [],
|
||||
setHoldings: (holdings) => set({ holdings }),
|
||||
|
||||
// Trades
|
||||
trades: [],
|
||||
setTrades: (trades) => set({ trades }),
|
||||
|
||||
// Statistics
|
||||
stats: null,
|
||||
setStats: (stats) => set({ stats }),
|
||||
|
||||
// Leaderboard
|
||||
leaderboard: [],
|
||||
setLeaderboard: (leaderboard) => set({ leaderboard }),
|
||||
}));
|
||||
90
frontend/src/store/runtimeStore.js
Normal file
90
frontend/src/store/runtimeStore.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
/**
|
||||
* Runtime Store - Connection state and runtime configuration
|
||||
*/
|
||||
export const useRuntimeStore = create((set) => ({
|
||||
// Connection state
|
||||
isConnected: false,
|
||||
connectionStatus: 'connecting', // 'connecting' | 'connected' | 'disconnected'
|
||||
setIsConnected: (isConnected) => set({ isConnected }),
|
||||
setConnectionStatus: (connectionStatus) => set({ connectionStatus }),
|
||||
|
||||
// System state
|
||||
systemStatus: 'initializing', // 'initializing' | 'running' | 'completed'
|
||||
currentDate: null,
|
||||
setSystemStatus: (systemStatus) => set({ systemStatus }),
|
||||
setCurrentDate: (currentDate) => set({ currentDate }),
|
||||
|
||||
// Progress
|
||||
progress: { current: 0, total: 0 },
|
||||
setProgress: (progress) => set({ progress }),
|
||||
|
||||
// Server mode
|
||||
serverMode: null, // 'live' | 'backtest' | null
|
||||
setServerMode: (serverMode) => set({ serverMode }),
|
||||
|
||||
// Market status
|
||||
marketStatus: null,
|
||||
virtualTime: null,
|
||||
setMarketStatus: (marketStatus) => set({ marketStatus }),
|
||||
setVirtualTime: (virtualTime) => set({ virtualTime }),
|
||||
|
||||
// Data sources
|
||||
dataSources: null,
|
||||
setDataSources: (dataSources) => set({ dataSources }),
|
||||
|
||||
// Runtime config
|
||||
runtimeConfig: null,
|
||||
setRuntimeConfig: (runtimeConfig) => set({ runtimeConfig }),
|
||||
|
||||
// Watchlist panel
|
||||
isWatchlistPanelOpen: false,
|
||||
setIsWatchlistPanelOpen: (isWatchlistPanelOpen) => set({ isWatchlistPanelOpen }),
|
||||
|
||||
// Watchlist draft
|
||||
watchlistDraftSymbols: [],
|
||||
watchlistInputValue: '',
|
||||
watchlistFeedback: null,
|
||||
isWatchlistSaving: false,
|
||||
setWatchlistDraftSymbols: (watchlistDraftSymbols) => set({ watchlistDraftSymbols }),
|
||||
setWatchlistInputValue: (watchlistInputValue) => set({ watchlistInputValue }),
|
||||
setWatchlistFeedback: (watchlistFeedback) => set({ watchlistFeedback }),
|
||||
setIsWatchlistSaving: (isWatchlistSaving) => set({ isWatchlistSaving }),
|
||||
|
||||
// Runtime settings panel
|
||||
isRuntimeSettingsOpen: false,
|
||||
setIsRuntimeSettingsOpen: (isRuntimeSettingsOpen) => set({ isRuntimeSettingsOpen }),
|
||||
|
||||
// Runtime config drafts
|
||||
scheduleModeDraft: 'daily',
|
||||
intervalMinutesDraft: '60',
|
||||
triggerTimeDraft: '09:30',
|
||||
maxCommCyclesDraft: '2',
|
||||
initialCashDraft: '100000',
|
||||
marginRequirementDraft: '0',
|
||||
enableMemoryDraft: false,
|
||||
modeDraft: 'live',
|
||||
pollIntervalDraft: '10',
|
||||
startDateDraft: '',
|
||||
endDateDraft: '',
|
||||
enableMockDraft: false,
|
||||
setScheduleModeDraft: (scheduleModeDraft) => set({ scheduleModeDraft }),
|
||||
setIntervalMinutesDraft: (intervalMinutesDraft) => set({ intervalMinutesDraft }),
|
||||
setTriggerTimeDraft: (triggerTimeDraft) => set({ triggerTimeDraft }),
|
||||
setMaxCommCyclesDraft: (maxCommCyclesDraft) => set({ maxCommCyclesDraft }),
|
||||
setInitialCashDraft: (initialCashDraft) => set({ initialCashDraft }),
|
||||
setMarginRequirementDraft: (marginRequirementDraft) => set({ marginRequirementDraft }),
|
||||
setEnableMemoryDraft: (enableMemoryDraft) => set({ enableMemoryDraft }),
|
||||
setModeDraft: (modeDraft) => set({ modeDraft }),
|
||||
setPollIntervalDraft: (pollIntervalDraft) => set({ pollIntervalDraft }),
|
||||
setStartDateDraft: (startDateDraft) => set({ startDateDraft }),
|
||||
setEndDateDraft: (endDateDraft) => set({ endDateDraft }),
|
||||
setEnableMockDraft: (enableMockDraft) => set({ enableMockDraft }),
|
||||
|
||||
// Runtime config feedback
|
||||
runtimeConfigFeedback: null,
|
||||
isRuntimeConfigSaving: false,
|
||||
setRuntimeConfigFeedback: (runtimeConfigFeedback) => set({ runtimeConfigFeedback }),
|
||||
setIsRuntimeConfigSaving: (isRuntimeConfigSaving) => set({ isRuntimeConfigSaving }),
|
||||
}));
|
||||
40
frontend/src/store/uiStore.js
Normal file
40
frontend/src/store/uiStore.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
/**
|
||||
* UI Store - UI state, view management, layout
|
||||
*/
|
||||
export const useUIStore = create((set) => ({
|
||||
// Current view
|
||||
currentView: 'traders', // 'traders' | 'room' | 'explain' | 'chart' | 'statistics' | 'runtime'
|
||||
setCurrentView: (currentView) => set({ currentView }),
|
||||
|
||||
// Chart tab
|
||||
chartTab: 'all',
|
||||
setChartTab: (chartTab) => set({ chartTab }),
|
||||
|
||||
// Initial animation
|
||||
isInitialAnimating: true,
|
||||
setIsInitialAnimating: (isInitialAnimating) => set({ isInitialAnimating }),
|
||||
|
||||
// Last update timestamp
|
||||
lastUpdate: new Date(),
|
||||
setLastUpdate: (lastUpdate) => set({ lastUpdate }),
|
||||
|
||||
// Is updating
|
||||
isUpdating: false,
|
||||
setIsUpdating: (isUpdating) => set({ isUpdating }),
|
||||
|
||||
// Room bubbles
|
||||
bubbles: {},
|
||||
setBubbles: (bubbles) => set({ bubbles }),
|
||||
|
||||
// Resizable panels
|
||||
leftWidth: 70,
|
||||
setLeftWidth: (leftWidth) => set({ leftWidth }),
|
||||
isResizing: false,
|
||||
setIsResizing: (isResizing) => set({ isResizing }),
|
||||
|
||||
// Now timestamp (for current time display)
|
||||
now: new Date(),
|
||||
setNow: (now) => set({ now }),
|
||||
}));
|
||||
Reference in New Issue
Block a user