Files
tradingagents/tests/test_cli_symbol_handling.py
Yijia-Xiao 9683194793 fix(cli): finish the run surface
- backtest takes --run-id, so an interrupted sweep continues
- an inverted date range or an empty ticker list is an error, not a clean zero-cell run
- a setup failure in a sweep reports one line instead of a traceback
- the remembered endpoint URL is offered back
- a round count set in the environment says it overrode the chosen research depth
- the run directory validates the ticker, and the report saves under results_dir
- the run says whether it resumed a saved run or started fresh
2026-09-17 23:44:14 +00:00

76 lines
2.6 KiB
Python

"""CLI symbol validation/classification must agree with the data path.
Regressions for #980 (validation rejected GC=F), #981 (BTCUSD misclassified as
stock), #982 (BTC-USDT accepted but unpriceable on Yahoo).
"""
import pytest
from cli.models import AssetType
from cli.utils import detect_asset_type, is_valid_ticker_input, normalize_ticker_symbol
from tradingagents.dataflows.symbol_utils import normalize_symbol
# --- #982: stablecoin-quoted crypto normalizes to Yahoo's -USD pair ---
@pytest.mark.parametrize("raw,expected", [
("BTCUSD", "BTC-USD"),
("BTCUSDT", "BTC-USD"),
("BTC-USDT", "BTC-USD"),
("BTC-USDC", "BTC-USD"),
("ethusdt", "ETH-USD"),
# non-crypto must be untouched
("AAPL", "AAPL"),
("GC=F", "GC=F"),
("600519.SS", "600519.SS"),
("EURUSD", "EURUSD=X"),
])
def test_normalize_symbol_crypto_and_passthrough(raw, expected):
assert normalize_symbol(raw) == expected
# --- #980: validation accepts Yahoo futures/forex symbols ---
@pytest.mark.parametrize("value,ok", [
("GC=F", True),
("EURUSD=X", True),
("AAPL", True),
("0700.HK", True),
("^GSPC", True),
("", True), # empty -> defaults to SPY downstream
("bad symbol!", False), # space + '!' rejected
("A" * 40, False), # too long
])
def test_ticker_input_validation(value, ok):
assert is_valid_ticker_input(value) is ok
# --- #981/#982: asset-type classified on the canonical symbol ---
@pytest.mark.parametrize("raw,expected", [
("BTCUSD", AssetType.CRYPTO),
("BTC-USDT", AssetType.CRYPTO),
("BTC-USD", AssetType.CRYPTO),
("ETHUSD", AssetType.CRYPTO),
("AAPL", AssetType.STOCK),
("GC=F", AssetType.STOCK),
("600519.SS", AssetType.STOCK),
])
def test_detect_asset_type(raw, expected):
assert detect_asset_type(raw) == expected
def test_cli_normalize_delegates_to_data_layer():
# CLI must produce the same canonical symbol the data path will price.
for raw in ("XAUUSD", "BTCUSD", "btc-usdt", "AAPL"):
assert normalize_ticker_symbol(raw) == normalize_symbol(raw)
@pytest.mark.unit
def test_the_run_directory_cannot_escape_the_results_directory(tmp_path, monkeypatch):
"""Every other path that interpolates a ticker validates it first; the CLI's
own results tree did not, so a ticker of '..' wrote a level up."""
import cli.main as m
with pytest.raises(ValueError):
m._run_directory({"results_dir": str(tmp_path)}, "..", "2026-09-01")
ok = m._run_directory({"results_dir": str(tmp_path)}, "NVDA", "2026-09-01")
assert str(ok).startswith(str(tmp_path))