ParallelLLC/algorithmic_trading
2732
1"""CLI surface — argument handling and that each command actually completes."""2 3from __future__ import annotations4 5import json6 7import pytest8 9from algotrader.cli import _parse_params, main10 11 12class TestArgumentParsing:13 def test_params_are_parsed_into_floats(self):14 assert _parse_params(["fast=10", "slow=50.5"]) == {"fast": 10.0, "slow": 50.5}15 16 def test_params_without_an_equals_sign_are_rejected(self):17 with pytest.raises(SystemExit, match="name=value"):18 _parse_params(["fast10"])19 20 def test_no_params_is_an_empty_dict(self):21 assert _parse_params(None) == {}22 23 def test_an_unknown_strategy_is_rejected_at_parse_time(self):24 with pytest.raises(SystemExit):25 main(["lab", "--strategy", "nope"])26 27 def test_a_missing_subcommand_is_rejected(self):28 with pytest.raises(SystemExit):29 main([])30 31 32class TestCommands:33 """All runs force the simulator so the suite never touches the network."""34 35 def test_lab_prints_a_report(self, capsys):36 code = main([37 "lab", "--symbol", "SPY", "--source", "synthetic", "--strategy", "sma_cross",38 "--start", "2018-01-01", "--end", "2023-01-01",39 "--permutations", "10", "--folds", "2", "--quiet",40 ])41 out = capsys.readouterr().out42 assert code == 043 assert "REALITY SCORE" in out44 assert "Deflated Sharpe" in out45 46 def test_lab_json_output_is_machine_readable(self, capsys):47 code = main([48 "lab", "--source", "synthetic", "--start", "2018-01-01", "--end", "2023-01-01",49 "--permutations", "10", "--folds", "2", "--quiet", "--json",50 ])51 payload = json.loads(capsys.readouterr().out)52 assert code == 053 assert 0.0 <= payload["verdict"]["score"] <= 100.054 assert payload["verdict"]["grade"] in {"A", "B", "C", "D", "F"}55 assert payload["source"] == "synthetic"56 57 def test_lab_honours_param_overrides(self, capsys):58 main([59 "lab", "--source", "synthetic", "--start", "2018-01-01", "--end", "2023-01-01",60 "--strategy", "sma_cross", "--param", "fast=5", "--param", "slow=60",61 "--permutations", "0", "--folds", "2", "--quiet", "--json",62 ])63 payload = json.loads(capsys.readouterr().out)64 assert payload["params"] == {"fast": 5, "slow": 60}65 assert payload["p_value"] is None # permutations disabled66 67 def test_arena_ranks_the_zoo(self, capsys):68 code = main([69 "arena", "--source", "synthetic", "--start", "2018-01-01", "--end", "2023-01-01",70 "--permutations", "0", "--quiet",71 ])72 out = capsys.readouterr().out73 assert code == 074 assert "Buy & Hold" in out and "Coin Flip" in out75 assert "Ranked by evidence" in out76 77 def test_strategies_lists_the_registry(self, capsys):78 assert main(["strategies"]) == 079 out = capsys.readouterr().out80 assert "sma_cross" in out and "donchian_breakout" in out81 82 def test_errors_are_reported_not_raised(self, capsys):83 code = main([84 "lab", "--source", "synthetic",85 "--start", "2022-01-01", "--end", "2022-02-01", # far too short86 "--permutations", "0", "--quiet",87 ])88 assert code == 189 assert "error:" in capsys.readouterr().err90 