Crypto Fear & Greed Index: Building Custom Sentiment Tracker with Ollama

Build a custom crypto fear and greed index with Ollama AI models. Track market sentiment, analyze social media, and create automated trading signals.

Remember when your friend bought Bitcoin at $65,000 because "everyone was doing it"? Or when they panic-sold at $15,000 because "crypto is dead"? That's the fear and greed cycle in action, and it's precisely what we can measure and exploit.

The crypto market runs on emotions more than fundamentals. While the official Fear & Greed Index gives us a snapshot, building your own sentiment tracker with Ollama lets you customize the inputs, weight different factors, and create actionable trading signals.

This guide shows you how to build a custom crypto fear and greed index using Ollama's AI models. You'll learn to analyze social media sentiment, track market indicators, and create automated alerts that help you buy when others are fearful and sell when others are greedy.

What Makes a Crypto Fear and Greed Index Effective

The traditional Fear & Greed Index combines seven market indicators: volatility, momentum, social media sentiment, surveys, Bitcoin dominance, trends, and volume. But here's the problem: it's a black box with fixed weightings that don't adapt to market conditions.

Your custom sentiment tracker will be different. You'll control the data sources, adjust the weightings based on market phases, and integrate real-time social media analysis that goes beyond simple keyword counting.

Key Components of Our Custom Index

Our Ollama-powered sentiment tracker analyzes five core components:

Social Media Sentiment Analysis: Process tweets, Reddit posts, and Telegram messages using Ollama's language models to extract emotional context, not just keyword frequency.

Market Technical Indicators: Track volatility, volume, and momentum with customizable weightings that adapt to different market conditions.

News Sentiment Processing: Analyze crypto news headlines and articles for sentiment changes that precede price movements.

On-Chain Metrics Integration: Include whale movements, exchange flows, and network activity as sentiment indicators.

Cross-Asset Correlations: Monitor traditional market fear indicators like VIX and their relationship to crypto sentiment.

Setting Up Ollama for Sentiment Analysis

Before we build the tracker, you need Ollama running locally. This gives you privacy, speed, and the ability to fine-tune models for crypto-specific sentiment analysis.

Installing Ollama

First, install Ollama on your system:

# Linux/macOS
curl -fsSL https://ollama.ai/install.sh | sh

# Windows (PowerShell)
winget install ollama

Pull the models we'll use for sentiment analysis:

# General sentiment analysis
ollama pull llama3.2:3b

# For more nuanced financial sentiment
ollama pull mistral:7b

# Lightweight model for high-frequency analysis
ollama pull phi3:mini

Testing Your Ollama Setup

Verify your installation with a quick sentiment test:

import requests
import json

def test_ollama_sentiment():
    """Test Ollama sentiment analysis capability"""
    
    prompt = """
    Analyze the sentiment of this crypto tweet on a scale of 1-10 
    (1 = extreme fear, 10 = extreme greed):
    
    "Bitcoin is about to break $100k! This is just the beginning! 
    HODL strong! 🚀🚀🚀"
    
    Respond with just the number and brief reason.
    """
    
    response = requests.post('http://localhost:11434/api/generate',
                           json={
                               'model': 'llama3.2:3b',
                               'prompt': prompt,
                               'stream': False
                           })
    
    result = json.loads(response.text)
    print(f"Sentiment Analysis: {result['response']}")

# Test the connection
test_ollama_sentiment()

Expected output:

Sentiment Analysis: 9 - Extreme optimism with moon emojis and price predictions indicates high greed

Building the Core Sentiment Tracker

Now let's create the main sentiment tracker class that will coordinate all our data sources and AI analysis.

Core Tracker Architecture

import asyncio
import aiohttp
import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import pandas as pd
import numpy as np

class CryptoSentimentTracker:
    """Custom Fear & Greed Index using Ollama AI models"""
    
    def __init__(self, ollama_url: str = "http://localhost:11434"):
        self.ollama_url = ollama_url
        self.sentiment_history = []
        self.weights = {
            'social_media': 0.25,
            'technical_indicators': 0.20,
            'news_sentiment': 0.20,
            'onchain_metrics': 0.20,
            'market_momentum': 0.15
        }
        
    async def analyze_text_sentiment(self, text: str, context: str = "general") -> Dict:
        """Analyze sentiment using Ollama with crypto-specific context"""
        
        prompt = f"""
        As a crypto market analyst, analyze this {context} for sentiment:
        
        "{text}"
        
        Provide a JSON response with:
        - sentiment_score: 1-10 (1=extreme fear, 10=extreme greed)
        - confidence: 0-1 (how confident you are)
        - key_phrases: list of 3 most important phrases
        - emotion_type: fear/greed/neutral/uncertainty
        
        Consider crypto-specific context like FOMO, FUD, diamond hands, etc.
        """
        
        async with aiohttp.ClientSession() as session:
            async with session.post(
                f"{self.ollama_url}/api/generate",
                json={
                    'model': 'llama3.2:3b',
                    'prompt': prompt,
                    'stream': False,
                    'format': 'json'
                }
            ) as response:
                result = await response.json()
                
        try:
            return json.loads(result['response'])
        except:
            # Fallback parsing if JSON format fails
            return self._parse_sentiment_fallback(result['response'])
    
    def _parse_sentiment_fallback(self, text: str) -> Dict:
        """Fallback parser for non-JSON responses"""
        
        # Extract sentiment score
        import re
        score_match = re.search(r'sentiment_score["\s:]*(\d+)', text)
        score = int(score_match.group(1)) if score_match else 5
        
        # Determine emotion type
        emotion = "neutral"
        if "fear" in text.lower() or "panic" in text.lower():
            emotion = "fear"
        elif "greed" in text.lower() or "fomo" in text.lower():
            emotion = "greed"
        elif "uncertain" in text.lower():
            emotion = "uncertainty"
        
        return {
            'sentiment_score': score,
            'confidence': 0.7,
            'key_phrases': ["market_sentiment"],
            'emotion_type': emotion
        }

