DEV Community

Cover image for Automating Crypto Trades with TradingView Webhooks and Custom Bots
Fxm Brand
Fxm Brand

Posted on

Automating Crypto Trades with TradingView Webhooks and Custom Bots

_
Complete developer guide to connecting TradingView alerts to your own trading bot via webhooks. Covers Pine Script alerts, secure webhook receivers, order execution, risk checks, and production deployment.
tags: python, tradingview, crypto, tradingbots, webhooks, fastapi_

TradingView is still one of the best charting and signal platforms available. Many developers already have working Pine Script strategies or indicators they trust. The missing piece is reliable, automated execution.

This guide shows you how to turn TradingView alerts into real orders using webhooks and a custom bot. We’ll cover:

  • Writing alerts that send structured data
  • Building a secure webhook receiver (FastAPI)
  • Validating and parsing incoming signals
  • Connecting the signals to exchange execution (CCXT for CEX, or your Solana executor)
  • Adding risk checks before any order is sent
  • Handling failures, retries, and logging
  • Deploying the system so it stays online

The result is a clean separation: TradingView handles detection and charting, your bot handles risk and execution.

Note for memecoin traders: TradingView works well for larger-cap pairs and some Solana tokens that have reliable data feeds. For pure low-cap memecoin sniping and on-chain filters, you will still want dedicated listeners. If you need a complete memecoin-focused strategy framework, see https://selar.com/60lw5u0623. This article focuses on the TradingView → bot bridge that many hybrid systems use.


Why TradingView + Webhooks?

Advantages:

  • Excellent charting and backtesting tools
  • Large library of community scripts
  • Alerts can fire on any condition you can code in Pine
  • Webhooks let you push signals to any server you control
  • No need to poll TradingView APIs constantly

Limitations:

  • Alert frequency is limited by your TradingView plan
  • Data quality on very new or low-liquidity memecoins can be poor
  • You are still responsible for execution quality, slippage, and risk

This architecture is ideal when you already have a Pine Script edge and want reliable automation without rewriting everything in Python.


High-Level Architecture

TradingView Alert (Pine Script)
        ↓  HTTPS POST
Your Webhook Receiver (FastAPI / Flask)
        ↓  Validate + Parse
Risk Manager
        ↓  Approved
Execution Layer (CCXT or Solana bot)
        ↓
Exchange / DEX
        ↓
Logging + Telegram Alerts
Enter fullscreen mode Exit fullscreen mode

Keeping these layers separate makes the system easier to debug and improve.


Step 1: Creating Useful Alerts in Pine Script

A good alert message is structured and machine-readable. Avoid free-text messages when possible.

Example alert message format (JSON-like):

{"strategy":"momentum_v2","symbol":"BTCUSDT","side":"buy","price":67250.5,"timeframe":"15","key":"YOUR_SECRET"}
Enter fullscreen mode Exit fullscreen mode

In Pine Script you can build this with alert() or the newer alert_message parameter in strategy orders.

Simple example inside a strategy:

//@version=5
strategy("Webhook Example", overlay=true)

longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
    strategy.entry("Long", strategy.long)
    alert('{"strategy":"sma_cross","symbol":"' + syminfo.ticker + '","side":"buy","key":"YOUR_SECRET"}', alert.freq_once_per_bar)
Enter fullscreen mode Exit fullscreen mode

For indicators (not strategies) you can use:

if longCondition
    alert('{"side":"buy","symbol":"' + syminfo.ticker + '","key":"YOUR_SECRET"}')
Enter fullscreen mode Exit fullscreen mode

Tips:

  • Always include a secret key so your server can reject unauthorized requests
  • Include symbol, side, and any extra context (timeframe, stop level, strategy name)
  • Test alerts first with a service like webhook.site before pointing them at your real server
  • Remember TradingView has rate limits on how many alerts can fire

Step 2: Building the Webhook Receiver

We will use FastAPI because it is fast, modern, and easy to secure.

pip install fastapi uvicorn python-dotenv httpx loguru tenacity ccxt
Enter fullscreen mode Exit fullscreen mode

Basic receiver:

