Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 22 additions & 74 deletions backend/app/data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import random

from app.schemas import (
ModelStatus,
NewsCategory,
Expand All @@ -10,66 +8,8 @@
TradingModel,
)

# Sample trading models data
SAMPLE_MODELS: list[TradingModel] = [
TradingModel(
id="1",
name="LSTM Deep Learning Model",
performance=78.5,
accuracy=82.3,
trades=145,
profit=2340.50,
status=ModelStatus.ACTIVE,
),
TradingModel(
id="2",
name="Random Forest Classifier",
performance=65.2,
accuracy=71.8,
trades=89,
profit=1250.75,
status=ModelStatus.ACTIVE,
),
TradingModel(
id="3",
name="XGBoost Regressor",
performance=71.9,
accuracy=76.4,
trades=112,
profit=1890.25,
status=ModelStatus.INACTIVE,
),
TradingModel(
id="4",
name="Support Vector Machine",
performance=55.8,
accuracy=62.1,
trades=67,
profit=-450.30,
status=ModelStatus.TRAINING,
),
TradingModel(
id="5",
name="Neural Network Ensemble",
performance=83.2,
accuracy=87.6,
trades=203,
profit=4120.80,
status=ModelStatus.ACTIVE,
),
]


def get_models_data() -> list[TradingModel]:
"""Get all trading models with some random variation in performance."""
models = []
for model in SAMPLE_MODELS:
# Add some random variation to make it more realistic
variation = random.uniform(-2, 2)
updated_model = model.model_copy()
updated_model.performance = max(0, min(100, model.performance + variation))
models.append(updated_model)
return models
# Import trading actions management
from app.trading_actions import get_trading_actions


def get_real_models_data() -> list[TradingModel]:
Expand Down Expand Up @@ -118,12 +58,6 @@ def get_real_models_data() -> list[TradingModel]:
return llm_models


def get_trades_data() -> list[Trade]:
"""Get trading history data."""
# Return empty list since SAMPLE_TRADES is commented out
return []


def get_real_trades_data(ticker: str = "NVDA", days: int = 7) -> list[Trade]:
"""Get real trading data by fetching stock prices."""
import os
Expand Down Expand Up @@ -199,11 +133,6 @@ def get_real_trades_data(ticker: str = "NVDA", days: int = 7) -> list[Trade]:
return []


def get_news_data() -> list[NewsItem]:
"""Get news data."""
return []