Social Media Data Collection

The social media component is crucial since retail sentiment often drives crypto price movements. Here's how to collect and analyze Twitter/X data:

class SocialMediaAnalyzer:
    """Analyze social media sentiment for crypto"""
    
    def __init__(self, sentiment_tracker: CryptoSentimentTracker):
        self.tracker = sentiment_tracker
        self.crypto_keywords = [
            'bitcoin', 'btc', 'ethereum', 'eth', 'crypto', 'cryptocurrency',
            'altcoin', 'defi', 'nft', 'blockchain', 'hodl', 'diamond hands'
        ]
        
    async def collect_twitter_sentiment(self, coin_symbol: str, hours: int = 24) -> Dict:
        """Collect and analyze Twitter sentiment for a specific coin"""
        
        # This would integrate with Twitter API v2
        # For demo purposes, we'll simulate social media data
        sample_tweets = [
            f"{coin_symbol} is going to the moon! Best investment ever! 🚀",
            f"I'm scared about {coin_symbol} dump coming soon...",
            f"Just bought more {coin_symbol} on the dip! Diamond hands! 💎",
            f"{coin_symbol} looking bearish, might sell soon",
            f"HODL {coin_symbol} no matter what! This is the way!"
        ]
        
        sentiment_scores = []
        emotional_context = []
        
        for tweet in sample_tweets:
            analysis = await self.tracker.analyze_text_sentiment(
                tweet, 
                context="social media post"
            )
            sentiment_scores.append(analysis['sentiment_score'])
            emotional_context.append(analysis['emotion_type'])
        
        # Calculate aggregated sentiment
        avg_sentiment = np.mean(sentiment_scores)
        
        # Count emotion types
        emotion_counts = pd.Series(emotional_context).value_counts()
        
        return {
            'average_sentiment': avg_sentiment,
            'total_posts': len(sample_tweets),
            'emotion_distribution': emotion_counts.to_dict(),
            'sentiment_trend': self._calculate_sentiment_trend(sentiment_scores),
            'greed_ratio': emotion_counts.get('greed', 0) / len(sample_tweets),
            'fear_ratio': emotion_counts.get('fear', 0) / len(sample_tweets)
        }
    
    def _calculate_sentiment_trend(self, scores: List[float]) -> str:
        """Calculate if sentiment is trending up or down"""
        
        if len(scores) < 2:
            return "neutral"
        
        # Simple trend calculation
        recent_avg = np.mean(scores[-3:])
        earlier_avg = np.mean(scores[:-3]) if len(scores) > 3 else np.mean(scores)
        
        if recent_avg > earlier_avg + 0.5:
            return "increasing_greed"
        elif recent_avg < earlier_avg - 0.5:
            return "increasing_fear"
        else:
            return "stable"

Technical Indicators Integration

Technical indicators provide objective market data that complements subjective sentiment analysis. Here's how to integrate them:

import yfinance as yf
import pandas_ta as ta

