Spaces:
Sleeping
Sleeping
| """ | |
| Pine Script Lab Router. | |
| Endpoints for Pine Script generation, template browsing, | |
| validation, backtesting, and code customization. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from typing import Any, Dict, List, Optional | |
| from fastapi import APIRouter, Depends, HTTPException | |
| from pydantic import BaseModel, Field | |
| from app.dependencies import get_current_user | |
| from app.models.user import User | |
| logger = logging.getLogger(__name__) | |
| router = APIRouter(prefix="/pinescript", tags=["Pine Script Lab"]) | |
| # ββ Schemas ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class GenerateRequest(BaseModel): | |
| description: str = Field(..., min_length=5, max_length=2000, description="Natural language description") | |
| parameters: Optional[Dict[str, Any]] = None | |
| class TemplateRequest(BaseModel): | |
| template_id: str = Field(..., min_length=1, max_length=50) | |
| parameters: Optional[Dict[str, Any]] = None | |
| class ValidateRequest(BaseModel): | |
| code: str = Field(..., min_length=10, max_length=10000) | |
| class BacktestRequest(BaseModel): | |
| code: str = Field(..., min_length=10, max_length=10000) | |
| ticker: str = Field("SPY", min_length=1, max_length=20) | |
| period: str = Field("3y") | |
| initial_capital: float = Field(100000, ge=1000) | |
| commission_pct: float = Field(0.1, ge=0, le=5) | |
| class CustomizeRequest(BaseModel): | |
| code: str = Field(..., min_length=10, max_length=10000) | |
| modification: str = Field(..., min_length=5, max_length=2000) | |
| # ββ Endpoints ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async def generate_pinescript( | |
| data: GenerateRequest, | |
| user: User = Depends(get_current_user), | |
| ): | |
| """ | |
| Generate Pine Script v5 code from a natural language description. | |
| Uses LLM (Groq) for intelligent code generation, falling back | |
| to template matching if LLM is unavailable. | |
| """ | |
| from app.services.pinescript.generator import generate_from_description | |
| try: | |
| result = await generate_from_description( | |
| description=data.description, | |
| parameters=data.parameters, | |
| ) | |
| return result | |
| except Exception as e: | |
| logger.error("Pine Script generation failed: %s", e, exc_info=True) | |
| raise HTTPException(status_code=500, detail="Generation failed") | |
| async def list_templates( | |
| user: User = Depends(get_current_user), | |
| ): | |
| """List all available strategy templates.""" | |
| from app.services.pinescript.generator import get_all_templates | |
| templates = get_all_templates() | |
| return {"total": len(templates), "templates": templates} | |
| async def generate_from_template_endpoint( | |
| data: TemplateRequest, | |
| user: User = Depends(get_current_user), | |
| ): | |
| """Generate Pine Script from a specific template with optional parameter overrides.""" | |
| from app.services.pinescript.generator import generate_from_template | |
| try: | |
| result = generate_from_template( | |
| template_id=data.template_id, | |
| parameters=data.parameters, | |
| ) | |
| return result | |
| except ValueError as e: | |
| raise HTTPException(status_code=404, detail=str(e)) | |
| async def validate_pinescript( | |
| data: ValidateRequest, | |
| user: User = Depends(get_current_user), | |
| ): | |
| """Validate Pine Script v5 syntax.""" | |
| from app.services.pinescript.validator import validate_pine_script | |
| return validate_pine_script(data.code) | |
| async def backtest_pinescript( | |
| data: BacktestRequest, | |
| user: User = Depends(get_current_user), | |
| ): | |
| """ | |
| Run a backtest on Pine Script code using historical data. | |
| Returns TradingView-style performance metrics, equity curve, | |
| trade log, and monthly returns. | |
| """ | |
| from app.services.pinescript.pine_backtester import pine_backtester | |
| try: | |
| result = await pine_backtester.backtest( | |
| code=data.code, | |
| ticker=data.ticker, | |
| period=data.period, | |
| initial_capital=data.initial_capital, | |
| commission_pct=data.commission_pct, | |
| ) | |
| return result | |
| except ValueError as e: | |
| raise HTTPException(status_code=400, detail=str(e)) | |
| except Exception as e: | |
| logger.error("Backtest failed: %s", e, exc_info=True) | |
| raise HTTPException(status_code=500, detail="Backtest failed") | |
| async def customize_pinescript( | |
| data: CustomizeRequest, | |
| user: User = Depends(get_current_user), | |
| ): | |
| """Modify existing Pine Script via LLM-powered customization.""" | |
| from app.services.pinescript.generator import customize_code | |
| try: | |
| result = await customize_code( | |
| existing_code=data.code, | |
| modification=data.modification, | |
| ) | |
| return result | |
| except Exception as e: | |
| logger.error("Customization failed: %s", e, exc_info=True) | |
| raise HTTPException(status_code=500, detail="Customization failed") | |