Files
TradeBot/tests/test_dashboard.py
T

106 lines
4.0 KiB
Python

from __future__ import annotations
import json
from crypto_spot_bot.dashboard import _compact_markets
from crypto_spot_bot.dashboard import _apply_fast_trading
from crypto_spot_bot.dashboard import _safe_config
from crypto_spot_bot.dashboard import WEB_INDEX
from crypto_spot_bot.storage import Storage
def test_apply_fast_trading_updates_runtime_and_env(make_settings, tmp_path) -> None:
settings = make_settings(tmp_path, fast_trading_enabled=False)
settings.env_file_path.write_text("FAST_TRADING_ENABLED=false\n", encoding="utf-8")
storage = Storage(settings.database_path)
env_persisted = _apply_fast_trading(settings, storage, True)
assert env_persisted is True
assert settings.fast_trading_enabled is True
assert storage.get_runtime("fast_trading_enabled") is True
assert "FAST_TRADING_ENABLED=true" in settings.env_file_path.read_text(encoding="utf-8")
def test_safe_config_summarizes_torch_forecast_artifact(make_settings, tmp_path) -> None:
artifact_path = tmp_path / "lstm_forecaster.json"
artifact_path.write_text(
json.dumps(
{
"type": "pytorch_recurrent_forecaster",
"created_at": "2026-06-20T18:15:05+00:00",
"symbols": {
"BTCUSDT": {"model": "torch_lstm"},
"ETHUSDT": {"model": "torch_gru"},
},
}
),
encoding="utf-8",
)
settings = make_settings(tmp_path, time_series_lstm_model_path=artifact_path)
config = _safe_config(settings)
assert config["time_series_probe_enabled"] is True
assert config["time_series_probe_min_edge_percent"] == 0.02
assert config["time_series_probe_min_probability_up"] == 0.55
assert config["time_series_probe_size_multiplier"] == 0.40
assert config["time_series_rebound_fallback_enabled"] is True
assert config["time_series_fallback_mode"] == "trend_macd"
assert config["market_observation_enabled"] is True
assert config["market_observation_sample_seconds"] == 30.0
assert config["time_series_model_artifact"] == {
"available": True,
"type": "pytorch_recurrent_forecaster",
"label": "PyTorch LSTM/GRU",
"created_at": "2026-06-20T18:15:05+00:00",
"symbol_count": 2,
"models": ["PyTorch GRU", "PyTorch LSTM"],
"feature_count": 1,
"target_horizon": 0,
"direct_horizon": False,
}
def test_web_ui_assets_are_available() -> None:
html = WEB_INDEX.read_text(encoding="utf-8")
assert "TradeBot — панель управления" in html
assert "/assets/dashboard.css" in html
assert "/assets/dashboard.js" in html
assert "/web-api/dashboard/snapshot" in WEB_INDEX.with_name("dashboard.js").read_text(
encoding="utf-8"
)
def test_compact_markets_keeps_dashboard_fields_and_limits_candles() -> None:
candles = [{"timestamp": index, "close": 100 + index, "open": 1} for index in range(60)]
compact = _compact_markets(
{
"symbols": ["BTCUSDT"],
"ws_connected": True,
"rest_error_count": 2,
"markets": [
{
"ticker": {"symbol": "BTCUSDT", "last_price": 160},
"candles": candles,
"forecast": {"expected_return_percent": 0.4},
"shadow_forecast": {"expected_return_percent": 0.5},
"orderbook": {"spread_bps": 1.2},
"quality": {"status": "ok"},
"instrument": {"symbol": "BTCUSDT"},
}
],
}
)
assert compact["ws_connected"] is True
assert compact["rest_error_count"] == 2
assert compact["markets"][0]["ticker"]["symbol"] == "BTCUSDT"
assert len(compact["markets"][0]["sparkline"]) == 48
assert compact["markets"][0]["sparkline"][0] == {"timestamp": 12, "close": 112}
assert "instrument" not in compact["markets"][0]
assert "orderbook" not in compact["markets"][0]
assert "shadow_forecast" not in compact["markets"][0]