Dividend Stock Analysis with Ollama: Yield and Sustainability Evaluation Guide

Learn dividend stock analysis with Ollama AI. Calculate yields, evaluate sustainability metrics, and automate screening for better investment decisions.

Picture this: You're scrolling through hundreds of dividend-paying stocks, manually calculating yields, and cross-referencing payout ratios. Your coffee goes cold. Your eyes glaze over. Your portfolio remains disappointingly average.

There's a better way. Ollama transforms dividend stock analysis from tedious spreadsheet gymnastics into automated insights that actually matter.

What Is Dividend Stock Analysis with Ollama?

Dividend stock analysis evaluates companies that pay regular cash distributions to shareholders. Traditional analysis requires manual data collection, yield calculations, and sustainability assessments across multiple metrics.

Ollama automates this process. The AI model processes financial data, calculates key metrics, and evaluates dividend sustainability patterns. This approach saves hours of manual work while improving analysis accuracy.

Key benefits:

  • Automated yield calculations and trend analysis
  • Multi-factor sustainability scoring
  • Batch processing for portfolio screening
  • Consistent evaluation criteria across all stocks

Essential Dividend Metrics for AI Analysis

Dividend Yield Calculation

Dividend yield measures annual dividend payments relative to stock price. Higher yields aren't always better - they might signal financial distress or unsustainable payouts.

# Basic dividend yield calculation
def calculate_dividend_yield(annual_dividend, stock_price):
    """
    Calculate dividend yield percentage
    
    Args:
        annual_dividend (float): Total annual dividend per share
        stock_price (float): Current stock price
    
    Returns:
        float: Dividend yield as percentage
    """
    yield_percent = (annual_dividend / stock_price) * 100
    return round(yield_percent, 2)

# Example calculation
annual_dividend = 2.40  # $2.40 per share annually
current_price = 45.50   # $45.50 current stock price
yield_result = calculate_dividend_yield(annual_dividend, current_price)
print(f"Dividend Yield: {yield_result}%")  # Output: Dividend Yield: 5.27%

Payout Ratio Assessment

Payout ratio shows what percentage of earnings funds dividend payments. Ratios above 80% often indicate unsustainable dividends.

def calculate_payout_ratio(dividends_per_share, earnings_per_share):
    """
    Calculate dividend payout ratio
    
    Args:
        dividends_per_share (float): Annual dividends paid per share
        earnings_per_share (float): Annual earnings per share
    
    Returns:
        float: Payout ratio as percentage
    """
    if earnings_per_share <= 0:
        return float('inf')  # Indicates potential red flag
    
    payout_ratio = (dividends_per_share / earnings_per_share) * 100
    return round(payout_ratio, 2)

# Example calculation
eps = 4.20  # $4.20 earnings per share
dps = 2.40  # $2.40 dividends per share
payout = calculate_payout_ratio(dps, eps)
print(f"Payout Ratio: {payout}%")  # Output: Payout Ratio: 57.14%

Setting Up Ollama for Dividend Analysis

Installation and Model Selection

First, install Ollama and download a suitable model for financial analysis. The Llama 3.1 model provides excellent performance for numerical calculations and financial reasoning.

# Install Ollama (macOS/Linux)
curl -fsSL https://ollama.ai/install.sh | sh

# Pull the recommended model
ollama pull llama3.1:8b

# Verify installation
ollama list

Creating the Analysis Prompt

Design a structured prompt that guides Ollama through dividend analysis steps. Clear instructions produce more consistent results.

dividend_analysis_prompt = """
You are a dividend stock analyst. Analyze the following stock data and provide:

1. Dividend yield calculation and interpretation
2. Payout ratio assessment with sustainability rating
3. Dividend growth trend over 5 years
4. Risk factors that could impact future payments
5. Overall dividend quality score (1-10 scale)

Stock Data:
- Company: {company_name}
- Current Price: ${current_price}
- Annual Dividend: ${annual_dividend}
- Earnings Per Share: ${eps}
- 5-Year Dividend History: {dividend_history}
- Debt-to-Equity Ratio: {debt_equity}
- Free Cash Flow: ${free_cash_flow}

Provide specific numbers and clear reasoning for each assessment.
"""