class TechnicalIndicatorAnalyzer:
    """Analyze technical indicators for fear/greed signals"""
    
    def __init__(self):
        self.indicators = {}
        
    def fetch_market_data(self, symbol: str = "BTC-USD", period: str = "30d") -> pd.DataFrame:
        """Fetch cryptocurrency market data"""
        
        ticker = yf.Ticker(symbol)
        df = ticker.history(period=period)
        
        # Calculate technical indicators
        df['rsi'] = ta.rsi(df['Close'])
        df['bb_upper'], df['bb_middle'], df['bb_lower'] = ta.bbands(df['Close'])
        df['macd'], df['macd_signal'], df['macd_histogram'] = ta.macd(df['Close'])
        df['volatility'] = df['Close'].pct_change().rolling(14).std() * 100
        
        return df
    
    def calculate_fear_greed_score(self, df: pd.DataFrame) -> Dict:
        """Calculate fear/greed score from technical indicators"""
        
        latest = df.iloc[-1]
        
        # RSI Analysis (30-70 range)
        rsi_score = self._rsi_to_sentiment(latest['rsi'])
        
        # Bollinger Bands Analysis
        bb_score = self._bollinger_to_sentiment(
            latest['Close'], 
            latest['bb_upper'], 
            latest['bb_lower']
        )
        
        # MACD Analysis
        macd_score = self._macd_to_sentiment(
            latest['macd'], 
            latest['macd_signal']
        )
        
        # Volatility Analysis
        volatility_score = self._volatility_to_sentiment(latest['volatility'])
        
        # Volume Analysis
        volume_score = self._volume_to_sentiment(df)
        
        # Weighted average
        technical_score = (
            rsi_score * 0.25 +
            bb_score * 0.20 +
            macd_score * 0.20 +
            volatility_score * 0.20 +
            volume_score * 0.15
        )
        
        return {
            'technical_sentiment': technical_score,
            'rsi_sentiment': rsi_score,
            'bollinger_sentiment': bb_score,
            'macd_sentiment': macd_score,
            'volatility_sentiment': volatility_score,
            'volume_sentiment': volume_score,
            'current_rsi': latest['rsi'],
            'current_volatility': latest['volatility']
        }
    
    def _rsi_to_sentiment(self, rsi: float) -> float:
        """Convert RSI to sentiment score (1-10)"""
        if rsi >= 70:
            return 8.5  # Overbought = high greed
        elif rsi <= 30:
            return 2.0  # Oversold = high fear
        else:
            # Linear interpolation between 30-70
            return 2.0 + (rsi - 30) * (8.5 - 2.0) / (70 - 30)
    
    def _bollinger_to_sentiment(self, price: float, upper: float, lower: float) -> float:
        """Convert Bollinger Band position to sentiment"""
        bb_position = (price - lower) / (upper - lower)
        
        if bb_position >= 0.8:
            return 8.0  # Near upper band = greed
        elif bb_position <= 0.2:
            return 2.5  # Near lower band = fear
        else:
            return 3.0 + bb_position * 4.0  # Linear scaling
    
    def _macd_to_sentiment(self, macd: float, signal: float) -> float:
        """Convert MACD to sentiment score"""
        if macd > signal:
            return 6.5  # Bullish crossover = mild greed
        else:
            return 3.5  # Bearish crossover = mild fear
    
    def _volatility_to_sentiment(self, volatility: float) -> float:
        """Convert volatility to sentiment (high vol = fear)"""
        if volatility > 5:
            return 2.0  # High volatility = fear
        elif volatility < 1:
            return 7.0  # Low volatility = complacency/greed
        else:
            return 7.0 - (volatility - 1) * 5.0 / 4.0
    
    def _volume_to_sentiment(self, df: pd.DataFrame) -> float:
        """Analyze volume patterns for sentiment"""
        recent_volume = df['Volume'].tail(7).mean()
        historical_volume = df['Volume'].head(-7).mean()
        
        volume_ratio = recent_volume / historical_volume
        
        if volume_ratio > 1.5:
            return 8.0  # High volume = FOMO/greed
        elif volume_ratio < 0.5:
            return 3.0  # Low volume = apathy/fear
        else:
            return 5.0  # Normal volume = neutral

News Sentiment Analysis

News sentiment often precedes price movements. Here's how to analyze crypto news with Ollama:

import feedparser
import asyncio
from datetime import datetime

class NewsAnalyzer:
    """Analyze crypto news sentiment"""
    
    def __init__(self, sentiment_tracker: CryptoSentimentTracker):
        self.tracker = sentiment_tracker
        self.news_sources = [
            'https://cointelegraph.com/rss',
            'https://coindesk.com/arc/outboundfeeds/rss/',
            'https://decrypt.co/feed'
        ]
        
    async def analyze_news_sentiment(self, hours: int = 24) -> Dict:
        """Analyze recent crypto news sentiment"""
        
        all_articles = []
        
        # Collect articles from all sources
        for source_url in self.news_sources:
            try:
                feed = feedparser.parse(source_url)
                
                for entry in feed.entries[:10]:  # Latest 10 articles per source
                    article_time = datetime(*entry.published_parsed[:6])
                    
                    # Only analyze recent articles
                    if (datetime.now() - article_time).total_seconds() < hours * 3600:
                        all_articles.append({
                            'title': entry.title,
                            'summary': entry.summary if hasattr(entry, 'summary') else '',
                            'published': article_time,
                            'source': source_url
                        })
                        
            except Exception as e:
                print(f"Error parsing {source_url}: {e}")
                continue
        
        # Analyze sentiment for each article
        sentiment_scores = []
        article_analyses = []
        
        for article in all_articles:
            analysis = await self.tracker.analyze_text_sentiment(
                f"Title: {article['title']}\nSummary: {article['summary'][:200]}",
                context="news article"
            )
            
            sentiment_scores.append(analysis['sentiment_score'])
            article_analyses.append({
                'title': article['title'],
                'sentiment': analysis['sentiment_score'],
                'emotion': analysis['emotion_type'],
                'key_phrases': analysis['key_phrases'],
                'published': article['published']
            })
        
        # Calculate news sentiment metrics
        avg_sentiment = np.mean(sentiment_scores) if sentiment_scores else 5.0
        
        return {
            'news_sentiment': avg_sentiment,
            'total_articles': len(all_articles),
            'article_analyses': article_analyses,
            'sentiment_distribution': self._calculate_sentiment_distribution(sentiment_scores),
            'trending_topics': self._extract_trending_topics(article_analyses)
        }
    
    def _calculate_sentiment_distribution(self, scores: List[float]) -> Dict:
        """Calculate distribution of sentiment scores"""
        
        if not scores:
            return {'fear': 0, 'neutral': 0, 'greed': 0}
        
        fear_count = sum(1 for score in scores if score <= 3)
        greed_count = sum(1 for score in scores if score >= 7)
        neutral_count = len(scores) - fear_count - greed_count
        
        total = len(scores)
        return {
            'fear': fear_count / total,
            'neutral': neutral_count / total,
            'greed': greed_count / total
        }
    
    def _extract_trending_topics(self, analyses: List[Dict]) -> List[str]:
        """Extract trending topics from news articles"""
        
        all_phrases = []
        for analysis in analyses:
            all_phrases.extend(analysis['key_phrases'])
        
        # Count phrase frequency
        phrase_counts = pd.Series(all_phrases).value_counts()
        
        return phrase_counts.head(5).index.tolist()

