ihsg-forecasting-dashboard / tests /test_dashboard_data.py
ElvssYo's picture
Upgrade dashboard fullscreen chart workspace
90eddf9
Raw
History Blame Contribute Delete
4.66 kB
import pytest
from kag.dashboard.data import (
build_investment_simulation,
load_local_price_ohlcv,
load_model_metrics,
load_stock_options,
normalize_prediction_rows,
prediction_label,
)
def test_normalize_prediction_rows_casts_values():
rows = normalize_prediction_rows(
[
{
"ticker": "BBCA",
"date": "2026-05-22",
"sector": "Financials",
"close": "5875.0",
"probability_up": "0.554636",
"predicted_direction": "1",
"model_type": "lightgbm",
}
]
)
assert rows == [
{
"ticker": "BBCA",
"date": "2026-05-22",
"sector": "Financials",
"close": 5875.0,
"probability_up": 0.554636,
"predicted_direction": 1,
"model_type": "lightgbm",
}
]
def test_prediction_label_maps_known_values():
assert prediction_label(1) == "Up"
assert prediction_label(0) == "Down"
assert prediction_label(None) == "Unknown"
def test_load_model_metrics_returns_empty_for_missing_file(tmp_path):
assert load_model_metrics(tmp_path / "missing.json") == {}
def test_load_local_price_ohlcv_filters_period_and_symbol(tmp_path):
pd = pytest.importorskip("pandas")
pytest.importorskip("pyarrow")
path = tmp_path / "prices.parquet"
frame = pd.DataFrame(
[
{
"ticker": "BBCA",
"yfinance_symbol": "BBCA.JK",
"date": "2026-01-01",
"open": 100,
"high": 110,
"low": 90,
"close": 105,
"volume": 1000,
},
{
"ticker": "BBCA",
"yfinance_symbol": "BBCA.JK",
"date": "2026-05-23",
"open": 120,
"high": 130,
"low": 118,
"close": 128,
"volume": 2000,
},
{
"ticker": "BBRI",
"yfinance_symbol": "BBRI.JK",
"date": "2026-05-23",
"open": 90,
"high": 95,
"low": 88,
"close": 94,
"volume": 900,
},
]
)
frame.to_parquet(path, index=False)
rows = load_local_price_ohlcv("BBCA.JK", period="1mo", interval="1d", path=path)
assert len(rows) == 1
assert rows[0]["date"] == "2026-05-23"
assert rows[0]["close"] == 128
assert rows[0]["source"] == str(path)
def test_load_stock_options_orders_priced_stocks_first():
class RecordingClient:
def execute_read(self, query, parameters=None):
assert "count(price) > 0 AS has_price" in query
assert "coalesce(stock.universe_rank, 1000000) AS universe_rank" in query
assert "ORDER BY has_price DESC, universe_rank, ticker" in query
return [
{"ticker": "BBCA", "has_price": True, "price_points": 20},
{"ticker": "AADI", "has_price": False, "price_points": 0},
]
assert load_stock_options(RecordingClient())[0]["ticker"] == "BBCA"
def test_build_investment_simulation_uses_historical_values():
simulation = build_investment_simulation(
[
{"date": "2026-01-01", "close": 100.0},
{"date": "2026-01-02", "close": 110.0},
{"date": "2026-01-05", "close": 121.0},
],
amount=1_000_000,
entry_date="2026-01-01",
exit_date="2026-01-05",
)
assert simulation["mode"] == "historical"
assert simulation["entry_close"] == 100.0
assert simulation["exit_value"] == 1_210_000
assert len(simulation["rows"]) == 3
def test_build_investment_simulation_projects_future_weekdays():
simulation = build_investment_simulation(
[
{"date": "2026-01-01", "close": 100.0},
{"date": "2026-01-02", "close": 101.0},
{"date": "2026-01-05", "close": 102.0},
{"date": "2026-01-06", "close": 103.0},
],
amount=1_000_000,
entry_date="2026-01-02",
exit_date="2026-01-09",
probability_up=0.6,
)
assert simulation["mode"] == "projected"
assert simulation["rows"][-1]["kind"] == "projected"
assert simulation["rows"][-1]["date"] == "2026-01-09"
def test_build_investment_simulation_validates_inputs():
with pytest.raises(ValueError, match="amount"):
build_investment_simulation([], amount=0, entry_date="2026-01-01", exit_date="2026-01-02")