53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from orchestrator.config import OrchestratorConfig
|
|
from orchestrator.contracts.error_taxonomy import ReasonCode
|
|
from orchestrator.llm_runner import LLMRunner
|
|
|
|
|
|
class _SuccessfulGraph:
|
|
def propagate(self, ticker: str, date: str):
|
|
return {"ticker": ticker, "date": date}, "BUY"
|
|
|
|
|
|
class _FailingGraph:
|
|
def propagate(self, _ticker: str, _date: str):
|
|
raise RuntimeError("graph offline")
|
|
|
|
|
|
def test_llm_runner_persists_result_contract_v1alpha1(monkeypatch, tmp_path):
|
|
runner = LLMRunner(OrchestratorConfig(cache_dir=str(tmp_path)))
|
|
monkeypatch.setattr(runner, "_get_graph", lambda: _SuccessfulGraph())
|
|
|
|
signal = runner.get_signal("BRK/B", "2026-04-11")
|
|
|
|
assert signal.ticker == "BRK/B"
|
|
assert signal.direction == 1
|
|
assert signal.confidence == 0.9
|
|
assert signal.source == "llm"
|
|
assert signal.metadata["rating"] == "BUY"
|
|
assert signal.metadata["ticker"] == "BRK/B"
|
|
assert signal.metadata["date"] == "2026-04-11"
|
|
assert datetime.fromisoformat(signal.metadata["timestamp"])
|
|
|
|
cache_path = Path(tmp_path) / "BRK_B_2026-04-11.json"
|
|
assert cache_path.exists()
|
|
|
|
|
|
def test_llm_runner_returns_error_contract_when_graph_fails(monkeypatch, tmp_path):
|
|
runner = LLMRunner(OrchestratorConfig(cache_dir=str(tmp_path)))
|
|
monkeypatch.setattr(runner, "_get_graph", lambda: _FailingGraph())
|
|
|
|
signal = runner.get_signal("AAPL", "2026-04-11")
|
|
|
|
assert signal.ticker == "AAPL"
|
|
assert signal.direction == 0
|
|
assert signal.confidence == 0.0
|
|
assert signal.source == "llm"
|
|
assert signal.metadata["error"] == "graph offline"
|
|
assert signal.metadata["reason_code"] == ReasonCode.LLM_SIGNAL_FAILED.value
|
|
assert signal.metadata["contract_version"]
|
|
assert signal.metadata["source"] == "llm"
|
|
assert not (Path(tmp_path) / "AAPL_2026-04-11.json").exists()
|