From 21ad31886c879896c6e717d800cc91cb2d30c222 Mon Sep 17 00:00:00 2001 From: paisley Date: Thu, 20 Nov 2025 13:35:28 +0800 Subject: [PATCH] feat: update strategy api --- .../valuecell/server/api/routers/strategy.py | 10 +++++++ .../server/api/routers/strategy_agent.py | 28 +++++++++++++++++-- .../valuecell/server/api/schemas/strategy.py | 10 +++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/python/valuecell/server/api/routers/strategy.py b/python/valuecell/server/api/routers/strategy.py index 78b07d2bd..812c23062 100644 --- a/python/valuecell/server/api/routers/strategy.py +++ b/python/valuecell/server/api/routers/strategy.py @@ -21,6 +21,7 @@ StrategyStatusSuccessResponse, StrategyStatusUpdateResponse, StrategySummaryData, + StrategyType, ) from valuecell.server.db import get_db from valuecell.server.db.models.strategy import Strategy @@ -103,6 +104,14 @@ def to_optional_float(value) -> Optional[float]: except Exception: return None + def normalize_strategy_type(meta: dict) -> Optional[StrategyType]: + raw = (meta.get("strategy_type") or "").strip().lower() + if raw == "prompt based strategy": + return StrategyType.PROMPT + if raw == "grid strategy": + return StrategyType.GRID + return None + strategy_data_list = [] for s in strategies: meta = s.strategy_metadata or {} @@ -110,6 +119,7 @@ def to_optional_float(value) -> Optional[float]: item = StrategySummaryData( strategy_id=s.strategy_id, strategy_name=s.name, + strategy_type=normalize_strategy_type(meta), status=map_status(s.status), trading_mode=normalize_trading_mode(meta, cfg), unrealized_pnl=to_optional_float(meta.get("unrealized_pnl", 0.0)), diff --git a/python/valuecell/server/api/routers/strategy_agent.py b/python/valuecell/server/api/routers/strategy_agent.py index 27b2c5a4c..39555576c 100644 --- a/python/valuecell/server/api/routers/strategy_agent.py +++ b/python/valuecell/server/api/routers/strategy_agent.py @@ -18,6 +18,7 @@ from valuecell.core.coordinate.orchestrator import AgentOrchestrator from valuecell.core.types import CommonResponseEvent, UserInput, UserInputMetadata from valuecell.server.api.schemas.base import SuccessResponse +from valuecell.server.api.schemas.strategy import StrategyType as StrategySummaryType from valuecell.server.db.connection import get_db from valuecell.server.db.repositories import get_strategy_repository from valuecell.utils.uuid import generate_conversation_id, generate_uuid @@ -31,7 +32,12 @@ def create_strategy_agent_router() -> APIRouter: @router.post("/create") async def create_strategy_agent( - request: UserRequest, db: Session = Depends(get_db) + request: UserRequest, + strategy_type: StrategySummaryType = Query( + default=StrategySummaryType.PROMPT, + description="'prompt based strategy' or 'grid strategy'", + ), + db: Session = Depends(get_db), ): """ Create a strategy through StrategyAgent and return final JSON result. @@ -98,7 +104,19 @@ async def create_strategy_agent( query = user_request.model_dump_json() - agent_name = "StrategyAgent" + # Select target agent based on strategy_type (enum) + if strategy_type == StrategySummaryType.PROMPT: + agent_name = "StrategyAgent" + elif strategy_type == StrategySummaryType.GRID: + agent_name = "GridStrategyAgent" + else: + raise HTTPException( + status_code=400, + detail=( + f"Unsupported strategy_type: '{strategy_type}'. " + "Use 'prompt based strategy' or 'grid strategy'" + ), + ) # Build UserInput for orchestrator user_input_meta = UserInputMetadata( @@ -134,6 +152,7 @@ async def create_strategy_agent( ) metadata = { "agent_name": agent_name, + "strategy_type": strategy_type.value, "model_provider": request.llm_model_config.provider, "model_id": request.llm_model_config.model_id, "exchange_id": request.exchange_config.exchange_id, @@ -174,6 +193,7 @@ async def create_strategy_agent( ) metadata = { "agent_name": agent_name, + "strategy_type": strategy_type.value, "model_provider": request.llm_model_config.provider, "model_id": request.llm_model_config.model_id, "exchange_id": request.exchange_config.exchange_id, @@ -209,6 +229,7 @@ async def create_strategy_agent( ) metadata = { "agent_name": agent_name, + "strategy_type": strategy_type.value, "model_provider": request.llm_model_config.provider, "model_id": request.llm_model_config.model_id, "exchange_id": request.exchange_config.exchange_id, @@ -246,7 +267,8 @@ async def create_strategy_agent( or f"Strategy-{fallback_strategy_id.split('-')[-1][:8]}" ) metadata = { - "agent_name": "StrategyAgent", + "agent_name": agent_name, + "strategy_type": strategy_type.value, "model_provider": request.llm_model_config.provider, "model_id": request.llm_model_config.model_id, "exchange_id": request.exchange_config.exchange_id, diff --git a/python/valuecell/server/api/schemas/strategy.py b/python/valuecell/server/api/schemas/strategy.py index 63a03c65b..96a350c5b 100644 --- a/python/valuecell/server/api/schemas/strategy.py +++ b/python/valuecell/server/api/schemas/strategy.py @@ -3,6 +3,7 @@ """ from datetime import datetime +from enum import Enum from typing import List, Literal, Optional from pydantic import BaseModel, Field @@ -10,6 +11,11 @@ from .base import SuccessResponse +class StrategyType(str, Enum): + PROMPT = "prompt based strategy" + GRID = "grid strategy" + + class StrategySummaryData(BaseModel): """Summary data for a single strategy per product spec.""" @@ -17,6 +23,10 @@ class StrategySummaryData(BaseModel): ..., description="Runtime strategy identifier from StrategyAgent" ) strategy_name: Optional[str] = Field(None, description="User-defined strategy name") + strategy_type: Optional[StrategyType] = Field( + None, + description="Strategy type identifier: 'prompt based strategy' or 'grid strategy'", + ) status: Literal["running", "stopped"] = Field(..., description="Strategy status") trading_mode: Optional[Literal["live", "virtual"]] = Field( None, description="Trading mode: live or virtual"