TickAtlas
Bot ~20 min setup

Discord Bot Integration

Bring live market data to your Discord server. Slash commands for indicators and quotes, rich embeds with color-coded signals, and scheduled hourly market updates.

Prerequisites

Choose Python (discord.py) or JavaScript (discord.js):

bash
# Python
pip install discord.py requests

# JavaScript
npm install discord.js
  1. Create a bot at discord.com/developers
  2. Enable the applications.commands scope
  3. Invite the bot to your server with slash command permissions

Python Bot (discord.py)

python
import os
import discord
from discord import app_commands
from discord.ext import commands, tasks
import requests

CLAW_API_KEY = os.environ["CLAW_API_KEY"]
DISCORD_TOKEN = os.environ["DISCORD_BOT_TOKEN"]
CLAW_BASE = "https://tickatlas.com/v1"

intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)

def claw_request(endpoint: str, params: dict) -> dict:
    resp = requests.get(
        f"{CLAW_BASE}/{endpoint}",
        headers={"X-API-Key": CLAW_API_KEY},
        params=params,
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()

@bot.event
async def on_ready():
    await bot.tree.sync()
    hourly_update.start()
    print(f"Bot ready: {bot.user}")

@bot.tree.command(name="rsi", description="Get RSI for a trading symbol")
@app_commands.describe(symbol="Symbol (e.g. EURUSD)", timeframe="Timeframe (default: H1)")
async def rsi(interaction: discord.Interaction, symbol: str, timeframe: str = "H1"):
    await interaction.response.defer()
    try:
        data = claw_request("indicator", {
            "symbol": symbol.upper(), "indicator": "RSI_14", "timeframe": timeframe.upper(),
        })
        color = discord.Color.green() if data["value"] < 40 else (
            discord.Color.red() if data["value"] > 60 else discord.Color.gold()
        )
        embed = discord.Embed(
            title=f"RSI(14) for {data['symbol']}",
            color=color,
        )
        embed.add_field(name="Value", value=f"**{data['value']:.2f}**", inline=True)
        embed.add_field(name="Signal", value=data["signal"].capitalize(), inline=True)
        embed.add_field(name="Timeframe", value=timeframe.upper(), inline=True)
        embed.add_field(name="Close Price", value=str(data["ohlc"]["close"]), inline=True)
        embed.set_footer(text=f"Data age: {data['metadata']['data_age_seconds']}s")
        await interaction.followup.send(embed=embed)
    except Exception as e:
        await interaction.followup.send(f"Error: {e}")

@bot.tree.command(name="summary", description="Get AI market summary for a symbol")
@app_commands.describe(symbol="Symbol", timeframe="Timeframe (default: H1)")
async def summary(interaction: discord.Interaction, symbol: str, timeframe: str = "H1"):
    await interaction.response.defer()
    try:
        data = claw_request("summary", {
            "symbol": symbol.upper(), "timeframe": timeframe.upper(),
        })
        bias_colors = {"bullish": discord.Color.green(), "bearish": discord.Color.red(), "neutral": discord.Color.gold()}
        embed = discord.Embed(
            title=f"AI Summary: {data['symbol']} ({timeframe.upper()})",
            description=data["narrative"],
            color=bias_colors.get(data["bias"], discord.Color.default()),
        )
        embed.add_field(name="Bias", value=f"**{data['bias'].upper()}**", inline=True)
        embed.add_field(name="Confidence", value=f"**{data['confidence']}%**", inline=True)
        await interaction.followup.send(embed=embed)
    except Exception as e:
        await interaction.followup.send(f"Error: {e}")

bot.run(DISCORD_TOKEN)

Scheduled Channel Updates

Post automatic market summaries to a designated channel every hour:

python
MARKET_CHANNEL_ID = 123456789012345678  # Your channel ID

@tasks.loop(hours=1)
async def hourly_update():
    channel = bot.get_channel(MARKET_CHANNEL_ID)
    if not channel:
        return

    symbols = ["EURUSD", "GBPUSD", "XAUUSD", "BTCUSD"]
    embed = discord.Embed(
        title="Hourly Market Update",
        color=discord.Color.blue(),
        timestamp=discord.utils.utcnow(),
    )

    for sym in symbols:
        try:
            data = claw_request("indicator", {
                "symbol": sym, "indicator": "RSI_14", "timeframe": "H1",
            })
            summary_data = claw_request("summary", {"symbol": sym, "timeframe": "H1"})
            embed.add_field(
                name=sym,
                value=(
                    f"RSI: **{data['value']:.1f}** ({data['signal']})\n"
                    f"Bias: **{summary_data['bias']}** ({summary_data['confidence']}%)"
                ),
                inline=True,
            )
        except Exception:
            embed.add_field(name=sym, value="Data unavailable", inline=True)

    embed.set_footer(text="Powered by TickAtlas API")
    await channel.send(embed=embed)

@hourly_update.before_loop
async def before_hourly():
    await bot.wait_until_ready()

Slash Commands

CommandDescription
/rsi EURUSD H1RSI value with colored embed
/summary XAUUSD H4AI market analysis embed
/quote GBPUSDLive bid/ask/spread
/screener RSI_14 30Find oversold instruments