@@ -473,3 +473,174 @@ def test_asset_class_relationship_module_with_mock_lm(self):
473473
474474 assert result .relationship_analysis == "Strong correlation between tech and GDP"
475475 assert module .analyze_relationships .called
476+
477+
478+ class TestExtractFunctionsWithEmptyContent :
479+ """Test cases for extract functions handling None/empty content."""
480+
481+ def test_extract_economy_state_summary_with_none (self ):
482+ """Test extract_economy_state_summary handles None content."""
483+ from macro_agents .defs .agents .economy_state_analyzer import (
484+ extract_economy_state_summary ,
485+ )
486+
487+ result = extract_economy_state_summary (None )
488+ assert isinstance (result , dict )
489+ assert len (result ) == 0
490+
491+ def test_extract_economy_state_summary_with_empty_string (self ):
492+ """Test extract_economy_state_summary handles empty string."""
493+ from macro_agents .defs .agents .economy_state_analyzer import (
494+ extract_economy_state_summary ,
495+ )
496+
497+ result = extract_economy_state_summary ("" )
498+ assert isinstance (result , dict )
499+ assert len (result ) == 0
500+
501+ def test_extract_economy_state_summary_with_valid_content (self ):
502+ """Test extract_economy_state_summary with valid content."""
503+ from macro_agents .defs .agents .economy_state_analyzer import (
504+ extract_economy_state_summary ,
505+ )
506+
507+ content = """
508+ Current Economic Cycle Position: Expansion
509+ Confidence: 0.75
510+ Risk Factors: Inflation concerns, geopolitical tensions
511+ """
512+ result = extract_economy_state_summary (content )
513+ assert isinstance (result , dict )
514+ assert "economic_cycle_position" in result
515+ assert result ["economic_cycle_position" ] == "Expansion"
516+ assert "confidence_level" in result
517+ assert result ["confidence_level" ] == 0.75
518+
519+ def test_extract_relationship_summary_with_none (self ):
520+ """Test extract_relationship_summary handles None content."""
521+ from macro_agents .defs .agents .asset_class_relationship_analyzer import (
522+ extract_relationship_summary ,
523+ )
524+
525+ result = extract_relationship_summary (None )
526+ assert isinstance (result , dict )
527+ assert len (result ) == 0
528+
529+ def test_extract_relationship_summary_with_empty_string (self ):
530+ """Test extract_relationship_summary handles empty string."""
531+ from macro_agents .defs .agents .asset_class_relationship_analyzer import (
532+ extract_relationship_summary ,
533+ )
534+
535+ result = extract_relationship_summary ("" )
536+ assert isinstance (result , dict )
537+ assert len (result ) == 0
538+
539+ def test_extract_recommendations_summary_with_none (self ):
540+ """Test extract_recommendations_summary handles None content."""
541+ from macro_agents .defs .agents .investment_recommendations import (
542+ extract_recommendations_summary ,
543+ )
544+
545+ result = extract_recommendations_summary (None )
546+ assert isinstance (result , dict )
547+ assert "total_overweight_count" in result
548+ assert "total_underweight_count" in result
549+ assert result ["total_overweight_count" ] == 0
550+ assert result ["total_underweight_count" ] == 0
551+
552+ def test_extract_recommendations_summary_with_empty_string (self ):
553+ """Test extract_recommendations_summary handles empty string."""
554+ from macro_agents .defs .agents .investment_recommendations import (
555+ extract_recommendations_summary ,
556+ )
557+
558+ result = extract_recommendations_summary ("" )
559+ assert isinstance (result , dict )
560+ assert "total_overweight_count" in result
561+ assert "total_underweight_count" in result
562+ assert result ["total_overweight_count" ] == 0
563+ assert result ["total_underweight_count" ] == 0
564+
565+
566+ class TestExtractRecommendationsFloatParsing :
567+ """Test cases for extract_recommendations handling trailing punctuation in floats."""
568+
569+ def test_extract_recommendations_with_trailing_period (self ):
570+ """Test extract_recommendations handles confidence with trailing period."""
571+ from macro_agents .defs .agents .backtest_utils import extract_recommendations
572+
573+ content = "OVERWEIGHT XLK with confidence 0.6. Expected return 5.2%."
574+ recommendations = extract_recommendations (content )
575+
576+ assert len (recommendations ) > 0
577+ xlk_rec = next ((r for r in recommendations if r ["symbol" ] == "XLK" ), None )
578+ assert xlk_rec is not None
579+ assert xlk_rec ["direction" ] == "OVERWEIGHT"
580+ assert xlk_rec ["confidence" ] == 0.6
581+ assert xlk_rec ["expected_return" ] == 5.2
582+
583+ def test_extract_recommendations_with_trailing_comma (self ):
584+ """Test extract_recommendations handles confidence with trailing comma."""
585+ from macro_agents .defs .agents .backtest_utils import extract_recommendations
586+
587+ content = "OVERWEIGHT SPY with confidence 0.75, expected return 8.3%"
588+ recommendations = extract_recommendations (content )
589+
590+ assert len (recommendations ) > 0
591+ spy_rec = next ((r for r in recommendations if r ["symbol" ] == "SPY" ), None )
592+ assert spy_rec is not None
593+ assert spy_rec ["confidence" ] == 0.75
594+ assert spy_rec ["expected_return" ] == 8.3
595+
596+ def test_extract_recommendations_with_trailing_semicolon (self ):
597+ """Test extract_recommendations handles confidence with trailing semicolon."""
598+ from macro_agents .defs .agents .backtest_utils import extract_recommendations
599+
600+ content = "UNDERWEIGHT XLE with confidence 0.4; expected return -2.1%"
601+ recommendations = extract_recommendations (content )
602+
603+ assert len (recommendations ) > 0
604+ xle_rec = next ((r for r in recommendations if r ["symbol" ] == "XLE" ), None )
605+ assert xle_rec is not None
606+ assert xle_rec ["direction" ] == "UNDERWEIGHT"
607+ assert xle_rec ["confidence" ] == 0.4
608+ assert xle_rec ["expected_return" ] == - 2.1
609+
610+ def test_extract_recommendations_with_percent_sign (self ):
611+ """Test extract_recommendations handles return values with percent sign."""
612+ from macro_agents .defs .agents .backtest_utils import extract_recommendations
613+
614+ content = "OVERWEIGHT QQQ confidence 0.8 expected return 12.5%"
615+ recommendations = extract_recommendations (content )
616+
617+ assert len (recommendations ) > 0
618+ qqq_rec = next ((r for r in recommendations if r ["symbol" ] == "QQQ" ), None )
619+ assert qqq_rec is not None
620+ assert qqq_rec ["expected_return" ] == 12.5
621+
622+ def test_extract_recommendations_with_invalid_float_gracefully (self ):
623+ """Test extract_recommendations handles invalid float strings gracefully."""
624+ from macro_agents .defs .agents .backtest_utils import extract_recommendations
625+
626+ content = "OVERWEIGHT XLK with confidence invalid. Expected return also.invalid"
627+ recommendations = extract_recommendations (content )
628+
629+ assert len (recommendations ) > 0
630+ xlk_rec = next ((r for r in recommendations if r ["symbol" ] == "XLK" ), None )
631+ assert xlk_rec is not None
632+ assert xlk_rec ["confidence" ] is None
633+ assert xlk_rec ["expected_return" ] is None
634+
635+ def test_extract_recommendations_with_multiple_trailing_punctuation (self ):
636+ """Test extract_recommendations handles multiple trailing punctuation."""
637+ from macro_agents .defs .agents .backtest_utils import extract_recommendations
638+
639+ content = "OVERWEIGHT DIA confidence 0.9., expected return 6.7%."
640+ recommendations = extract_recommendations (content )
641+
642+ assert len (recommendations ) > 0
643+ dia_rec = next ((r for r in recommendations if r ["symbol" ] == "DIA" ), None )
644+ assert dia_rec is not None
645+ assert dia_rec ["confidence" ] == 0.9
646+ assert dia_rec ["expected_return" ] == 6.7
0 commit comments