Crypto Bots

Crypto Fear and Greed Index: How to Build a Sentiment Trading Bot

The Crypto Fear and Greed Index is one of the most reliable contrarian indicators in crypto. Learn how to automate buy/sell decisions based on extreme sentiment readings.

A
AI Agents Hubยท2026-02-22ยท6 min readยท1,006 words

Builder of AI agents, crypto trading bots, and open-source automation tools. Sharing practical guides on how to build, deploy, and profit from AI and DeFi technology.

Why the Fear and Greed Index Works

Warren Buffett's famous rule โ€” "Be fearful when others are greedy, and greedy when others are fearful" โ€” is mathematically provable in crypto data.

The Crypto Fear and Greed Index (0-100) combines:

  • Volatility (25%): High volatility โ†’ more fear
  • Market momentum (25%): Strong up trends โ†’ more greed
  • Social media (15%): Positive social sentiment โ†’ more greed
  • Surveys (15%): Direct polling (paused currently)
  • Bitcoin dominance (10%): High dominance โ†’ fear of altcoins
  • Trends (10%): Google Trends for "Bitcoin"

The contrarian signal:

  • Extreme Fear (0-25): Historically great buying opportunities
  • Extreme Greed (75-100): Historically good times to reduce exposure

Historical Performance of the Signal

| Period | F&G at Start | Action | 30-Day Return | |--------|-------------|--------|---------------| | Jan 2019 | 8 (Extreme Fear) | BUY | +36% | | Jun 2019 | 91 (Extreme Greed) | SELL | -24% | | Mar 2020 | 10 (Extreme Fear) | BUY | +45% | | Nov 2021 | 82 (Extreme Greed) | SELL | -30% | | Jun 2022 | 6 (Extreme Fear) | BUY | +12% | | Nov 2022 | 20 (Fear) | BUY | +18% |

Not every extreme reading leads to a reversal โ€” but the track record is significant enough to build a systematic strategy around it.

Fetching the Fear and Greed Index

import requests
from datetime import datetime, timedelta

def get_fear_greed() -> dict:
    """Get current and historical Fear & Greed data"""
    response = requests.get(
        "https://api.alternative.me/fng/",
        params={"limit": 30, "format": "json"}
    )
    data = response.json()['data']
    
    current = data[0]
    yesterday = data[1]
    week_ago = data[7] if len(data) > 7 else data[-1]
    
    return {
        'current': {
            'value': int(current['value']),
            'classification': current['value_classification'],
            'timestamp': datetime.fromtimestamp(int(current['timestamp'])).isoformat()
        },
        'yesterday': int(yesterday['value']),
        'week_ago': int(week_ago['value']),
        'trend': 'improving' if int(current['value']) > int(week_ago['value']) else 'declining',
        'history': [int(d['value']) for d in data]
    }

# Example output:
# {
#   'current': {'value': 35, 'classification': 'Fear', 'timestamp': '2026-03-01'},
#   'yesterday': 32,
#   'week_ago': 28,
#   'trend': 'improving'
# }

Building the Sentiment Trading Bot

import ccxt
import schedule
import time
from dataclasses import dataclass

@dataclass
class SentimentConfig:
    extreme_fear_threshold: int = 20    # BUY when below this
    fear_threshold: int = 35            # Partial buy
    greed_threshold: int = 65           # Partial sell
    extreme_greed_threshold: int = 80   # SELL when above this
    
    # Position sizing
    extreme_fear_allocation: float = 0.20    # Buy 20% of dry powder on extreme fear
    fear_allocation: float = 0.10            # Buy 10% on normal fear
    greed_deallocation: float = 0.10         # Sell 10% on normal greed
    extreme_greed_deallocation: float = 0.25 # Sell 25% on extreme greed
    
    # Cooldown: don't trade if we just traded in last N days
    cooldown_days: int = 3

