Big refactoring
Some checks failed
Deploy / lint (push) Failing after 21s
Deploy / test (push) Has been skipped
Deploy / deploy (push) Has been skipped

This commit is contained in:
Dennis Thiessen
2026-03-03 15:20:18 +01:00
parent 181cfe6588
commit 0a011d4ce9
55 changed files with 6898 additions and 544 deletions

View File

@@ -18,10 +18,17 @@ from app.dependencies import get_db, require_access
from app.exceptions import ProviderError
from app.models.user import User
from app.providers.alpaca import AlpacaOHLCVProvider
from app.providers.fmp import FMPFundamentalProvider
from app.providers.fundamentals_chain import build_fundamental_provider_chain
from app.providers.openai_sentiment import OpenAISentimentProvider
from app.services.rr_scanner_service import scan_ticker
from app.schemas.common import APIEnvelope
from app.services import fundamental_service, ingestion_service, sentiment_service
from app.services import (
fundamental_service,
ingestion_service,
scoring_service,
sentiment_service,
sr_service,
)
logger = logging.getLogger(__name__)
@@ -99,10 +106,10 @@ async def fetch_symbol(
}
# --- Fundamentals ---
if settings.fmp_api_key:
if settings.fmp_api_key or settings.finnhub_api_key or settings.alpha_vantage_api_key:
try:
fmp_provider = FMPFundamentalProvider(settings.fmp_api_key)
fdata = await fmp_provider.fetch_fundamentals(symbol_upper)
fundamentals_provider = build_fundamental_provider_chain()
fdata = await fundamentals_provider.fetch_fundamentals(symbol_upper)
await fundamental_service.store_fundamental(
db,
symbol=symbol_upper,
@@ -119,9 +126,50 @@ async def fetch_symbol(
else:
sources["fundamentals"] = {
"status": "skipped",
"message": "FMP API key not configured",
"message": "No fundamentals provider key configured",
}
# --- Derived pipeline: S/R levels ---
try:
levels = await sr_service.recalculate_sr_levels(db, symbol_upper)
sources["sr_levels"] = {
"status": "ok",
"count": len(levels),
"message": None,
}
except Exception as exc:
logger.error("S/R recalc failed for %s: %s", symbol_upper, exc)
sources["sr_levels"] = {"status": "error", "message": str(exc)}
# --- Derived pipeline: scores ---
try:
score_payload = await scoring_service.get_score(db, symbol_upper)
sources["scores"] = {
"status": "ok",
"composite_score": score_payload.get("composite_score"),
"missing_dimensions": score_payload.get("missing_dimensions", []),
"message": None,
}
except Exception as exc:
logger.error("Score recompute failed for %s: %s", symbol_upper, exc)
sources["scores"] = {"status": "error", "message": str(exc)}
# --- Derived pipeline: scanner ---
try:
setups = await scan_ticker(
db,
symbol_upper,
rr_threshold=settings.default_rr_threshold,
)
sources["scanner"] = {
"status": "ok",
"setups_found": len(setups),
"message": None,
}
except Exception as exc:
logger.error("Scanner run failed for %s: %s", symbol_upper, exc)
sources["scanner"] = {"status": "error", "message": str(exc)}
# Always return success — per-source breakdown tells the full story
return APIEnvelope(
status="success",