From d883731212a26455b5f44f5769d3ae117e150430 Mon Sep 17 00:00:00 2001 From: ahmet guzererler Date: Wed, 25 Mar 2026 15:50:49 +0100 Subject: [PATCH] feat: add launch configuration for FastAPI and Vite; enhance Finviz filter validation tests (#110) --- .claude/launch.json | 18 ++++++ tests/integration/test_finviz_live.py | 63 +++++++++++++++++++++ tradingagents/agents/utils/scanner_tools.py | 4 +- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 .claude/launch.json diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 00000000..ee66737b --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,18 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "Backend (FastAPI / uvicorn)", + "runtimeExecutable": "/opt/miniconda3/envs/tradingagents/bin/python", + "runtimeArgs": ["-m", "agent_os.backend.main"], + "port": 8088 + }, + { + "name": "Frontend (Vite / React)", + "runtimeExecutable": "/opt/homebrew/bin/node", + "runtimeArgs": ["/Users/Ahmet/Repo/TradingAgents/agent_os/frontend/node_modules/.bin/vite", "/Users/Ahmet/Repo/TradingAgents/agent_os/frontend"], + "port": 5173, + "autoPort": true + } + ] +} diff --git a/tests/integration/test_finviz_live.py b/tests/integration/test_finviz_live.py index d1ff18b5..84601383 100644 --- a/tests/integration/test_finviz_live.py +++ b/tests/integration/test_finviz_live.py @@ -57,6 +57,22 @@ def _assert_valid_result(result: str, label: str) -> None: ) +_INVALID_FILTER_MARKER = "Invalid filter" + + +def _assert_no_invalid_filter_error(result: str, label: str) -> None: + """Assert result does not contain a Finviz 'Invalid filter' error. + + Distinguishes code bugs (wrong filter name/value hardcoded in the tool) + from acceptable transient failures (network errors, rate limits). + Catches both 'Invalid filter 'name'' and 'Invalid filter option 'value''. + """ + assert _INVALID_FILTER_MARKER not in result, ( + f"{label}: Finviz filter string is invalid — this is a code bug, " + f"not a transient network issue:\n{result}" + ) + + def _assert_ticker_rows(result: str, label: str) -> None: """When results were found, every data row must have the expected shape.""" if not result.startswith("Top 5 stocks for "): @@ -274,6 +290,53 @@ class TestGetBreakoutAccumulationStocks: # --------------------------------------------------------------------------- +@_skip_if_no_finviz +class TestNoInvalidFilterErrors: + """Assert that none of the three tools produce an 'Invalid filter' error. + + The existing tests accept 'Smart money scan unavailable' as a valid result + to tolerate network/rate-limit failures. This class tightens that: it + rejects results where Finviz rejected the *filter name itself* (a code bug + in the hardcoded filter dict), while still permitting genuine transient + failures. All calls hit the real finviz.com — no mocks. + """ + + def test_insider_buying_filter_is_valid(self): + from tradingagents.agents.utils.scanner_tools import get_insider_buying_stocks + + result = get_insider_buying_stocks.invoke({}) + _assert_no_invalid_filter_error(result, "insider_buying") + + def test_unusual_volume_filter_is_valid(self): + from tradingagents.agents.utils.scanner_tools import get_unusual_volume_stocks + + result = get_unusual_volume_stocks.invoke({}) + _assert_no_invalid_filter_error(result, "unusual_volume") + + def test_breakout_accumulation_filter_is_valid(self): + from tradingagents.agents.utils.scanner_tools import get_breakout_accumulation_stocks + + result = get_breakout_accumulation_stocks.invoke({}) + _assert_no_invalid_filter_error(result, "breakout_accumulation") + + def test_all_three_tools_no_invalid_filter(self): + """Single test exercising all three tools — useful for quick CI smoke run.""" + from tradingagents.agents.utils.scanner_tools import ( + get_breakout_accumulation_stocks, + get_insider_buying_stocks, + get_unusual_volume_stocks, + ) + + tools = [ + (get_insider_buying_stocks, "insider_buying"), + (get_unusual_volume_stocks, "unusual_volume"), + (get_breakout_accumulation_stocks, "breakout_accumulation"), + ] + for tool_fn, label in tools: + result = tool_fn.invoke({}) + _assert_no_invalid_filter_error(result, label) + + @_skip_if_no_finviz class TestAllThreeToolsSmoke: """Quick smoke test running all three tools sequentially.""" diff --git a/tradingagents/agents/utils/scanner_tools.py b/tradingagents/agents/utils/scanner_tools.py index b00738ae..a6950361 100644 --- a/tradingagents/agents/utils/scanner_tools.py +++ b/tradingagents/agents/utils/scanner_tools.py @@ -162,7 +162,7 @@ def get_insider_buying_stocks() -> str: """ return _run_finviz_screen( { - "InsiderPurchases": "Positive (>0%)", + "InsiderTransactions": "Positive (>0%)", "Market Cap.": "+Mid (over $2bln)", "Current Volume": "Over 1M", }, @@ -194,7 +194,7 @@ def get_breakout_accumulation_stocks() -> str: """ return _run_finviz_screen( { - "Performance 2": "52-Week High", + "52-Week High/Low": "New High", "Relative Volume": "Over 2", "Price": "Over $10", },