class FearGreedBot:
    def __init__(self, exchange: ccxt.Exchange, config: SentimentConfig):
        self.exchange = exchange
        self.config = config
        self.last_trade_date = None
        self.trade_log = []
    
    def check_cooldown(self) -> bool:
        """Return True if we can trade (not in cooldown)"""
        if not self.last_trade_date:
            return True
        days_since = (datetime.now() - self.last_trade_date).days
        return days_since >= self.config.cooldown_days
    
    def get_available_capital(self) -> float:
        """Get USDT balance available for trading"""
        balance = self.exchange.fetch_balance()
        return balance['USDT']['free']
    
    def get_btc_value(self) -> float:
        """Get total BTC position value in USDT"""
        balance = self.exchange.fetch_balance()
        btc_held = balance.get('BTC', {}).get('total', 0)
        if btc_held == 0:
            return 0
        ticker = self.exchange.fetch_ticker('BTC/USDT')
        return btc_held * ticker['last']
    
    def execute_strategy(self):
        """Main strategy logic - called daily"""
        if not self.check_cooldown():
            print("In cooldown period, skipping...")
            return
        
        fg = get_fear_greed()
        value = fg['current']['value']
        classification = fg['current']['classification']
        
        print(f"Fear & Greed: {value} ({classification}), Trend: {fg['trend']}")
        
        usdt_balance = self.get_available_capital()
        btc_value = self.get_btc_value()
        
        if value <= self.config.extreme_fear_threshold and fg['trend'] == 'improving':
            # EXTREME FEAR + improving โ†’ Strong buy signal
            buy_amount = usdt_balance * self.config.extreme_fear_allocation
            if buy_amount > 100:  # Minimum $100 trade
                print(f"๐ŸŸข EXTREME FEAR BUY: ${buy_amount:.0f}")
                self.buy_btc(buy_amount)
                self.last_trade_date = datetime.now()
        
        elif value <= self.config.fear_threshold:
            # FEAR โ†’ Smaller buy
            buy_amount = usdt_balance * self.config.fear_allocation
            if buy_amount > 50:
                print(f"๐ŸŸก FEAR BUY: ${buy_amount:.0f}")
                self.buy_btc(buy_amount)
                self.last_trade_date = datetime.now()
        
        elif value >= self.config.extreme_greed_threshold and fg['trend'] == 'declining':
            # EXTREME GREED + declining โ†’ Strong sell signal
            sell_amount = btc_value * self.config.extreme_greed_deallocation
            if sell_amount > 100:
                print(f"๐Ÿ”ด EXTREME GREED SELL: ${sell_amount:.0f}")
                self.sell_btc(sell_amount)
                self.last_trade_date = datetime.now()
        
        elif value >= self.config.greed_threshold:
            # GREED โ†’ Smaller sell
            sell_amount = btc_value * self.config.greed_deallocation
            if sell_amount > 50:
                print(f"๐ŸŸ  GREED SELL: ${sell_amount:.0f}")
                self.sell_btc(sell_amount)
                self.last_trade_date = datetime.now()
        
        else:
            print(f"โœ“ Neutral ({value}) โ€” holding")
    
    def buy_btc(self, usdt_amount: float):
        """Execute a buy order"""
        order = self.exchange.create_market_buy_order(
            'BTC/USDT',
            usdt_amount / self.exchange.fetch_ticker('BTC/USDT')['last'],
            {'quoteOrderQty': usdt_amount}
        )
        self.trade_log.append({'type': 'BUY', 'amount': usdt_amount, 'date': datetime.now()})
    
    def sell_btc(self, usdt_amount: float):
        """Execute a sell order"""
        btc_qty = usdt_amount / self.exchange.fetch_ticker('BTC/USDT')['last']
        order = self.exchange.create_market_sell_order('BTC/USDT', btc_qty)
        self.trade_log.append({'type': 'SELL', 'amount': usdt_amount, 'date': datetime.now()})

# Initialize and run
exchange = ccxt.binance({'apiKey': API_KEY, 'secret': SECRET})
config = SentimentConfig()
bot = FearGreedBot(exchange, config)

# Run once daily at 00:05 UTC (after midnight update)
schedule.every().day.at("00:05").do(bot.execute_strategy)

while True:
    schedule.run_pending()
    time.sleep(3600)

Combining F&G with Other Indicators

The Fear and Greed signal is most powerful when confirmed:

def get_composite_signal() -> dict:
    """Combine F&G with technical and on-chain signals"""
    fg = get_fear_greed()
    
    # Get BTC technical data
    btc_above_200ma = get_btc_vs_200ma() > 1.0
    mvrv = get_mvrv_ratio()  # Market Value to Realized Value
    exchange_netflow = get_exchange_netflow_30d()  # Negative = outflows (bullish)
    
    signals = []
    
    # Signal 1: F&G
    if fg['current']['value'] < 25:
        signals.append(('fear_greed', 1.0, 'Extreme Fear'))
    elif fg['current']['value'] < 45:
        signals.append(('fear_greed', 0.5, 'Fear'))
    elif fg['current']['value'] > 75:
        signals.append(('fear_greed', -1.0, 'Extreme Greed'))
    elif fg['current']['value'] > 55:
        signals.append(('fear_greed', -0.5, 'Greed'))
    
    # Signal 2: MVRV (< 1.0 = undervalued, > 3.5 = overvalued)
    if mvrv < 1.0:
        signals.append(('mvrv', 1.0, 'MVRV undervalued'))
    elif mvrv > 3.5:
        signals.append(('mvrv', -1.0, 'MVRV overvalued'))
    
    # Signal 3: Exchange flows
    if exchange_netflow < -1000:  # 1000+ BTC left exchanges
        signals.append(('netflow', 0.5, 'Exchange outflows bullish'))
    
    total_score = sum(s[1] for s in signals)
    return {
        'composite_score': total_score,
        'action': 'BUY' if total_score > 1.0 else 'SELL' if total_score < -1.0 else 'HOLD',
        'signals': signals
    }

Sentiment trading is patient trading. The biggest returns come from holding for weeks or months after extreme fear buying. This is not a strategy for the impatient โ€” but it's one of the most consistently profitable systematic approaches in crypto.

Related Articles