Creating the Master Fear & Greed Index

Now let's combine all components into a comprehensive fear and greed index:

class MasterFearGreedIndex:
    """Master class combining all sentiment indicators"""
    
    def __init__(self):
        self.sentiment_tracker = CryptoSentimentTracker()
        self.social_analyzer = SocialMediaAnalyzer(self.sentiment_tracker)
        self.technical_analyzer = TechnicalIndicatorAnalyzer()
        self.news_analyzer = NewsAnalyzer(self.sentiment_tracker)
        
    async def calculate_master_index(self, symbol: str = "BTC") -> Dict:
        """Calculate comprehensive fear and greed index"""
        
        print(f"Calculating Fear & Greed Index for {symbol}...")
        
        # Gather all sentiment data
        results = await asyncio.gather(
            self.social_analyzer.collect_twitter_sentiment(symbol),
            self.news_analyzer.analyze_news_sentiment(),
            return_exceptions=True
        )
        
        social_data = results[0] if not isinstance(results[0], Exception) else {}
        news_data = results[1] if not isinstance(results[1], Exception) else {}
        
        # Get technical data
        market_df = self.technical_analyzer.fetch_market_data(f"{symbol}-USD")
        technical_data = self.technical_analyzer.calculate_fear_greed_score(market_df)
        
        # Extract individual scores
        social_score = social_data.get('average_sentiment', 5.0)
        technical_score = technical_data.get('technical_sentiment', 5.0)
        news_score = news_data.get('news_sentiment', 5.0)
        
        # Calculate weighted master score
        weights = {
            'social': 0.35,
            'technical': 0.40,
            'news': 0.25
        }
        
        master_score = (
            social_score * weights['social'] +
            technical_score * weights['technical'] +
            news_score * weights['news']
        )
        
        # Determine sentiment label
        sentiment_label = self._score_to_label(master_score)
        
        return {
            'master_score': round(master_score, 2),
            'sentiment_label': sentiment_label,
            'component_scores': {
                'social_sentiment': round(social_score, 2),
                'technical_sentiment': round(technical_score, 2),
                'news_sentiment': round(news_score, 2)
            },
            'detailed_analysis': {
                'social': social_data,
                'technical': technical_data,
                'news': news_data
            },
            'trading_signal': self._generate_trading_signal(master_score),
            'timestamp': datetime.now().isoformat()
        }
    
    def _score_to_label(self, score: float) -> str:
        """Convert numeric score to sentiment label"""
        
        if score <= 2:
            return "Extreme Fear"
        elif score <= 4:
            return "Fear"
        elif score <= 6:
            return "Neutral"
        elif score <= 8:
            return "Greed"
        else:
            return "Extreme Greed"
    
    def _generate_trading_signal(self, score: float) -> Dict:
        """Generate trading signals based on fear/greed score"""
        
        if score <= 2.5:
            return {
                'signal': 'STRONG_BUY',
                'reasoning': 'Extreme fear often signals market bottoms',
                'confidence': 0.8
            }
        elif score <= 4:
            return {
                'signal': 'BUY',
                'reasoning': 'Fear presents buying opportunities',
                'confidence': 0.6
            }
        elif score >= 7.5:
            return {
                'signal': 'STRONG_SELL',
                'reasoning': 'Extreme greed often signals market tops',
                'confidence': 0.8
            }
        elif score >= 6.5:
            return {
                'signal': 'SELL',
                'reasoning': 'Greed suggests overvaluation',
                'confidence': 0.6
            }
        else:
            return {
                'signal': 'HOLD',
                'reasoning': 'Neutral sentiment, wait for clearer signals',
                'confidence': 0.4
            }

Running Your Custom Fear & Greed Index

Here's how to run your complete sentiment tracker:

