Passive Income

How to Build a Crypto Signals Telegram Channel That Makes Money

Automated Telegram channels delivering AI-generated crypto trading signals can generate $1,000-5,000/month. Learn how to build the signal engine, set up a paid channel, and automate delivery.

A
AI Agents Hubยท2026-02-19ยท5 min readยท929 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.

The Telegram Signals Business Model

Crypto trading signal channels on Telegram are big business. Channels with 10,000+ subscribers commonly charge $50-150/month for premium signal access. The economics are compelling:

  • 1,000 premium subscribers ร— $49/month = $49,000/month
  • Operating costs: ~$100-500/month (server + API keys)

The key is delivering genuine value โ€” signals that work. AI-generated signals from a properly backtested system are more reliable than most human "signal providers."

Architecture Overview

Your AI Signal Engine
    โ†“ generates signals
Telegram Bot API
    โ”œโ”€โ”€ Free channel (teaser signals, delayed by 1 hour)
    โ””โ”€โ”€ Paid channel (instant signals, with reasoning)
Payment Gateway (Stripe/Crypto)
    โ†“ on payment
Auto-approve to paid channel

Step 1: Build the Signal Engine

import ccxt
import pandas as pd
import numpy as np
from openai import OpenAI
from datetime import datetime

class SignalEngine:
    def __init__(self):
        self.exchange = ccxt.binance()
        self.openai = OpenAI()
        self.tracked_pairs = [
            'BTC/USDT', 'ETH/USDT', 'SOL/USDT', 
            'BNB/USDT', 'AVAX/USDT', 'LINK/USDT'
        ]
    
    def calculate_technical_score(self, symbol: str) -> dict:
        """Generate a technical analysis score for a pair"""
        ohlcv = self.exchange.fetch_ohlcv(symbol, '4h', limit=100)
        df = pd.DataFrame(ohlcv, columns=['ts', 'open', 'high', 'low', 'close', 'volume'])
        
        closes = df['close'].values
        
        # RSI
        rsi = self.calculate_rsi(closes)
        
        # MACD
        ema12 = df['close'].ewm(span=12).mean().iloc[-1]
        ema26 = df['close'].ewm(span=26).mean().iloc[-1]
        macd = ema12 - ema26
        signal_line = df['close'].ewm(span=9).mean().iloc[-1]
        macd_signal = 1 if macd > signal_line else -1
        
        # Moving averages
        ma20 = closes[-20:].mean()
        ma50 = closes[-50:].mean()
        price_vs_ma20 = (closes[-1] - ma20) / ma20
        
        # Volume trend
        avg_vol = df['volume'].iloc[-20:].mean()
        recent_vol = df['volume'].iloc[-1]
        volume_surge = recent_vol / avg_vol
        
        # Composite score (-1 to 1)
        score = 0
        score += 0.3 * (1 if rsi < 40 else -1 if rsi > 70 else 0)  # RSI
        score += 0.3 * macd_signal  # MACD
        score += 0.2 * (1 if price_vs_ma20 > 0 else -1)  # Trend
        score += 0.2 * min(volume_surge - 1, 1)  # Volume confirmation
        
        return {
            'symbol': symbol,
            'score': score,
            'rsi': rsi,
            'macd_bullish': macd_signal == 1,
            'above_ma20': price_vs_ma20 > 0,
            'volume_surge': volume_surge > 1.5,
            'current_price': closes[-1],
        }
    
    def calculate_rsi(self, prices: np.ndarray, period: int = 14) -> float:
        deltas = np.diff(prices)
        gains = np.where(deltas > 0, deltas, 0)
        losses = np.where(deltas < 0, -deltas, 0)
        avg_gain = gains[-period:].mean()
        avg_loss = losses[-period:].mean()
        if avg_loss == 0:
            return 100.0
        rs = avg_gain / avg_loss
        return 100 - (100 / (1 + rs))
    
    def generate_ai_signal(self, tech_data: dict) -> dict:
        """Use GPT-4o-mini to generate a formatted trading signal"""
        prompt = f"""
        Generate a trading signal for {tech_data['symbol']}:
        - Current Price: ${tech_data['current_price']:,.2f}
        - RSI (4h): {tech_data['rsi']:.1f}
        - MACD: {'Bullish' if tech_data['macd_bullish'] else 'Bearish'}
        - Above 20 MA: {'Yes' if tech_data['above_ma20'] else 'No'}
        - Volume Surge: {'Yes' if tech_data['volume_surge'] else 'No'}
        - Technical Score: {tech_data['score']:.2f} (-1 bearish to +1 bullish)
        
        Provide:
        1. Direction: LONG or SHORT (or WAIT if unclear)
        2. Entry zone: specific price range
        3. Stop loss: specific price
        4. Target 1: first take profit
        5. Target 2: full take profit
        6. Timeframe: how long to hold
        7. Confidence: 1-5 stars
        8. Reasoning: 1-2 sentences
        
        Format as a clean Telegram message with emojis."""
        
        response = self.openai.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": prompt}],
            max_tokens=300,
            temperature=0.4
        )
        
        return {
            'symbol': tech_data['symbol'],
            'signal_text': response.choices[0].message.content,
            'score': tech_data['score'],
            'timestamp': datetime.now().isoformat()
        }
    
    def scan_all_pairs(self) -> list[dict]:
        """Scan all tracked pairs and return high-confidence signals"""
        signals = []
        
        for symbol in self.tracked_pairs:
            try:
                tech_data = self.calculate_technical_score(symbol)
                
                # Only generate signal if score is significant
                if abs(tech_data['score']) >= 0.4:
                    signal = self.generate_ai_signal(tech_data)
                    signals.append(signal)
                    
            except Exception as e:
                print(f"Error processing {symbol}: {e}")
        
        # Sort by confidence score
        return sorted(signals, key=lambda x: abs(x['score']), reverse=True)