Implementing Automated Dividend Screening

Basic Screening Script

Create a Python script that processes multiple stocks through Ollama's dividend analysis framework.

import requests
import json
from typing import Dict, List

class DividendAnalyzer:
    def __init__(self, ollama_url="http://localhost:11434"):
        self.ollama_url = ollama_url
        self.model = "llama3.1:8b"
    
    def analyze_stock(self, stock_data: Dict) -> Dict:
        """
        Analyze a single stock's dividend metrics
        
        Args:
            stock_data (dict): Stock financial data
            
        Returns:
            dict: Analysis results with scores and recommendations
        """
        prompt = self._build_analysis_prompt(stock_data)
        
        payload = {
            "model": self.model,
            "prompt": prompt,
            "stream": False,
            "options": {
                "temperature": 0.1,  # Low temperature for consistent analysis
                "num_predict": 500   # Limit response length
            }
        }
        
        response = requests.post(
            f"{self.ollama_url}/api/generate",
            json=payload
        )
        
        if response.status_code == 200:
            result = response.json()
            return self._parse_analysis(result['response'])
        else:
            raise Exception(f"Ollama API error: {response.status_code}")
    
    def _build_analysis_prompt(self, data: Dict) -> str:
        """Build structured analysis prompt from stock data"""
        return dividend_analysis_prompt.format(**data)
    
    def _parse_analysis(self, analysis_text: str) -> Dict:
        """Extract structured data from analysis response"""
        # Implementation depends on your specific parsing needs
        # This is a simplified example
        lines = analysis_text.split('\n')
        parsed_result = {
            'raw_analysis': analysis_text,
            'dividend_yield': self._extract_yield(lines),
            'sustainability_score': self._extract_score(lines),
            'recommendation': self._extract_recommendation(lines)
        }
        return parsed_result

# Example usage
analyzer = DividendAnalyzer()

stock_portfolio = [
    {
        'company_name': 'Coca-Cola Co',
        'current_price': 61.50,
        'annual_dividend': 1.84,
        'eps': 2.85,
        'dividend_history': [1.68, 1.72, 1.76, 1.80, 1.84],
        'debt_equity': 1.45,
        'free_cash_flow': 8900000000
    },
    # Add more stocks here
]

# Analyze each stock
results = []
for stock in stock_portfolio:
    analysis = analyzer.analyze_stock(stock)
    results.append({
        'company': stock['company_name'],
        'analysis': analysis
    })
    print(f"Analyzed: {stock['company_name']}")

# Display results
for result in results:
    print(f"\n{result['company']}:")
    print(f"Sustainability Score: {result['analysis']['sustainability_score']}")
    print(f"Recommendation: {result['analysis']['recommendation']}")

Advanced Screening with Multiple Criteria

Enhance the basic screener with additional filters and ranking capabilities.