# main.py
from fastapi import FastAPI, Request, HTTPException, Header
from pydantic import BaseModel
import os
from dotenv import load_dotenv
from loguru import logger
import hmac
import hashlib

load_dotenv()

app = FastAPI(title="TradingView Webhook Bot")

WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")
ALLOWED_IPS = os.getenv("ALLOWED_IPS", "").split(",")  # optional

class AlertPayload(BaseModel):
    strategy: str | None = None
    symbol: str
    side: str
    price: float | None = None
    timeframe: str | None = None
    key: str

@app.post("/webhook")
async def tradingview_webhook(request: Request, payload: AlertPayload):
    # 1. Basic secret check
    if payload.key != WEBHOOK_SECRET:
        logger.warning("Invalid secret key received")
        raise HTTPException(status_code=403, detail="Forbidden")

    # 2. Optional IP allowlist (TradingView publishes their IPs)
    client_ip = request.client.host
    if ALLOWED_IPS and client_ip not in ALLOWED_IPS:
        logger.warning(f"Request from non-allowed IP: {client_ip}")
        raise HTTPException(status_code=403, detail="Forbidden")

    logger.info(f"Received alert: {payload.dict()}")

    # 3. Pass to risk + execution
    result = await process_alert(payload)
    return {"status": "ok", "result": result}
Enter fullscreen mode Exit fullscreen mode

Run it:

uvicorn main:app --host 0.0.0.0 --port 8000
Enter fullscreen mode Exit fullscreen mode

For production you will put this behind Nginx or Caddy with HTTPS (Let’s Encrypt).


Step 3: Processing the Alert & Risk Checks

Never execute blindly. Always run risk checks first.

# risk.py
from loguru import logger

MAX_POSITIONS = 3
MAX_RISK_PER_TRADE = 0.02  # 2% of equity
DAILY_LOSS_LIMIT = 0.05

class RiskManager:
    def __init__(self):
        self.open_positions = 0
        self.daily_pnl = 0.0

    def approve(self, symbol: str, side: str, size: float) -> bool:
        if self.open_positions >= MAX_POSITIONS:
            logger.warning("Max open positions reached")
            return False
        if self.daily_pnl <= -DAILY_LOSS_LIMIT:
            logger.warning("Daily loss limit hit — trading paused")
            return False
        # Add more checks: symbol whitelist, max size, etc.
        return True
Enter fullscreen mode Exit fullscreen mode

In the main flow:

async def process_alert(payload: AlertPayload):
    # Normalize symbol (TradingView uses BTCUSDT, CCXT often wants BTC/USDT)
    symbol = normalize_symbol(payload.symbol)

    # Calculate size (example)
    size = calculate_position_size(symbol)

    risk = RiskManager()
    if not risk.approve(symbol, payload.side, size):
        return {"executed": False, "reason": "risk_rejected"}

    # Execute
    order = await execute_order(symbol, payload.side, size)
    return {"executed": True, "order": order}
Enter fullscreen mode Exit fullscreen mode

Step 4: Execution Layer

You can reuse the CCXT infrastructure from the earlier production bot article, or call your Solana executor.

Simple CCXT example:

import ccxt.async_support as ccxt
from loguru import logger

exchange = ccxt.binance({
    "apiKey": os.getenv("BINANCE_KEY"),
    "secret": os.getenv("BINANCE_SECRET"),
    "enableRateLimit": True,
    "options": {"defaultType": "future"}  # or "spot"
})

async def execute_order(symbol: str, side: str, amount: float):
    try:
        order = await exchange.create_order(
            symbol=symbol,
            type="market",
            side=side.lower(),
            amount=amount
        )
        logger.success(f"Order placed: {order['id']}")
        return order
    except Exception as e:
        logger.error(f"Execution failed: {e}")
        raise
Enter fullscreen mode Exit fullscreen mode

For Solana memecoins you would call your Jupiter or Raydium execution function instead.

Always:

  • Log the full order response
  • Send a Telegram notification on fill or failure
  • Update your internal position tracker

Step 5: Security Best Practices

Webhook endpoints are public. Protect them properly:

  1. Shared secret in the alert message (as shown)
  2. IP allowlisting (TradingView publishes their outbound IPs)
  3. HTTPS only
  4. Rate limiting on your endpoint
  5. Request signature (more advanced — HMAC of the body)
  6. Idempotency keys so the same alert cannot trigger twice
  7. Run the receiver with minimal privileges