Step 2: Telegram Bot for Signal Delivery

import telegram
import asyncio
import os

class SignalDeliveryBot:
    def __init__(self):
        self.bot = telegram.Bot(token=os.environ['TELEGRAM_BOT_TOKEN'])
        self.free_channel_id = os.environ['FREE_CHANNEL_ID']
        self.paid_channel_id = os.environ['PAID_CHANNEL_ID']
    
    async def send_signal(self, signal: dict):
        """Send signal to paid channel immediately, free channel with delay"""
        
        # Format premium signal with full details
        premium_msg = f"""
๐Ÿš€ **AI SIGNAL โ€” {signal['symbol']}**

{signal['signal_text']}

โฐ Signal Time: {datetime.now().strftime('%H:%M UTC')}
๐Ÿ“Š Confidence Score: {abs(signal['score'])*100:.0f}/100
---
_โš ๏ธ Not financial advice. Always use proper risk management._
"""
        
        # Free channel: send teaser, delayed 1 hour
        teaser_msg = f"""
โšก New signal for **{signal['symbol']}** โ€” Direction detected

๐Ÿ”’ Full entry/exit/stop details available in Premium Channel.

๐Ÿ‘‡ Join premium for instant signals: t.me/your_premium_channel
"""
        
        # Send to paid channel immediately
        await self.bot.send_message(
            chat_id=self.paid_channel_id,
            text=premium_msg,
            parse_mode='Markdown'
        )
        
        # Schedule free channel post for 1 hour later
        await asyncio.sleep(3600)
        await self.bot.send_message(
            chat_id=self.free_channel_id,
            text=teaser_msg,
            parse_mode='Markdown'
        )

Step 3: Payment Integration

For subscription management, use Telegram Stars (native Telegram payments) or a third-party service:

from telegram.ext import Application, CommandHandler, PreCheckoutQueryHandler

async def subscribe_command(update, context):
    """Handle /subscribe command"""
    await context.bot.send_invoice(
        chat_id=update.effective_chat.id,
        title="Premium Signals - Monthly",
        description="AI-generated crypto trading signals. 5-10 signals per week.",
        payload="premium_monthly",
        currency="USD",
        prices=[{"label": "Monthly Access", "amount": 4900}],  # $49.00
    )

async def precheckout_handler(update, context):
    await update.pre_checkout_query.answer(ok=True)

async def payment_handler(update, context):
    """User paid - add to premium channel"""
    if update.message.successful_payment:
        user_id = update.effective_user.id
        # Create invite link for paid channel
        invite = await context.bot.create_chat_invite_link(
            chat_id=PAID_CHANNEL_ID,
            member_limit=1,
            expire_date=datetime.now() + timedelta(days=31)
        )
        await update.message.reply_text(
            f"โœ… Payment successful! Join premium here (1-time link): {invite.invite_link}"
        )

What Makes a Good Signal Service

  1. Transparent track record: Post your win rate and P&L publicly. Real results build trust.
  2. Risk management: Always include stop losses. Channels that only post wins and ignore losses lose subscribers fast.
  3. Consistent volume: 5-10 quality signals per week. Over-signaling destroys P&L for followers.
  4. Education content: Mix educational posts with signals. This builds community and reduces churn.

A well-run signal service with 200 paying subscribers at $49/month generates $9,800/month in recurring revenue โ€” with AI doing most of the analysis work.

Related Articles