async def main():
    """Run the complete fear and greed analysis"""
    
    # Initialize the master index
    master_index = MasterFearGreedIndex()
    
    # Calculate for Bitcoin
    btc_analysis = await master_index.calculate_master_index("BTC")
    
    # Display results
    print("="*60)
    print("CUSTOM CRYPTO FEAR & GREED INDEX")
    print("="*60)
    print(f"Asset: Bitcoin (BTC)")
    print(f"Master Score: {btc_analysis['master_score']}/10")
    print(f"Sentiment: {btc_analysis['sentiment_label']}")
    print(f"Trading Signal: {btc_analysis['trading_signal']['signal']}")
    print(f"Reasoning: {btc_analysis['trading_signal']['reasoning']}")
    print()
    
    print("Component Breakdown:")
    print(f"  Social Media: {btc_analysis['component_scores']['social_sentiment']}/10")
    print(f"  Technical: {btc_analysis['component_scores']['technical_sentiment']}/10")
    print(f"  News: {btc_analysis['component_scores']['news_sentiment']}/10")
    print()
    
    # Show detailed technical analysis
    technical = btc_analysis['detailed_analysis']['technical']
    print("Technical Details:")
    print(f"  RSI: {technical['current_rsi']:.1f}")
    print(f"  Volatility: {technical['current_volatility']:.1f}%")
    print()
    
    # Show social media insights
    social = btc_analysis['detailed_analysis']['social']
    if social:
        print("Social Media Insights:")
        print(f"  Posts Analyzed: {social['total_posts']}")
        print(f"  Greed Ratio: {social['greed_ratio']:.2f}")
        print(f"  Fear Ratio: {social['fear_ratio']:.2f}")
        print(f"  Trend: {social['sentiment_trend']}")
    
    print("="*60)

# Run the analysis
if __name__ == "__main__":
    asyncio.run(main())

Example output:

============================================================
CUSTOM CRYPTO FEAR & GREED INDEX
============================================================
Asset: Bitcoin (BTC)
Master Score: 7.2/10
Sentiment: Greed
Trading Signal: SELL
Reasoning: Greed suggests overvaluation

Component Breakdown:
  Social Media: 8.1/10
  Technical: 6.8/10
  News: 6.7/10

Technical Details:
  RSI: 72.3
  Volatility: 3.2%

Social Media Insights:
  Posts Analyzed: 5
  Greed Ratio: 0.60
  Fear Ratio: 0.20
  Trend: increasing_greed
============================================================

Advanced Features and Customization

Dynamic Weight Adjustment

Market conditions change, so your index weights should adapt:

class AdaptiveWeightManager:
    """Dynamically adjust component weights based on market conditions"""
    
    def __init__(self):
        self.base_weights = {
            'social': 0.35,
            'technical': 0.40,
            'news': 0.25
        }
        
    def adjust_weights(self, market_data: Dict) -> Dict:
        """Adjust weights based on market volatility and phase"""
        
        volatility = market_data.get('current_volatility', 3.0)
        
        # During high volatility, trust technical indicators more
        if volatility > 6:
            return {
                'social': 0.25,
                'technical': 0.50,
                'news': 0.25
            }
        # During low volatility, social sentiment becomes more important
        elif volatility < 2:
            return {
                'social': 0.50,
                'technical': 0.25,
                'news': 0.25
            }
        else:
            return self.base_weights

Historical Tracking and Backtesting

Track your index performance over time:

class PerformanceTracker:
    """Track fear/greed index performance and trading signals"""
    
    def __init__(self):
        self.history = []
        
    def log_analysis(self, analysis: Dict, price: float):
        """Log analysis results with current price"""
        
        self.history.append({
            'timestamp': datetime.now(),
            'score': analysis['master_score'],
            'sentiment': analysis['sentiment_label'],
            'signal': analysis['trading_signal']['signal'],
            'price': price,
            'components': analysis['component_scores']
        })
        
    def calculate_signal_performance(self, days: int = 30) -> Dict:
        """Calculate how well trading signals performed"""
        
        if len(self.history) < 2:
            return {"error": "Not enough data"}
        
        # Filter recent signals
        cutoff_date = datetime.now() - timedelta(days=days)
        recent_signals = [
            h for h in self.history 
            if h['timestamp'] > cutoff_date
        ]
        
        # Calculate returns for each signal type
        signal_returns = {'BUY': [], 'SELL': [], 'HOLD': []}
        
        for i, signal in enumerate(recent_signals[:-1]):
            next_signal = recent_signals[i + 1]
            
            # Calculate return
            price_change = (next_signal['price'] - signal['price']) / signal['price']
            
            if signal['signal'] in ['BUY', 'STRONG_BUY']:
                signal_returns['BUY'].append(price_change)
            elif signal['signal'] in ['SELL', 'STRONG_SELL']:
                signal_returns['SELL'].append(-price_change)  # Inverse for short
            else:
                signal_returns['HOLD'].append(0)
        
        # Calculate performance metrics
        performance = {}
        for signal_type, returns in signal_returns.items():
            if returns:
                performance[signal_type] = {
                    'avg_return': np.mean(returns),
                    'success_rate': sum(1 for r in returns if r > 0) / len(returns),
                    'total_signals': len(returns)
                }
        
        return performance

Deployment and Automation

Setting Up Automated Analysis

Create a scheduled task to run your analysis:

import schedule
import time
from datetime import datetime