def get_real_news_data(query: str = "stock market", days: int = 7) -> list[NewsItem]:
"""Get real news data from Google News."""
import os
Expand Down Expand Up @@ -315,7 +244,6 @@ def get_real_news_data(query: str = "stock market", days: int = 7) -> list[NewsI

except Exception as e:
print(f"Error fetching real news: {e}")
# Fallback to sample data
return []


Expand All @@ -325,8 +253,17 @@ def get_real_social_data(
"""Get real social media data from Reddit across all categories."""
import os
import sys
import warnings
from datetime import datetime

# Suppress PRAW async warnings since we're using it correctly in FastAPI
warnings.filterwarnings("ignore", message=".*PRAW.*asynchronous.*")

# Also suppress PRAW logging warnings
import logging

logging.getLogger("praw").setLevel(logging.ERROR)

# Add trading_bench to path
project_root = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Expand Down Expand Up @@ -432,3 +369,14 @@ def get_real_social_data(
except Exception as e:
print(f"Error fetching real social data: {e}")
return []


def get_real_system_log_data(
agent_type: str = None, status: str = None, limit: int = 100, hours: int = 24
) -> list[dict]:
"""Get trading actions from system logs - ONLY trading decisions, not data fetching."""
# Get trading actions using the new system - NO SAMPLE DATA
actions = get_trading_actions(
agent_type=agent_type, status=status, limit=limit, hours=hours
)
return actions
42 changes: 40 additions & 2 deletions backend/app/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,49 @@
from app.routers import models, news, social, trades
from fastapi import FastAPI
import logging
import time

from app.routers import models, news, social, system_logs, trades
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI(
title="Live Trade Bench API",
description="FastAPI backend for trading dashboard with models, trades, and news data",
version="1.0.0",
)


# Add request logging middleware
@app.middleware("http")
async def log_requests(request: Request, call_next):
start_time = time.time()

# Log incoming request
logger.info(f"→ {request.method} {request.url.path}")

response = await call_next(request)

# Calculate processing time
process_time = time.time() - start_time

# Log response with status code and time
status_emoji = (
"✅"
if response.status_code == 200
else "❌"
if response.status_code >= 400
else "⚠️"
)
logger.info(
f"{status_emoji} {response.status_code} {request.method} {request.url.path} - {process_time:.3f}s"
)

return response


# Configure CORS
app.add_middleware(
CORSMiddleware,
Expand All @@ -22,6 +58,7 @@
app.include_router(trades.router)
app.include_router(news.router)
app.include_router(social.router)
app.include_router(system_logs.router)


@app.get("/")
Expand All @@ -35,6 +72,7 @@ async def root():
"trades": "/api/trades",
"news": "/api/news",
"social": "/api/social",
"system-log": "/api/system-log",
"docs": "/docs",
"redoc": "/redoc",
},
Expand Down
63 changes: 9 additions & 54 deletions backend/app/routers/models.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,25 @@
from app.data import SAMPLE_MODELS, get_models_data, get_real_models_data
from app.schemas import APIResponse, TradingModel
from app.data import get_real_models_data
from app.schemas import TradingModel
from fastapi import APIRouter, HTTPException

router = APIRouter(prefix="/api/models", tags=["models"])


@router.get("/", response_model=list[TradingModel])
async def get_models():
"""Get all trading models with current performance metrics."""
try:
models = get_models_data()
return models
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error fetching models: {str(e)}")


@router.get("/real", response_model=list[TradingModel])
async def get_real_models():
"""Get real LLM trading models with performance from actual predictions."""
try:
models = get_real_models_data()
return models
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Error fetching real models: {str(e)}"
)
raise HTTPException(status_code=500, detail=f"Error fetching models: {str(e)}")


@router.get("/{model_id}", response_model=TradingModel)
async def get_model(model_id: str):
"""Get a specific trading model by ID."""
"""Get a specific real trading model by ID."""
try:
models = get_models_data()
models = get_real_models_data()
model = next((m for m in models if m.id == model_id), None)
if not model:
raise HTTPException(status_code=404, detail="Model not found")
Expand All @@ -42,40 +30,16 @@ async def get_model(model_id: str):
raise HTTPException(status_code=500, detail=f"Error fetching model: {str(e)}")


@router.post("/{model_id}/toggle", response_model=APIResponse)
async def toggle_model(model_id: str):
"""Toggle a trading model's status (active/inactive)."""
try:
model = next((m for m in SAMPLE_MODELS if m.id == model_id), None)
if not model:
raise HTTPException(status_code=404, detail="Model not found")

# Toggle between active and inactive
if model.status.value == "active":
model.status = "inactive"
elif model.status.value == "inactive":
model.status = "active"

return APIResponse(
success=True,
message=f"Model {model.name} is now {model.status.value}",
data={"id": model_id, "status": model.status.value},
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error toggling model: {str(e)}")


@router.get("/{model_id}/performance")
async def get_model_performance(model_id: str):
"""Get detailed performance metrics for a specific model."""
"""Get detailed performance metrics for a specific real model."""
try:
model = next((m for m in SAMPLE_MODELS if m.id == model_id), None)
models = get_real_models_data()
model = next((m for m in models if m.id == model_id), None)
if not model:
raise HTTPException(status_code=404, detail="Model not found")

# Return detailed performance metrics
# Return real performance metrics
return {
"id": model.id,
"name": model.name,
Expand All @@ -88,15 +52,6 @@ async def get_model_performance(model_id: str):
"average_profit_per_trade": model.profit / model.trades
if model.trades > 0
else 0,
"risk_metrics": {
"sharpe_ratio": round(
model.performance / 15, 2
), # Simplified calculation
"max_drawdown": round(model.profit * 0.1, 2), # Simplified calculation
"volatility": round(
model.performance * 0.2, 2
), # Simplified calculation
},
}
except HTTPException:
raise
Expand Down
Loading
Loading