quanthedge / backend /app /routers /pinescript.py
jashdoshi77's picture
whole lotta changes
e6021a3
Raw
History Blame Contribute Delete
5.26 kB
"""
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 ────────────────────────────────────────────────────────────
@router.post("/generate")
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")
@router.get("/templates")
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}
@router.post("/templates/generate")
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))
@router.post("/validate")
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)
@router.post("/backtest")
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")
@router.post("/customize")
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")