Example simple rate limiter with FastAPI middleware or a library like slowapi.


Step 6: Making It Production-Ready

Logging & Alerts

from loguru import logger
import sys

logger.add("logs/webhook_{time}.log", rotation="20 MB", retention="10 days")
logger.add(sys.stdout, level="INFO")
Enter fullscreen mode Exit fullscreen mode

Send critical events to Telegram:

async def notify(message: str):
    # simple httpx POST to Telegram Bot API
    pass
Enter fullscreen mode Exit fullscreen mode

Error Handling & Retries

Use tenacity for transient exchange errors. Catch specific exceptions (rate limits, insufficient funds, network issues) and decide whether to retry or alert.

Position Tracking

Keep a lightweight local state (Redis or even a SQLite file) of open positions so the bot knows what it currently holds. This prevents duplicate entries and helps with exit logic.

Health Checks

Add a simple /health endpoint that returns 200 if the bot is alive and can reach the exchange.


Deployment

Recommended path:

  1. VPS (Hetzner, DigitalOcean, etc.)
  2. Docker + Docker Compose
  3. Caddy or Nginx for automatic HTTPS
  4. Systemd or Docker restart policies

Example docker-compose.yml snippet:

services:
  webhook-bot:
    build: .
    ports:
      - "8000:8000"
    env_file: .env
    restart: unless-stopped
    volumes:
      - ./logs:/app/logs
Enter fullscreen mode Exit fullscreen mode

Point your TradingView alert URL to:

https://yourdomain.com/webhook
Enter fullscreen mode Exit fullscreen mode

Test thoroughly with the TradingView “Test” button and with small size live orders.


Advanced Patterns

Once the basic bridge works you can add:

  • Multiple strategy support (different Pine scripts → different risk parameters)
  • Exit alerts (separate webhook messages for closing positions)
  • Dynamic position sizing based on TradingView-sent stop distance
  • Paper-trading mode that logs signals without sending orders
  • Multi-exchange routing (send BTC signals to Binance, SOL signals to your Solana bot)
  • Confirmation candles or secondary filters before execution

Common Pitfalls

  • Alert message format breaks when you change Pine Script
  • Forgetting to normalize symbols (BTCUSDT vs BTC/USDT)
  • No secret → anyone can spam your endpoint
  • No risk checks → one bad alert can open oversized positions
  • TradingView plan limits causing missed alerts
  • Not handling partial fills or order rejections cleanly
  • Running without HTTPS or proper authentication

When to Use This vs Pure On-Chain Bots

TradingView webhooks shine when:

  • You trade liquid pairs with good TradingView data
  • Your edge is chart/pattern/indicator based
  • You already have working Pine Scripts

Pure on-chain / sniper bots are better when:

  • You focus on brand-new memecoins
  • You need block-level speed and custom filters
  • Social + on-chain data is more important than classical technical analysis

Many serious traders run both systems side by side.

For a dedicated memecoin strategy that already includes filters, scoring, and risk rules, the framework at https://selar.com/60lw5u0623 remains the recommended starting point.


Final Checklist

  • [ ] Pine Script sends clean, structured JSON messages
  • [ ] Webhook secret is validated on every request
  • [ ] HTTPS is enabled
  • [ ] Risk manager runs before any order
  • [ ] Execution errors are caught and alerted
  • [ ] Positions are tracked
  • [ ] Logs and Telegram notifications are working
  • [ ] System restarts automatically on failure
  • [ ] You have tested with small size

You now have a complete, production-oriented bridge between TradingView and your own execution engine. This pattern scales cleanly and keeps your strategy logic where it is easiest to maintain (Pine) while giving you full control over risk and order management.

Build carefully, size conservatively, and keep improving the risk layer — that is usually where the real durability comes from.


Related articles in this series

  • Production-ready CCXT bot
  • Solana memecoin sniper architecture
  • Memecoin strategies: hype + on-chain signals

Resource


Enter fullscreen mode Exit fullscreen mode

Top comments (0)