Skip to content

Discovery Schemas

Schemas for investment discovery, opportunity identification, and alternative suggestions.

APlusDiscoveryResult

Results from A+ investment opportunity discovery across asset classes.

Schema Definition

Python
class APlusDiscoveryResult(BaseModel):
    discovery_date: datetime = Field(default_factory=datetime.now)
    discovery_criteria: Dict[str, Any] = Field(default_factory=dict)

    # Discovery summary
    total_opportunities: int = Field(..., ge=0)
    asset_breakdown: Dict[str, int] = Field(default_factory=dict)

    # Opportunities by category
    stock_opportunities: List[InvestmentCandidate] = Field(default_factory=list)
    etf_opportunities: List[InvestmentCandidate] = Field(default_factory=list)
    crypto_opportunities: List[InvestmentCandidate] = Field(default_factory=list)

    # Categorized opportunities
    opportunity_sections: List[APlusOpportunitySection] = Field(default_factory=list)

    # Discovery quality metrics
    screening_universe_size: int = Field(..., ge=0)
    pass_rate: float = Field(..., ge=0.0, le=1.0)
    confidence_level: float = Field(..., ge=0.0, le=1.0)

    # Market context
    market_conditions: Dict[str, Any] = Field(default_factory=dict)
    discovery_notes: str = Field(default="")

    # Data sources and freshness
    data_sources: List[str] = Field(default_factory=list)
    data_freshness: datetime = Field(default_factory=datetime.now)

    model_config = {
        "extra": "forbid",
        "str_strip_whitespace": True
    }

Example

JSON
{
  "discovery_date": "2025-01-15T10:30:00Z",
  "discovery_criteria": {
    "min_market_cap": 1000000000,
    "min_volume": 1000000,
    "max_risk_score": 7,
    "asset_classes": ["stock", "etf", "crypto"]
  },
  "total_opportunities": 25,
  "asset_breakdown": {
    "stock": 15,
    "etf": 7,
    "crypto": 3
  },
  "stock_opportunities": [
    {
      "ticker": "MSFT",
      "name": "Microsoft Corporation",
      "asset_class": "stock",
      "grade": "A+",
      "confidence": 0.92,
      "key_strengths": ["Strong cloud growth", "Excellent margins"]
    }
  ],
  "opportunity_sections": [
    {
      "category": "Technology Leaders",
      "description": "Established technology companies with strong fundamentals",
      "opportunities": ["MSFT", "GOOGL", "NVDA"]
    }
  ],
  "screening_universe_size": 5000,
  "pass_rate": 0.005,
  "confidence_level": 0.88,
  "market_conditions": {
    "market_regime": "BULL",
    "volatility_level": "MODERATE",
    "sector_rotation": "TECHNOLOGY_FAVORED"
  }
}

InvestmentCandidate

Individual investment opportunity identified through discovery process.

Schema Definition

Python
class InvestmentCandidate(BaseModel):
    ticker: str = Field(..., description="Asset ticker symbol")
    name: str = Field(..., description="Asset name")
    asset_class: Literal["stock", "etf", "crypto"]

    # Grading and scoring
    grade: str = Field(..., pattern=r'^A\+$|^[A-F][+-]?$')
    composite_score: float = Field(..., ge=0.0, le=1.0)
    confidence: float = Field(..., ge=0.0, le=1.0)

    # Key metrics (asset-class specific)
    key_metrics: Dict[str, float] = Field(default_factory=dict)

    # Strengths and opportunities
    key_strengths: List[str] = Field(default_factory=list)
    growth_catalysts: List[str] = Field(default_factory=list)

    # Risk assessment
    risk_score: int = Field(..., ge=1, le=10)
    risk_factors: List[str] = Field(default_factory=list)

    # Market context
    current_price: Optional[float] = Field(None, gt=0)
    price_target: Optional[float] = Field(None, gt=0)
    upside_potential: Optional[float] = Field(None, ge=0.0)

    # Discovery context
    discovery_reason: str = Field(..., min_length=50)
    category: Optional[str] = Field(None, description="Opportunity category")

    # Data quality
    data_completeness: float = Field(..., ge=0.0, le=1.0)
    analysis_depth: Literal["BASIC", "STANDARD", "COMPREHENSIVE"] = Field(default="STANDARD")

    model_config = {
        "extra": "forbid",
        "str_strip_whitespace": True
    }

Example

