feat: OpenBB Investment Analysis API
REST API wrapping OpenBB SDK for stock data, sentiment analysis, technical indicators, macro data, and rule-based portfolio analysis. - Stock data via yfinance (quote, profile, metrics, financials, historical, news) - News sentiment via Alpha Vantage (per-article, per-ticker scores) - Analyst data via Finnhub (recommendations, insider trades, upgrades) - Macro data via FRED (Fed rate, CPI, GDP, unemployment, treasury yields) - Technical indicators via openbb-technical (RSI, MACD, SMA, EMA, Bollinger) - Rule-based portfolio analysis engine (BUY_MORE/HOLD/SELL) - Stock discovery (gainers, losers, active, undervalued, growth) - 102 tests, all passing
This commit is contained in:
42
tests/test_routes_technical.py
Normal file
42
tests/test_routes_technical.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from unittest.mock import patch, AsyncMock
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient, ASGITransport
|
||||
|
||||
from main import app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def client():
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://test") as c:
|
||||
yield c
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_technical.technical_service.get_technical_indicators", new_callable=AsyncMock)
|
||||
async def test_stock_technical(mock_tech, client):
|
||||
mock_tech.return_value = {
|
||||
"symbol": "AAPL",
|
||||
"rsi_14": 55.3,
|
||||
"macd": {"macd": 1.5, "signal": 1.2, "histogram": 0.3},
|
||||
"sma_20": 180.0,
|
||||
"sma_50": 175.0,
|
||||
"sma_200": 170.0,
|
||||
"ema_12": 179.0,
|
||||
"ema_26": 176.0,
|
||||
"bollinger_bands": {"upper": 190.0, "middle": 180.0, "lower": 170.0},
|
||||
"signals": ["RSI 55.3: Neutral", "MACD histogram positive (bullish momentum)"],
|
||||
}
|
||||
resp = await client.get("/api/v1/stock/AAPL/technical")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()["data"]
|
||||
assert data["symbol"] == "AAPL"
|
||||
assert data["rsi_14"] == 55.3
|
||||
assert len(data["signals"]) == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalid_symbol_technical(client):
|
||||
resp = await client.get("/api/v1/stock/INVALID!!!/technical")
|
||||
assert resp.status_code == 400
|
||||
Reference in New Issue
Block a user