class AutomatedTracker:
    """Automated fear/greed index tracking"""
    
    def __init__(self):
        self.master_index = MasterFearGreedIndex()
        self.performance_tracker = PerformanceTracker()
        
    async def run_analysis(self):
        """Run complete analysis and log results"""
        
        try:
            # Get current Bitcoin price
            btc_price = self.get_current_price("BTC-USD")
            
            # Run fear/greed analysis
            analysis = await self.master_index.calculate_master_index("BTC")
            
            # Log for performance tracking
            self.performance_tracker.log_analysis(analysis, btc_price)
            
            # Check for significant signals
            if analysis['trading_signal']['confidence'] > 0.7:
                await self.send_alert(analysis, btc_price)
                
            print(f"Analysis completed at {datetime.now()}")
            print(f"Score: {analysis['master_score']} | Signal: {analysis['trading_signal']['signal']}")
            
        except Exception as e:
            print(f"Error in analysis: {e}")
    
    def get_current_price(self, symbol: str) -> float:
        """Get current cryptocurrency price"""
        
        try:
            ticker = yf.Ticker(symbol)
            data = ticker.history(period="1d")
            return float(data['Close'].iloc[-1])
        except:
            return 0.0
    
    async def send_alert(self, analysis: Dict, price: float):
        """Send alert for significant signals"""
        
        signal = analysis['trading_signal']
        
        message = f"""
        🚨 CRYPTO FEAR & GREED ALERT 🚨
        
        Score: {analysis['master_score']}/10 ({analysis['sentiment_label']})
        Signal: {signal['signal']}
        Confidence: {signal['confidence']:.0%}
        
        Current BTC Price: ${price:,.2f}
        
        Reasoning: {signal['reasoning']}
        
        Component Breakdown:
        📱 Social: {analysis['component_scores']['social_sentiment']}/10
        📊 Technical: {analysis['component_scores']['technical_sentiment']}/10
        📰 News: {analysis['component_scores']['news_sentiment']}/10
        """
        
        # Send to Discord, Slack, or email
        await self.send_to_discord(message)
        
    async def send_to_discord(self, message: str):
        """Send alert to Discord webhook"""
        
        webhook_url = "YOUR_DISCORD_WEBHOOK_URL"
        
        if not webhook_url or webhook_url == "YOUR_DISCORD_WEBHOOK_URL":
            print("Discord webhook not configured")
            print(message)
            return
        
        async with aiohttp.ClientSession() as session:
            async with session.post(webhook_url, json={"content": message}) as response:
                if response.status == 204:
                    print("Alert sent to Discord")
                else:
                    print(f"Failed to send Discord alert: {response.status}")

# Set up automated scheduling
def setup_automation():
    """Set up automated fear/greed analysis"""
    
    tracker = AutomatedTracker()
    
    # Schedule analysis every 4 hours
    schedule.every(4).hours.do(lambda: asyncio.run(tracker.run_analysis()))
    
    # Schedule daily performance report
    schedule.every().day.at("09:00").do(lambda: asyncio.run(tracker.generate_daily_report()))
    
    print("Automated tracking started...")
    print("Analysis will run every 4 hours")
    print("Daily reports at 9:00 AM")
    
    while True:
        schedule.run_pending()
        time.sleep(60)  # Check every minute

# Add daily report method to AutomatedTracker
async def generate_daily_report(self):
    """Generate daily performance report"""
    
    performance = self.performance_tracker.calculate_signal_performance(7)
    
    if 'error' in performance:
        print("Not enough data for performance report")
        return
    
    report = f"""
    📊 WEEKLY FEAR & GREED PERFORMANCE REPORT
    
    Signal Performance (Last 7 Days):
    """
    
    for signal_type, metrics in performance.items():
        report += f"""
    {signal_type} Signals:
    • Average Return: {metrics['avg_return']:.2%}
    • Success Rate: {metrics['success_rate']:.1%}
    • Total Signals: {metrics['total_signals']}
    """
    
    await self.send_to_discord(report)

Web Dashboard Creation

Create a web interface to visualize your fear/greed index:

from flask import Flask, render_template, jsonify
import plotly.graph_objs as go
import plotly.utils

app = Flask(__name__)

class FearGreedDashboard:
    """Web dashboard for fear/greed index"""
    
    def __init__(self):
        self.master_index = MasterFearGreedIndex()
        self.performance_tracker = PerformanceTracker()
        
    @app.route('/')
    def dashboard():
        return render_template('dashboard.html')
    
    @app.route('/api/current-analysis')
    async def get_current_analysis():
        """API endpoint for current analysis"""
        
        try:
            analysis = await self.master_index.calculate_master_index("BTC")
            return jsonify(analysis)
        except Exception as e:
            return jsonify({"error": str(e)}), 500
    
    @app.route('/api/historical-data')
    def get_historical_data():
        """API endpoint for historical data"""
        
        # Get last 30 days of data
        history = self.performance_tracker.history[-30:]
        
        return jsonify({
            'timestamps': [h['timestamp'].isoformat() for h in history],
            'scores': [h['score'] for h in history],
            'prices': [h['price'] for h in history],
            'signals': [h['signal'] for h in history]
        })
    
    @app.route('/api/performance-chart')
    def get_performance_chart():
        """Generate performance chart"""
        
        history = self.performance_tracker.history[-30:]
        
        if not history:
            return jsonify({"error": "No data available"})
        
        # Create plotly chart
        fig = go.Figure()
        
        # Add fear/greed score
        fig.add_trace(go.Scatter(
            x=[h['timestamp'] for h in history],
            y=[h['score'] for h in history],
            mode='lines+markers',
            name='Fear/Greed Score',
            line=dict(color='blue'),
            yaxis='y1'
        ))
        
        # Add price on secondary y-axis
        fig.add_trace(go.Scatter(
            x=[h['timestamp'] for h in history],
            y=[h['price'] for h in history],
            mode='lines',
            name='BTC Price',
            line=dict(color='orange'),
            yaxis='y2'
        ))
        
        # Add trading signals as markers
        buy_signals = [h for h in history if 'BUY' in h['signal']]
        sell_signals = [h for h in history if 'SELL' in h['signal']]
        
        if buy_signals:
            fig.add_trace(go.Scatter(
                x=[h['timestamp'] for h in buy_signals],
                y=[h['price'] for h in buy_signals],
                mode='markers',
                name='Buy Signals',
                marker=dict(color='green', size=10, symbol='triangle-up'),
                yaxis='y2'
            ))
        
        if sell_signals:
            fig.add_trace(go.Scatter(
                x=[h['timestamp'] for h in sell_signals],
                y=[h['price'] for h in sell_signals],
                mode='markers',
                name='Sell Signals',
                marker=dict(color='red', size=10, symbol='triangle-down'),
                yaxis='y2'
            ))
        
        # Update layout
        fig.update_layout(
            title='Fear/Greed Index vs Bitcoin Price',
            xaxis_title='Date',
            yaxis=dict(title='Fear/Greed Score', side='left'),
            yaxis2=dict(title='BTC Price ($)', side='right', overlaying='y'),
            hovermode='x unified'
        )
        
        return jsonify(plotly.utils.PlotlyJSONEncoder().encode(fig))