JSON
{
  "ticker": "MSFT",
  "name": "Microsoft Corporation",
  "asset_class": "stock",
  "grade": "A+",
  "composite_score": 0.92,
  "confidence": 0.89,
  "key_metrics": {
    "pe_ratio": 28.5,
    "revenue_growth": 0.18,
    "profit_margin": 0.36,
    "roe": 0.42,
    "debt_to_equity": 0.35
  },
  "key_strengths": [
    "Dominant cloud platform position",
    "Strong recurring revenue model",
    "Excellent capital allocation",
    "Diversified product portfolio"
  ],
  "growth_catalysts": [
    "AI integration across products",
    "Cloud market expansion",
    "Enterprise digital transformation"
  ],
  "risk_score": 4,
  "risk_factors": [
    "High valuation multiples",
    "Regulatory scrutiny",
    "Cloud competition"
  ],
  "current_price": 420.00,
  "price_target": 480.00,
  "upside_potential": 0.14,
  "discovery_reason": "Microsoft demonstrates exceptional fundamentals with strong cloud growth, excellent margins, and dominant market position in enterprise software",
  "category": "Technology Leaders",
  "data_completeness": 0.95,
  "analysis_depth": "COMPREHENSIVE"
}

APlusOpportunitySection

Categorized grouping of A+ investment opportunities.

Schema Definition

Python
class APlusOpportunitySection(BaseModel):
    category: str = Field(..., min_length=5, description="Opportunity category name")
    description: str = Field(..., min_length=20, description="Category description")

    # Opportunities in this category
    opportunities: List[str] = Field(..., min_items=1, description="Ticker symbols")
    opportunity_count: int = Field(..., ge=1)

    # Category characteristics
    avg_grade: str = Field(..., pattern=r'^A\+$|^[A-F][+-]?$')
    avg_confidence: float = Field(..., ge=0.0, le=1.0)
    avg_risk_score: float = Field(..., ge=1.0, le=10.0)

    # Category themes
    common_strengths: List[str] = Field(default_factory=list)
    shared_catalysts: List[str] = Field(default_factory=list)
    category_risks: List[str] = Field(default_factory=list)

    # Investment thesis
    category_thesis: str = Field(..., min_length=100)

    model_config = {
        "extra": "forbid",
        "str_strip_whitespace": True
    }

Example

JSON
{
  "category": "Technology Leaders",
  "description": "Established technology companies with dominant market positions and strong growth prospects",
  "opportunities": ["MSFT", "GOOGL", "NVDA", "AAPL"],
  "opportunity_count": 4,
  "avg_grade": "A+",
  "avg_confidence": 0.87,
  "avg_risk_score": 4.5,
  "common_strengths": [
    "Strong competitive moats",
    "Excellent profit margins",
    "Robust cash generation",
    "Innovation leadership"
  ],
  "shared_catalysts": [
    "AI technology adoption",
    "Digital transformation trends",
    "Cloud computing growth"
  ],
  "category_risks": [
    "Regulatory scrutiny",
    "High valuations",
    "Technology disruption"
  ],
  "category_thesis": "Technology leaders represent the highest quality investment opportunities with sustainable competitive advantages, strong financial metrics, and exposure to long-term growth trends in artificial intelligence and digital transformation."
}

APlusImprovementSuggestion

Specific suggestions for improving portfolio through A+ opportunities.

Schema Definition

Python
class APlusImprovementSuggestion(BaseModel):
    suggestion_type: Literal["REPLACE", "ADD", "INCREASE", "DIVERSIFY"]
    priority: Literal["HIGH", "MEDIUM", "LOW"]

    # Current situation
    current_holding: Optional[str] = Field(None, description="Current ticker to replace/modify")
    current_allocation: Optional[float] = Field(None, ge=0.0, le=1.0)

    # Suggested action
    suggested_ticker: str = Field(..., description="A+ opportunity ticker")
    suggested_allocation: float = Field(..., ge=0.0, le=1.0)

    # Expected benefits
    expected_return_improvement: Optional[float] = Field(None)
    expected_risk_improvement: Optional[float] = Field(None)
    diversification_benefit: Optional[float] = Field(None, ge=0.0, le=1.0)

    # Rationale
    improvement_rationale: str = Field(..., min_length=100)
    key_advantages: List[str] = Field(default_factory=list)

    # Implementation
    implementation_timeline: Literal["IMMEDIATE", "SHORT", "MEDIUM", "LONG"]
    implementation_notes: str = Field(default="")

    # Confidence
    confidence: float = Field(..., ge=0.0, le=1.0)

    model_config = {
        "extra": "forbid",
        "str_strip_whitespace": True
    }

