Spaces:
Sleeping
Sleeping
File size: 5,259 Bytes
e6021a3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | """
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")
|