if __name__ == '__main__':
    app.run(debug=True, port=5000)

Create the HTML template (templates/dashboard.html):

<!DOCTYPE html>
<html>
<head>
    <title>Crypto Fear & Greed Dashboard</title>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .metric-card { 
            display: inline-block; 
            margin: 10px; 
            padding: 20px; 
            border: 1px solid #ddd; 
            border-radius: 8px;
            min-width: 200px;
        }
        .score { font-size: 2em; font-weight: bold; }
        .fear { color: #ff4444; }
        .greed { color: #44ff44; }
        .neutral { color: #666; }
        #chart { height: 500px; margin: 20px 0; }
    </style>
</head>
<body>
    <h1>🚀 Crypto Fear & Greed Index Dashboard</h1>
    
    <div id="current-metrics">
        <div class="metric-card">
            <h3>Master Score</h3>
            <div id="master-score" class="score">Loading...</div>
            <div id="sentiment-label">Loading...</div>
        </div>
        
        <div class="metric-card">
            <h3>Trading Signal</h3>
            <div id="trading-signal" class="score">Loading...</div>
            <div id="signal-confidence">Loading...</div>
        </div>
        
        <div class="metric-card">
            <h3>Social Sentiment</h3>
            <div id="social-score" class="score">Loading...</div>
        </div>
        
        <div class="metric-card">
            <h3>Technical Score</h3>
            <div id="technical-score" class="score">Loading...</div>
        </div>
    </div>
    
    <div id="chart"></div>
    
    <script>
        // Load current analysis
        async function loadCurrentAnalysis() {
            try {
                const response = await fetch('/api/current-analysis');
                const data = await response.json();
                
                document.getElementById('master-score').textContent = data.master_score;
                document.getElementById('sentiment-label').textContent = data.sentiment_label;
                document.getElementById('trading-signal').textContent = data.trading_signal.signal;
                document.getElementById('signal-confidence').textContent = 
                    `Confidence: ${(data.trading_signal.confidence * 100).toFixed(0)}%`;
                
                document.getElementById('social-score').textContent = 
                    data.component_scores.social_sentiment;
                document.getElementById('technical-score').textContent = 
                    data.component_scores.technical_sentiment;
                
                // Color code the master score
                const scoreElement = document.getElementById('master-score');
                if (data.master_score <= 4) {
                    scoreElement.className = 'score fear';
                } else if (data.master_score >= 7) {
                    scoreElement.className = 'score greed';
                } else {
                    scoreElement.className = 'score neutral';
                }
                
            } catch (error) {
                console.error('Error loading analysis:', error);
            }
        }
        
        // Load performance chart
        async function loadChart() {
            try {
                const response = await fetch('/api/performance-chart');
                const chartData = await response.json();
                
                Plotly.newPlot('chart', chartData.data, chartData.layout);
                
            } catch (error) {
                console.error('Error loading chart:', error);
            }
        }
        
        // Initialize dashboard
        loadCurrentAnalysis();
        loadChart();
        
        // Refresh every 5 minutes
        setInterval(loadCurrentAnalysis, 5 * 60 * 1000);
    </script>
</body>
</html>

Advanced Signal Generation

Multi-Timeframe Analysis

Enhance your signals by analyzing multiple timeframes:

class MultiTimeframeAnalyzer:
    """Analyze fear/greed across multiple timeframes"""
    
    def __init__(self, master_index: MasterFearGreedIndex):
        self.master_index = master_index
        
    async def analyze_multiple_timeframes(self, symbol: str) -> Dict:
        """Analyze fear/greed across different timeframes"""
        
        timeframes = {
            '1h': {'social_hours': 1, 'news_hours': 4, 'market_period': '5d'},
            '4h': {'social_hours': 4, 'news_hours': 12, 'market_period': '30d'},
            '1d': {'social_hours': 24, 'news_hours': 48, 'market_period': '90d'},
            '1w': {'social_hours': 168, 'news_hours': 168, 'market_period': '1y'}
        }
        
        results = {}
        
        for timeframe, params in timeframes.items():
            # Customize analysis parameters for each timeframe
            self.master_index.social_analyzer.hours = params['social_hours']
            self.master_index.news_analyzer.hours = params['news_hours']
            
            # Run analysis
            analysis = await self.master_index.calculate_master_index(symbol)
            
            results[timeframe] = {
                'score': analysis['master_score'],
                'sentiment': analysis['sentiment_label'],
                'signal': analysis['trading_signal']['signal'],
                'confidence': analysis['trading_signal']['confidence']
            }
        
        # Generate consensus signal
        consensus = self._generate_consensus_signal(results)
        
        return {
            'timeframe_analysis': results,
            'consensus_signal': consensus,
            'signal_strength': self._calculate_signal_strength(results)
        }
    
    def _generate_consensus_signal(self, results: Dict) -> Dict:
        """Generate consensus signal from multiple timeframes"""
        
        signals = [data['signal'] for data in results.values()]
        confidences = [data['confidence'] for data in results.values()]
        
        # Weight signals by timeframe importance
        weights = {'1h': 0.1, '4h': 0.2, '1d': 0.4, '1w': 0.3}
        
        buy_weight = 0
        sell_weight = 0
        
        for timeframe, signal_data in results.items():
            weight = weights[timeframe]
            signal = signal_data['signal']
            confidence = signal_data['confidence']
            
            if 'BUY' in signal:
                buy_weight += weight * confidence
            elif 'SELL' in signal:
                sell_weight += weight * confidence
        
        # Determine consensus
        if buy_weight > sell_weight + 0.2:
            return {'signal': 'BUY', 'confidence': buy_weight}
        elif sell_weight > buy_weight + 0.2:
            return {'signal': 'SELL', 'confidence': sell_weight}
        else:
            return {'signal': 'HOLD', 'confidence': 0.5}
    
    def _calculate_signal_strength(self, results: Dict) -> float:
        """Calculate overall signal strength"""
        
        scores = [data['score'] for data in results.values()]
        
        # Calculate agreement between timeframes
        score_std = np.std(scores)
        
        # Lower standard deviation = higher agreement = stronger signal
        strength = max(0, 1 - (score_std / 3))
        
        return strength

Risk Management Integration

Add risk management features to your signals:

class RiskManager:
    """Risk management for fear/greed trading signals"""
    
    def __init__(self):
        self.max_position_size = 0.1  # 10% of portfolio
        self.stop_loss_percent = 0.05  # 5% stop loss
        self.take_profit_percent = 0.15  # 15% take profit
        
    def calculate_position_size(self, 
                              signal_confidence: float,
                              volatility: float,
                              account_balance: float) -> Dict:
        """Calculate optimal position size based on signal and risk"""
        
        # Base position size on confidence
        base_size = signal_confidence * self.max_position_size
        
        # Adjust for volatility
        volatility_adjustment = max(0.1, 1 - (volatility / 10))
        adjusted_size = base_size * volatility_adjustment
        
        # Calculate dollar amount
        dollar_amount = account_balance * adjusted_size
        
        return {
            'position_size_percent': adjusted_size,
            'dollar_amount': dollar_amount,
            'stop_loss_price': None,  # Set after entry
            'take_profit_price': None,  # Set after entry
            'risk_reward_ratio': self.take_profit_percent / self.stop_loss_percent
        }
    
    def set_exit_levels(self, entry_price: float, signal_type: str) -> Dict:
        """Set stop loss and take profit levels"""
        
        if signal_type in ['BUY', 'STRONG_BUY']:
            stop_loss = entry_price * (1 - self.stop_loss_percent)
            take_profit = entry_price * (1 + self.take_profit_percent)
        else:  # SELL signals
            stop_loss = entry_price * (1 + self.stop_loss_percent)
            take_profit = entry_price * (1 - self.take_profit_percent)
        
        return {
            'stop_loss': stop_loss,
            'take_profit': take_profit,
            'risk_amount': abs(entry_price - stop_loss),
            'reward_amount': abs(take_profit - entry_price)
        }

Conclusion

Building a custom crypto fear and greed index with Ollama gives you several advantages over using the standard index. You control the data sources, can weight different factors based on market conditions, and integrate real-time AI analysis that understands crypto-specific sentiment.

Your custom tracker analyzes social media sentiment with context-aware AI, combines technical indicators with adaptive weightings, processes news sentiment for early signals, and generates actionable trading signals with confidence scores. The system runs locally with Ollama, protecting your privacy while providing fast, customizable analysis.

The key to success is continuous refinement. Monitor your signal performance, adjust weightings based on market conditions, and add new data sources as they become available. Remember that no sentiment indicator is perfect, but combining multiple sources with AI analysis gives you a significant edge in understanding market psychology.

Start with the basic implementation, then gradually add the advanced features like multi-timeframe analysis, risk management, and automated alerts. Your custom fear and greed index will become more accurate as you feed it more data and refine the analysis components.

Market sentiment drives crypto prices more than fundamentals. With your custom Ollama-powered sentiment tracker, you'll have the tools to profit from the eternal cycle of fear and greed that governs cryptocurrency markets.