Validation Rules

Discovery-Specific Validation

Python
@field_validator('grade')
@classmethod
def validate_aplus_grade(cls, v: str) -> str:
    valid_grades = ['A+', 'A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D+', 'D', 'D-', 'F']
    if v not in valid_grades:
        raise ValueError(f'Invalid grade: {v}')
    return v

@field_validator('opportunities')
@classmethod
def validate_opportunity_tickers(cls, v: List[str]) -> List[str]:
    for ticker in v:
        if not ticker.replace('-', '').replace('.', '').isalnum():
            raise ValueError(f'Invalid ticker format: {ticker}')
    return [ticker.upper() for ticker in v]

@field_validator('pass_rate')
@classmethod
def validate_pass_rate(cls, v: float) -> float:
    if not 0.0 <= v <= 1.0:
        raise ValueError('Pass rate must be between 0.0 and 1.0')
    return v

Consistency Validation

Python
@model_validator(mode='after')
def validate_opportunity_consistency(self) -> 'APlusDiscoveryResult':
    # Validate total opportunities matches breakdown
    calculated_total = sum(self.asset_breakdown.values())
    if calculated_total != self.total_opportunities:
        raise ValueError('Asset breakdown does not sum to total opportunities')

    # Validate opportunity lists match breakdown
    actual_stocks = len(self.stock_opportunities)
    expected_stocks = self.asset_breakdown.get('stock', 0)
    if actual_stocks != expected_stocks:
        raise ValueError(f'Stock opportunities count mismatch: {actual_stocks} vs {expected_stocks}')

    return self

Usage Examples

Creating Discovery Results

Python
from finwiz.schemas.discovery import APlusDiscoveryResult, InvestmentCandidate, APlusOpportunitySection

# Create investment candidates
candidates = [
    InvestmentCandidate(
        ticker="MSFT",
        name="Microsoft Corporation",
        asset_class="stock",
        grade="A+",
        composite_score=0.92,
        confidence=0.89,
        key_strengths=["Strong cloud growth", "Excellent margins"],
        risk_score=4,
        discovery_reason="Exceptional fundamentals and market position",
        data_completeness=0.95
    )
]

# Create opportunity sections
sections = [
    APlusOpportunitySection(
        category="Technology Leaders",
        description="Dominant tech companies with strong growth",
        opportunities=["MSFT", "GOOGL"],
        opportunity_count=2,
        avg_grade="A+",
        avg_confidence=0.87,
        avg_risk_score=4.5,
        category_thesis="Technology leaders offer the best risk-adjusted returns"
    )
]

# Create discovery results
discovery = APlusDiscoveryResult(
    total_opportunities=25,
    asset_breakdown={"stock": 15, "etf": 7, "crypto": 3},
    stock_opportunities=candidates,
    opportunity_sections=sections,
    screening_universe_size=5000,
    pass_rate=0.005,
    confidence_level=0.88
)

Filtering Opportunities

Python
# Filter by grade
aplus_only = [
    candidate for candidate in discovery.stock_opportunities
    if candidate.grade == "A+"
]

# Filter by risk score
low_risk = [
    candidate for candidate in discovery.stock_opportunities
    if candidate.risk_score <= 5
]

# Filter by confidence
high_confidence = [
    candidate for candidate in discovery.stock_opportunities
    if candidate.confidence >= 0.8
]

Creating Improvement Suggestions

Python
from finwiz.schemas.discovery import APlusImprovementSuggestion

suggestion = APlusImprovementSuggestion(
    suggestion_type="REPLACE",
    priority="HIGH",
    current_holding="IBM",
    current_allocation=0.10,
    suggested_ticker="MSFT",
    suggested_allocation=0.10,
    expected_return_improvement=0.05,
    expected_risk_improvement=0.02,
    improvement_rationale="Microsoft offers superior growth prospects and financial metrics compared to IBM",
    key_advantages=["Better cloud position", "Higher margins", "Stronger growth"],
    implementation_timeline="SHORT",
    confidence=0.85
)

Integration with Analysis

Discovery schemas integrate with analysis schemas:

Python
# Convert discovery candidate to full analysis
def convert_to_analysis(candidate: InvestmentCandidate) -> TenKInsight:
    if candidate.asset_class == "stock":
        return TenKInsight(
            ticker=candidate.ticker,
            company_name=candidate.name,
            recommendation="BUY" if candidate.grade in ["A+", "A"] else "HOLD",
            confidence_level=candidate.confidence,
            # ... other fields from detailed analysis
        )