fix(schema): coerce null-ish strings in optional float fields

A weak model can write a placeholder ('None', 'N/A') into an optional price
field, tripping schema validation. Coerce null-ish strings to None on the
trader/PM float fields; real numeric strings still parse.
This commit is contained in:
Yijia-Xiao
2026-06-21 22:31:35 +00:00
parent 709fe2b646
commit 0405168f20
2 changed files with 55 additions and 1 deletions

View File

@@ -15,6 +15,7 @@ from pydantic import ValidationError
from tradingagents.agents.analysts.sentiment_analyst import create_sentiment_analyst
from tradingagents.agents.managers.research_manager import create_research_manager
from tradingagents.agents.schemas import (
PortfolioDecision,
PortfolioRating,
ResearchPlan,
SentimentBand,
@@ -67,6 +68,36 @@ class TestRenderTraderProposal:
assert "FINAL TRANSACTION PROPOSAL: **SELL**" in md
@pytest.mark.unit
class TestNullishFloatCoercion:
"""A weak LLM may write "None"/"N/A" into an optional float field (#1058);
coerce those to None so the structured call validates instead of erroring."""
def test_trader_nullish_strings_coerce_to_none(self):
for sentinel in ("None", "N/A", "null", "-", "", "TBD"):
p = TraderProposal(
action=TraderAction.HOLD,
reasoning="x",
entry_price=sentinel,
stop_loss=sentinel,
)
assert p.entry_price is None
assert p.stop_loss is None
def test_trader_real_numeric_string_still_parses(self):
p = TraderProposal(action=TraderAction.BUY, reasoning="x", entry_price="189.5")
assert p.entry_price == 189.5
def test_pm_nullish_price_target_coerces_to_none(self):
d = PortfolioDecision(
rating=PortfolioRating.OVERWEIGHT,
executive_summary="s",
investment_thesis="t",
price_target="N/A",
)
assert d.price_target is None
@pytest.mark.unit
class TestRenderResearchPlan:
def test_required_fields(self):