Removes all mock price simulation features: - Delete MockPriceManager from backend/data/ - Remove mock_mode, enable_mock, is_mock_mode flags from services - Remove mock CLI options and config - Remove mock mode UI components and state from frontend - Update tests to remove mock references Now system supports only live and backtest modes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
236 lines
7.3 KiB
Python
236 lines
7.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from pathlib import Path
|
|
|
|
from backend import cli
|
|
|
|
|
|
def test_live_runs_incremental_market_store_update_before_start(monkeypatch, tmp_path):
|
|
project_root = tmp_path
|
|
(project_root / ".env").write_text("FINNHUB_API_KEY=test\n", encoding="utf-8")
|
|
|
|
calls = []
|
|
|
|
monkeypatch.setattr(cli, "get_project_root", lambda: project_root)
|
|
monkeypatch.setattr(cli, "handle_history_cleanup", lambda config_name, auto_clean=False: None)
|
|
monkeypatch.setattr(cli, "run_data_updater", lambda project_root: calls.append(("run_data_updater", project_root)))
|
|
monkeypatch.setattr(
|
|
cli,
|
|
"auto_update_market_store",
|
|
lambda config_name, end_date=None: calls.append(("auto_update_market_store", config_name, end_date)),
|
|
)
|
|
monkeypatch.setattr(
|
|
cli,
|
|
"auto_enrich_market_store",
|
|
lambda config_name, end_date=None, lookback_days=120, force=False: calls.append(
|
|
("auto_enrich_market_store", config_name, end_date, lookback_days, force)
|
|
),
|
|
)
|
|
monkeypatch.setattr(cli.os, "chdir", lambda path: calls.append(("chdir", Path(path))))
|
|
|
|
def fake_run(cmd, check=True, **kwargs):
|
|
calls.append(("subprocess.run", cmd, check))
|
|
return 0
|
|
|
|
monkeypatch.setattr(cli.subprocess, "run", fake_run)
|
|
|
|
cli.live(
|
|
config_name="smoke_fullstack",
|
|
host="0.0.0.0",
|
|
port=8765,
|
|
trigger_time="now",
|
|
poll_interval=10,
|
|
clean=False,
|
|
enable_memory=False,
|
|
)
|
|
|
|
assert any(item[0] == "run_data_updater" for item in calls)
|
|
assert any(
|
|
item[0] == "auto_update_market_store" and item[1] == "smoke_fullstack"
|
|
for item in calls
|
|
)
|
|
assert any(
|
|
item[0] == "auto_enrich_market_store" and item[1] == "smoke_fullstack"
|
|
for item in calls
|
|
)
|
|
run_call = next(item for item in calls if item[0] == "subprocess.run")
|
|
assert run_call[1][:6] == [
|
|
cli.sys.executable,
|
|
"-u",
|
|
"-m",
|
|
"backend.main",
|
|
"--mode",
|
|
"live",
|
|
]
|
|
|
|
|
|
def test_backtest_runs_full_market_store_prepare_before_start(monkeypatch, tmp_path):
|
|
project_root = tmp_path
|
|
calls = []
|
|
|
|
monkeypatch.setattr(cli, "get_project_root", lambda: project_root)
|
|
monkeypatch.setattr(cli, "handle_history_cleanup", lambda config_name, auto_clean=False: None)
|
|
monkeypatch.setattr(cli, "run_data_updater", lambda project_root: calls.append(("run_data_updater", project_root)))
|
|
monkeypatch.setattr(
|
|
cli,
|
|
"auto_prepare_backtest_market_store",
|
|
lambda config_name, start_date, end_date: calls.append(
|
|
("auto_prepare_backtest_market_store", config_name, start_date, end_date)
|
|
),
|
|
)
|
|
monkeypatch.setattr(
|
|
cli,
|
|
"auto_enrich_market_store",
|
|
lambda config_name, end_date=None, lookback_days=120, force=False: calls.append(
|
|
("auto_enrich_market_store", config_name, end_date, lookback_days, force)
|
|
),
|
|
)
|
|
monkeypatch.setattr(cli.os, "chdir", lambda path: calls.append(("chdir", Path(path))))
|
|
|
|
def fake_run(cmd, check=True, **kwargs):
|
|
calls.append(("subprocess.run", cmd, check))
|
|
return 0
|
|
|
|
monkeypatch.setattr(cli.subprocess, "run", fake_run)
|
|
|
|
cli.backtest(
|
|
start="2026-03-01",
|
|
end="2026-03-10",
|
|
config_name="smoke_fullstack",
|
|
host="0.0.0.0",
|
|
port=8765,
|
|
poll_interval=10,
|
|
clean=False,
|
|
enable_memory=False,
|
|
)
|
|
|
|
assert any(item[0] == "run_data_updater" for item in calls)
|
|
assert any(
|
|
item[0] == "auto_prepare_backtest_market_store"
|
|
and item[1:] == ("smoke_fullstack", "2026-03-01", "2026-03-10")
|
|
for item in calls
|
|
)
|
|
assert any(
|
|
item[0] == "auto_enrich_market_store"
|
|
and item[1] == "smoke_fullstack"
|
|
and item[2] == "2026-03-10"
|
|
for item in calls
|
|
)
|
|
run_call = next(item for item in calls if item[0] == "subprocess.run")
|
|
assert run_call[1][:6] == [
|
|
cli.sys.executable,
|
|
"-u",
|
|
"-m",
|
|
"backend.main",
|
|
"--mode",
|
|
"backtest",
|
|
]
|
|
|
|
|
|
def test_ingest_enrich_runs_batch_enrichment(monkeypatch):
|
|
calls = []
|
|
|
|
monkeypatch.setattr(cli, "_resolve_symbols", lambda raw_tickers, config_name=None: ["AAPL", "MSFT"])
|
|
|
|
class DummyStore:
|
|
pass
|
|
|
|
monkeypatch.setattr(cli, "MarketStore", lambda: DummyStore())
|
|
monkeypatch.setattr(
|
|
cli,
|
|
"enrich_symbols",
|
|
lambda store, symbols, start_date=None, end_date=None, limit=200, analysis_source="local", skip_existing=True: calls.append(
|
|
("enrich_symbols", symbols, start_date, end_date, limit, analysis_source, skip_existing)
|
|
) or [
|
|
{
|
|
"symbol": symbol,
|
|
"news_count": 3,
|
|
"queued_count": 3,
|
|
"analyzed": 3,
|
|
"skipped_existing_count": 0,
|
|
"deduped_count": 0,
|
|
"llm_count": 0,
|
|
"local_count": 3,
|
|
}
|
|
for symbol in symbols
|
|
],
|
|
)
|
|
|
|
cli.ingest_enrich(
|
|
tickers=None,
|
|
start="2026-03-01",
|
|
end="2026-03-10",
|
|
limit=150,
|
|
force=False,
|
|
config_name="smoke_fullstack",
|
|
)
|
|
|
|
assert calls == [
|
|
("enrich_symbols", ["AAPL", "MSFT"], "2026-03-01", "2026-03-10", 150, "local", True)
|
|
]
|
|
|
|
|
|
def test_ingest_report_reads_market_store_report(monkeypatch):
|
|
calls = []
|
|
printed = []
|
|
|
|
monkeypatch.setattr(cli, "_resolve_symbols", lambda raw_tickers, config_name=None: ["AAPL"])
|
|
|
|
class DummyStore:
|
|
def get_enrich_report(self, symbols=None, start_date=None, end_date=None):
|
|
calls.append(("get_enrich_report", symbols, start_date, end_date))
|
|
return [
|
|
{
|
|
"symbol": "AAPL",
|
|
"raw_news_count": 10,
|
|
"analyzed_news_count": 8,
|
|
"coverage_pct": 80.0,
|
|
"llm_count": 5,
|
|
"local_count": 3,
|
|
"latest_trade_date": "2026-03-16",
|
|
"latest_analysis_at": "2026-03-16T09:00:00",
|
|
}
|
|
]
|
|
|
|
monkeypatch.setattr(cli, "MarketStore", lambda: DummyStore())
|
|
monkeypatch.setattr(cli, "get_explain_model_info", lambda: {"provider": "DASHSCOPE", "model_name": "qwen-max", "label": "DASHSCOPE:qwen-max"})
|
|
monkeypatch.setattr(cli, "llm_enrichment_enabled", lambda: True)
|
|
monkeypatch.setattr(cli.console, "print", lambda value: printed.append(value))
|
|
|
|
cli.ingest_report(
|
|
tickers=None,
|
|
start="2026-03-01",
|
|
end="2026-03-16",
|
|
config_name="smoke_fullstack",
|
|
only_problematic=False,
|
|
)
|
|
|
|
assert calls == [
|
|
("get_enrich_report", ["AAPL"], "2026-03-01", "2026-03-16")
|
|
]
|
|
assert printed
|
|
assert getattr(printed[0], "caption", "") == "Explain LLM: DASHSCOPE:qwen-max"
|
|
|
|
|
|
def test_filter_problematic_report_rows_keeps_low_coverage_and_no_llm():
|
|
rows = [
|
|
{
|
|
"symbol": "AAPL",
|
|
"coverage_pct": 100.0,
|
|
"llm_count": 2,
|
|
},
|
|
{
|
|
"symbol": "MSFT",
|
|
"coverage_pct": 80.0,
|
|
"llm_count": 1,
|
|
},
|
|
{
|
|
"symbol": "NVDA",
|
|
"coverage_pct": 100.0,
|
|
"llm_count": 0,
|
|
},
|
|
]
|
|
|
|
filtered = cli._filter_problematic_report_rows(rows)
|
|
|
|
assert [row["symbol"] for row in filtered] == ["MSFT", "NVDA"]
|