57 lines
2.2 KiB
Python
57 lines
2.2 KiB
Python
"""BybitExecutionConfig (design §4.5): env-driven, safe defaults (testnet on, live off, kill-switch off),
|
|
and the `can_trade_live` triple-gate. Also asserts it is wired into the top-level Settings."""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from fxhnt.config import BybitExecutionConfig, Settings
|
|
|
|
|
|
def test_safe_defaults() -> None:
|
|
c = BybitExecutionConfig()
|
|
assert c.api_key == "" and c.api_secret == ""
|
|
assert c.testnet is True
|
|
assert c.allow_live is False
|
|
assert c.kill_switch is False
|
|
assert c.min_order_usd == 10.0
|
|
assert c.max_gross == 1.0
|
|
assert c.schedule_cron == "30 0 * * *"
|
|
|
|
|
|
def test_env_populates(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_API_KEY", "k")
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_API_SECRET", "s")
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_TESTNET", "false")
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_ALLOW_LIVE", "true")
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_MIN_ORDER_USD", "25")
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_MAX_GROSS", "0.5")
|
|
monkeypatch.setenv("FXHNT_BYBIT_EXEC_SCHEDULE_CRON", "0 1 * * *")
|
|
c = BybitExecutionConfig()
|
|
assert c.api_key == "k" and c.api_secret == "s"
|
|
assert c.testnet is False and c.allow_live is True
|
|
assert c.min_order_usd == 25.0 and c.max_gross == 0.5
|
|
assert c.schedule_cron == "0 1 * * *"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("testnet", "allow_live", "kill_switch", "expected"),
|
|
[
|
|
(False, True, False, True), # the only True combination
|
|
(True, True, False, False), # still testnet
|
|
(False, False, False, False), # live not allowed
|
|
(False, True, True, False), # kill switch engaged
|
|
(True, False, True, False),
|
|
(False, False, True, False),
|
|
],
|
|
)
|
|
def test_can_trade_live_truth_table(testnet: bool, allow_live: bool, kill_switch: bool,
|
|
expected: bool) -> None:
|
|
c = BybitExecutionConfig(testnet=testnet, allow_live=allow_live, kill_switch=kill_switch)
|
|
assert c.can_trade_live is expected
|
|
|
|
|
|
def test_wired_into_settings() -> None:
|
|
s = Settings()
|
|
assert isinstance(s.bybit_exec, BybitExecutionConfig)
|
|
assert s.bybit_exec.testnet is True
|