class AdvancedDividendScreener(DividendAnalyzer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.screening_criteria = {
            'min_yield': 2.0,
            'max_payout_ratio': 75.0,
            'min_dividend_growth': 3.0,
            'max_debt_equity': 2.0,
            'min_market_cap': 1000000000  # $1B minimum
        }
    
    def screen_portfolio(self, stocks: List[Dict]) -> List[Dict]:
        """
        Screen and rank stocks based on dividend quality
        
        Args:
            stocks (list): List of stock data dictionaries
            
        Returns:
            list: Ranked stocks with scores and analysis
        """
        screened_stocks = []
        
        for stock in stocks:
            # Pre-screen with basic criteria
            if self._passes_basic_screening(stock):
                analysis = self.analyze_stock(stock)
                
                # Calculate composite score
                composite_score = self._calculate_composite_score(stock, analysis)
                
                screened_stocks.append({
                    'stock_data': stock,
                    'analysis': analysis,
                    'composite_score': composite_score,
                    'meets_criteria': True
                })
            else:
                screened_stocks.append({
                    'stock_data': stock,
                    'analysis': None,
                    'composite_score': 0,
                    'meets_criteria': False
                })
        
        # Sort by composite score (highest first)
        screened_stocks.sort(key=lambda x: x['composite_score'], reverse=True)
        return screened_stocks
    
    def _passes_basic_screening(self, stock: Dict) -> bool:
        """Apply basic numerical filters before AI analysis"""
        yield_percent = (stock['annual_dividend'] / stock['current_price']) * 100
        payout_ratio = (stock['annual_dividend'] / stock['eps']) * 100 if stock['eps'] > 0 else 100
        
        return (
            yield_percent >= self.screening_criteria['min_yield'] and
            payout_ratio <= self.screening_criteria['max_payout_ratio'] and
            stock['debt_equity'] <= self.screening_criteria['max_debt_equity']
        )
    
    def _calculate_composite_score(self, stock: Dict, analysis: Dict) -> float:
        """Calculate weighted composite score for ranking"""
        # This would implement your specific scoring algorithm
        # combining quantitative metrics with AI analysis
        base_score = analysis.get('sustainability_score', 0)
        yield_score = min((stock['annual_dividend'] / stock['current_price']) * 20, 10)
        
        # Weighted average of different factors
        composite = (base_score * 0.6) + (yield_score * 0.4)
        return round(composite, 2)

# Example usage with advanced screening
screener = AdvancedDividendScreener()
ranked_results = screener.screen_portfolio(stock_portfolio)

# Display top 5 dividend stocks
print("Top 5 Dividend Stocks:")
for i, result in enumerate(ranked_results[:5], 1):
    if result['meets_criteria']:
        stock = result['stock_data']
        print(f"{i}. {stock['company_name']}")
        print(f"   Composite Score: {result['composite_score']}")
        print(f"   Current Yield: {(stock['annual_dividend']/stock['current_price'])*100:.2f}%")
        print()

Dividend Sustainability Evaluation Methods

Cash Flow Coverage Analysis

Sustainable dividends require sufficient cash flow coverage. Companies that pay dividends exceeding free cash flow often cut payments during economic downturns.

def evaluate_cash_flow_coverage(free_cash_flow, total_dividends_paid, shares_outstanding):
    """
    Evaluate dividend coverage by free cash flow
    
    Args:
        free_cash_flow (float): Annual free cash flow
        total_dividends_paid (float): Total annual dividend payments
        shares_outstanding (int): Number of shares outstanding
    
    Returns:
        dict: Coverage analysis results
    """
    coverage_ratio = free_cash_flow / total_dividends_paid if total_dividends_paid > 0 else 0
    dividend_per_share = total_dividends_paid / shares_outstanding
    
    # Coverage interpretation
    if coverage_ratio >= 2.0:
        sustainability = "Strong"
        risk_level = "Low"
    elif coverage_ratio >= 1.5:
        sustainability = "Adequate"
        risk_level = "Medium"
    elif coverage_ratio >= 1.0:
        sustainability = "Marginal"
        risk_level = "High"
    else:
        sustainability = "At Risk"
        risk_level = "Very High"
    
    return {
        'coverage_ratio': round(coverage_ratio, 2),
        'sustainability': sustainability,
        'risk_level': risk_level,
        'dividend_per_share': round(dividend_per_share, 2)
    }

# Example evaluation
fcf = 2500000000  # $2.5B free cash flow
total_dividends = 1800000000  # $1.8B total dividend payments
shares = 4500000000  # 4.5B shares outstanding

coverage_analysis = evaluate_cash_flow_coverage(fcf, total_dividends, shares)
print(f"Coverage Ratio: {coverage_analysis['coverage_ratio']}")
print(f"Sustainability: {coverage_analysis['sustainability']}")
print(f"Risk Level: {coverage_analysis['risk_level']}")

Debt Impact Assessment

High debt levels threaten dividend sustainability. Companies prioritize debt service over dividend payments during financial stress.

def assess_debt_impact_on_dividends(debt_to_equity, interest_coverage, dividend_yield):
    """
    Assess how debt levels impact dividend sustainability
    
    Returns risk assessment and recommendations
    """
    risk_factors = []
    risk_score = 0
    
    # Debt-to-equity evaluation
    if debt_to_equity > 2.0:
        risk_factors.append("High debt-to-equity ratio")
        risk_score += 3
    elif debt_to_equity > 1.5:
        risk_factors.append("Elevated debt levels")
        risk_score += 2
    elif debt_to_equity > 1.0:
        risk_factors.append("Moderate debt burden")
        risk_score += 1
    
    # Interest coverage evaluation
    if interest_coverage < 2.5:
        risk_factors.append("Low interest coverage")
        risk_score += 3
    elif interest_coverage < 5.0:
        risk_factors.append("Adequate interest coverage")
        risk_score += 1
    
    # High yield with high debt is concerning
    if dividend_yield > 6.0 and debt_to_equity > 1.5:
        risk_factors.append("High yield may indicate distress")
        risk_score += 2
    
    # Overall assessment
    if risk_score >= 6:
        assessment = "High Risk"
        recommendation = "Avoid or reduce position"
    elif risk_score >= 4:
        assessment = "Medium Risk"
        recommendation = "Monitor closely"
    elif risk_score >= 2:
        assessment = "Low-Medium Risk"
        recommendation = "Acceptable with monitoring"
    else:
        assessment = "Low Risk"
        recommendation = "Favorable debt profile"
    
    return {
        'risk_score': risk_score,
        'risk_factors': risk_factors,
        'assessment': assessment,
        'recommendation': recommendation
    }

Performance Optimization for Large Portfolios

Batch Processing Implementation

Process multiple stocks efficiently by batching requests and implementing parallel processing where appropriate.

import concurrent.futures
import time
from typing import List, Dict

class BatchDividendAnalyzer(AdvancedDividendScreener):
    def __init__(self, max_workers=4, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.max_workers = max_workers
        self.rate_limit_delay = 1.0  # Seconds between requests
    
    def analyze_portfolio_batch(self, stocks: List[Dict]) -> List[Dict]:
        """
        Analyze multiple stocks with rate limiting and error handling
        
        Args:
            stocks (list): List of stock data dictionaries
            
        Returns:
            list: Analysis results for all stocks
        """
        results = []
        failed_analyses = []
        
        # Split into batches to avoid overwhelming Ollama
        batch_size = self.max_workers
        stock_batches = [stocks[i:i + batch_size] for i in range(0, len(stocks), batch_size)]
        
        for batch_num, batch in enumerate(stock_batches, 1):
            print(f"Processing batch {batch_num}/{len(stock_batches)}")
            
            with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:
                # Submit analysis tasks
                future_to_stock = {
                    executor.submit(self._safe_analyze_stock, stock): stock 
                    for stock in batch
                }
                
                # Collect results
                for future in concurrent.futures.as_completed(future_to_stock):
                    stock = future_to_stock[future]
                    try:
                        analysis_result = future.result()
                        results.append({
                            'company': stock['company_name'],
                            'analysis': analysis_result,
                            'status': 'success'
                        })
                    except Exception as e:
                        failed_analyses.append({
                            'company': stock['company_name'],
                            'error': str(e),
                            'status': 'failed'
                        })
                        print(f"Failed to analyze {stock['company_name']}: {e}")
            
            # Rate limiting between batches
            if batch_num < len(stock_batches):
                time.sleep(self.rate_limit_delay)
        
        return {
            'successful_analyses': results,
            'failed_analyses': failed_analyses,
            'success_rate': len(results) / (len(results) + len(failed_analyses))
        }
    
    def _safe_analyze_stock(self, stock: Dict) -> Dict:
        """Wrapper for stock analysis with error handling"""
        try:
            return self.analyze_stock(stock)
        except Exception as e:
            # Log error details for debugging
            print(f"Analysis error for {stock.get('company_name', 'Unknown')}: {e}")
            raise

# Example usage with large portfolio
large_portfolio = [
    # Add 50+ stocks here for batch testing
    # Each stock should have the same data structure as previous examples
]

batch_analyzer = BatchDividendAnalyzer(max_workers=3)
batch_results = batch_analyzer.analyze_portfolio_batch(large_portfolio)

print(f"Successfully analyzed: {len(batch_results['successful_analyses'])} stocks")
print(f"Failed analyses: {len(batch_results['failed_analyses'])} stocks")
print(f"Success rate: {batch_results['success_rate']*100:.1f}%")

Caching and Result Storage

Implement caching to avoid re-analyzing unchanged data and store results for historical comparison.

import json
import hashlib
from datetime import datetime, timedelta
from pathlib import Path

class CachedDividendAnalyzer(BatchDividendAnalyzer):
    def __init__(self, cache_dir="dividend_cache", cache_expiry_hours=24, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(exist_ok=True)
        self.cache_expiry = timedelta(hours=cache_expiry_hours)
    
    def analyze_stock(self, stock_data: Dict) -> Dict:
        """Analyze stock with caching support"""
        cache_key = self._generate_cache_key(stock_data)
        cache_file = self.cache_dir / f"{cache_key}.json"
        
        # Check for valid cached result
        if cache_file.exists():
            cached_result = self._load_cached_result(cache_file)
            if cached_result and self._is_cache_valid(cached_result):
                print(f"Using cached analysis for {stock_data['company_name']}")
                return cached_result['analysis']
        
        # Perform fresh analysis
        analysis = super().analyze_stock(stock_data)
        
        # Cache the result
        self._save_to_cache(cache_file, stock_data, analysis)
        
        return analysis
    
    def _generate_cache_key(self, stock_data: Dict) -> str:
        """Generate unique cache key for stock data"""
        # Create hash based on company name and key financial metrics
        key_data = {
            'company': stock_data['company_name'],
            'price': stock_data['current_price'],
            'dividend': stock_data['annual_dividend'],
            'eps': stock_data['eps']
        }
        key_string = json.dumps(key_data, sort_keys=True)
        return hashlib.md5(key_string.encode()).hexdigest()
    
    def _load_cached_result(self, cache_file: Path) -> Dict:
        """Load cached analysis result"""
        try:
            with open(cache_file, 'r') as f:
                return json.load(f)
        except (json.JSONDecodeError, FileNotFoundError):
            return None
    
    def _is_cache_valid(self, cached_result: Dict) -> bool:
        """Check if cached result is still valid"""
        cache_time = datetime.fromisoformat(cached_result['timestamp'])
        return datetime.now() - cache_time < self.cache_expiry
    
    def _save_to_cache(self, cache_file: Path, stock_data: Dict, analysis: Dict):
        """Save analysis result to cache"""
        cache_data = {
            'timestamp': datetime.now().isoformat(),
            'stock_data': stock_data,
            'analysis': analysis
        }
        
        with open(cache_file, 'w') as f:
            json.dump(cache_data, f, indent=2)

# Example usage with caching
cached_analyzer = CachedDividendAnalyzer(cache_expiry_hours=6)

# First run - will analyze fresh
start_time = time.time()
first_results = cached_analyzer.analyze_portfolio_batch(stock_portfolio[:5])
first_duration = time.time() - start_time

# Second run - will use cache
start_time = time.time()
second_results = cached_analyzer.analyze_portfolio_batch(stock_portfolio[:5])
second_duration = time.time() - start_time

print(f"First analysis: {first_duration:.2f} seconds")
print(f"Cached analysis: {second_duration:.2f} seconds")
print(f"Speed improvement: {(first_duration/second_duration):.1f}x faster")

Troubleshooting Common Issues

Ollama Connection Problems

Problem: Connection refused or timeout errors Solution: Verify Ollama service status and port configuration

# Check if Ollama is running
ps aux | grep ollama

# Restart Ollama service
ollama serve

# Test connection manually
curl http://localhost:11434/api/version

Inconsistent Analysis Results

Problem: Different results for identical stock data Solution: Lower temperature setting and use structured prompts

# Use consistent settings for reproducible results
payload = {
    "model": "llama3.1:8b",
    "prompt": structured_prompt,
    "stream": False,
    "options": {
        "temperature": 0.0,  # Completely deterministic
        "top_p": 1.0,        # Use full probability distribution
        "repeat_penalty": 1.0 # Avoid repetition artifacts
    }
}

Memory and Performance Issues

Problem: Slow analysis or out-of-memory errors Solution: Implement batching and resource monitoring

import psutil

def monitor_system_resources():
    """Monitor system resources during analysis"""
    memory_percent = psutil.virtual_memory().percent
    cpu_percent = psutil.cpu_percent(interval=1)
    
    if memory_percent > 90:
        print(f"Warning: High memory usage ({memory_percent}%)")
    if cpu_percent > 95:
        print(f"Warning: High CPU usage ({cpu_percent}%)")
    
    return {
        'memory_percent': memory_percent,
        'cpu_percent': cpu_percent,
        'available_memory_gb': psutil.virtual_memory().available / 1024**3
    }

# Monitor resources during batch analysis
resources = monitor_system_resources()
if resources['memory_percent'] < 80:
    # Safe to proceed with full batch
    batch_size = 10
else:
    # Reduce batch size to prevent memory issues
    batch_size = 5

Advanced Integration Strategies

Real-Time Data Integration

Connect your dividend analyzer to live market data feeds for up-to-date analysis.

import yfinance as yf
from datetime import datetime

class LiveDividendAnalyzer(CachedDividendAnalyzer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.last_market_update = None
    
    def fetch_live_stock_data(self, symbol: str) -> Dict:
        """Fetch current stock data from Yahoo Finance"""
        try:
            ticker = yf.Ticker(symbol)
            info = ticker.info
            history = ticker.history(period="1y")
            dividends = ticker.dividends
            
            # Calculate current metrics
            current_price = history['Close'].iloc[-1]
            annual_dividend = dividends.sum() if len(dividends) > 0 else 0
            
            stock_data = {
                'company_name': info.get('longName', symbol),
                'symbol': symbol,
                'current_price': float(current_price),
                'annual_dividend': float(annual_dividend),
                'eps': info.get('trailingEps', 0),
                'dividend_history': dividends.tail(5).tolist(),
                'debt_equity': info.get('debtToEquity', 0) / 100 if info.get('debtToEquity') else 0,
                'free_cash_flow': info.get('freeCashflow', 0),
                'market_cap': info.get('marketCap', 0),
                'last_updated': datetime.now().isoformat()
            }
            
            return stock_data
            
        except Exception as e:
            print(f"Error fetching data for {symbol}: {e}")
            return None
    
    def analyze_live_portfolio(self, symbols: List[str]) -> Dict:
        """Analyze portfolio using live market data"""
        live_stocks = []
        failed_fetches = []
        
        for symbol in symbols:
            stock_data = self.fetch_live_stock_data(symbol)
            if stock_data:
                live_stocks.append(stock_data)
            else:
                failed_fetches.append(symbol)
        
        if live_stocks:
            analysis_results = self.analyze_portfolio_batch(live_stocks)
            analysis_results['failed_data_fetches'] = failed_fetches
            return analysis_results
        else:
            return {'error': 'No valid stock data retrieved'}

# Example usage with live data
live_analyzer = LiveDividendAnalyzer()

# Analyze current dividend aristocrats
dividend_aristocrats = ['KO', 'PG', 'JNJ', 'MMM', 'WMT']
live_results = live_analyzer.analyze_live_portfolio(dividend_aristocrats)

print("Live Dividend Analysis Results:")
for result in live_results['successful_analyses']:
    print(f"{result['company']}: {result['analysis']['sustainability_score']}/10")

Results Interpretation and Action Steps

Creating Actionable Reports

Transform Ollama's analysis into clear investment recommendations with specific action items.

def generate_investment_report(analysis_results: List[Dict]) -> str:
    """
    Generate formatted investment report from analysis results
    
    Args:
        analysis_results: List of stock analysis results
        
    Returns:
        str: Formatted report with recommendations
    """
    
    # Sort stocks by composite score
    sorted_stocks = sorted(
        analysis_results['successful_analyses'],
        key=lambda x: x['analysis'].get('sustainability_score', 0),
        reverse=True
    )
    
    report = "# Dividend Portfolio Analysis Report\n\n"
    report += f"Analysis Date: {datetime.now().strftime('%Y-%m-%d %H:%M')}\n"
    report += f"Stocks Analyzed: {len(sorted_stocks)}\n\n"
    
    # Executive Summary
    report += "## Executive Summary\n\n"
    high_quality = [s for s in sorted_stocks if s['analysis'].get('sustainability_score', 0) >= 7]
    medium_quality = [s for s in sorted_stocks if 5 <= s['analysis'].get('sustainability_score', 0) < 7]
    low_quality = [s for s in sorted_stocks if s['analysis'].get('sustainability_score', 0) < 5]
    
    report += f"- **High Quality Dividends**: {len(high_quality)} stocks (Score 7-10)\n"
    report += f"- **Medium Quality Dividends**: {len(medium_quality)} stocks (Score 5-7)\n"
    report += f"- **Low Quality Dividends**: {len(low_quality)} stocks (Score <5)\n\n"
    
    # Top Recommendations
    report += "## Top Dividend Recommendations\n\n"
    for i, stock in enumerate(sorted_stocks[:5], 1):
        company = stock['company']
        score = stock['analysis'].get('sustainability_score', 'N/A')
        recommendation = stock['analysis'].get('recommendation', 'Hold')
        
        report += f"### {i}. {company}\n"
        report += f"- **Sustainability Score**: {score}/10\n"
        report += f"- **Recommendation**: {recommendation}\n"
        report += f"- **Key Insight**: {stock['analysis'].get('key_insight', 'No insight available')}\n\n"
    
    # Risk Alerts
    risk_stocks = [s for s in sorted_stocks if s['analysis'].get('sustainability_score', 10) < 4]
    if risk_stocks:
        report += "## Risk Alerts\n\n"
        for stock in risk_stocks:
            report += f"- **{stock['company']}**: High dividend risk (Score: {stock['analysis'].get('sustainability_score', 'N/A')})\n"
        report += "\n"
    
    # Action Items
    report += "## Recommended Actions\n\n"
    report += "### Immediate Actions:\n"
    if high_quality:
        report += f"- Consider increasing positions in: {', '.join([s['company'] for s in high_quality[:3]])}\n"
    if low_quality:
        report += f"- Review and potentially reduce: {', '.join([s['company'] for s in low_quality])}\n"
    
    report += "\n### Monitoring Actions:\n"
    report += "- Set up quarterly review alerts for all medium-quality positions\n"
    report += "- Monitor payout ratios for any stocks above 70%\n"
    report += "- Track debt levels for highly leveraged dividend payers\n\n"
    
    return report

# Generate report from analysis results
investment_report = generate_investment_report(batch_results)
print(investment_report)

# Save report to file
with open(f"dividend_analysis_report_{datetime.now().strftime('%Y%m%d')}.md", 'w') as f:
    f.write(investment_report)

Conclusion

Dividend stock analysis with Ollama transforms manual screening into automated intelligence. This approach combines AI-powered evaluation with systematic screening criteria to identify sustainable dividend opportunities.

Key advantages:

  • Automated screening processes hundreds of stocks consistently
  • Multi-factor analysis evaluates yield, sustainability, and risk simultaneously
  • Scalable implementation handles portfolios from 10 to 1000+ stocks
  • Actionable insights generate specific buy/hold/sell recommendations

Start with the basic screening script, then expand to live data integration and batch processing as your needs grow. The combination of Ollama's analytical capabilities with structured dividend evaluation creates a powerful tool for dividend-focused investors.

Remember to validate AI recommendations with fundamental analysis and consider your risk tolerance before making investment decisions. Dividend stock analysis with Ollama provides the foundation - your judgment provides the final investment wisdom.


Ready to implement dividend analysis with Ollama? Download the complete code examples and start screening your portfolio today.