103 lines
3.9 KiB
Python
103 lines
3.9 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
|
|
|
|
|
|
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]
|