A Discord bot for posting and tracking stock trade alerts across servers. Supports day trades, swing trades, and generic updates — with confirmation previews, message forwarding, fully customizable embed appearance, and production-grade logging and reliability.
- Trade alerts — structured embeds for day trades and swing trades with entry, target, stop loss, and more
- Confirmation preview — review an alert before it goes live; cancel if you spot a typo
- Edit posted alerts — update any field on a trade that's already been posted
- Message forwarding — automatically forward messages from source channels to target channels as formatted embeds
- Customizable embeds — color, footer, thumbnail, timestamp, and more configurable per server
- Per-server config — each server has its own target channel, source channels, alert role, and embed appearance
- DM receipts — optionally receive a DM confirmation whenever you post an alert
- Access control — only the bot owner and configured trusted users can use commands
- SQLite storage — all settings and trade history stored in a local database
- Rotating file logs — timestamped logs written to
logs/bot.logwith automatic rotation - Auto-reconnect — database connection health-checked and restored automatically if lost
- Graceful shutdown — handles SIGTERM/SIGINT cleanly, closing the database before exit
- Python 3.13+
- discord.py 2.5+
- aiosqlite 0.22+
- python-dotenv 1.0+
Install all dependencies:
pip install -r requirements.txt1. Create a Discord application and bot
- Go to the Discord Developer Portal
- Create a new application → Bot tab → add a bot
- Under Privileged Gateway Intents, enable Message Content Intent
- Copy your bot token
2. Configure your environment
Copy .env.example to .env and fill in your values:
cp .env.example .envDISCORD_BOT_TOKEN=your_token_here
BOT_NAME=TradeBot
TRUSTED_USER_IDS=123456789012345678,987654321098765432All settings are optional except DISCORD_BOT_TOKEN. See .env.example for the full list of options.
To find a user ID for TRUSTED_USER_IDS: enable Developer Mode in Discord settings, then right-click any user → Copy User ID.
3. Invite the bot to your server
In the Developer Portal → OAuth2 → URL Generator:
- Scopes:
bot,applications.commands - Bot Permissions:
Send Messages,Embed Links,Attach Files,Read Message History,Manage Messages
4. Run the bot
python3.13 bot.pyThe database (bot.db) and log directory (logs/) are created automatically on first run.
| Command | Description |
|---|---|
/daytrade |
Post a day trade alert with entry, target, stop loss, and optional size/notes |
/swingtrade |
Post a swing trade alert with optional timeframe and risk/reward ratio |
/update |
Post a generic stock update (ticker, action, price) |
/edittrade |
Edit a previously posted trade alert by message ID |
All trade commands show an ephemeral preview with Confirm / Cancel buttons before posting publicly — so typos never go live.
Getting a message ID for /edittrade:
Enable Developer Mode in Discord settings → right-click the posted alert → Copy Message ID.
| Command | Description |
|---|---|
/settarget |
Set the default channel where alerts are posted |
/setsource |
Add a channel to monitor for message forwarding |
/setadvancedsource |
Bind a source channel to a specific target (overrides the default) |
/setrole |
Set a role to @mention when alerts are posted |
/setid |
Set a source channel, target channel, or role by raw ID |
/removesource |
Remove a source channel |
/removetarget |
Remove the default target channel |
/removeid |
Remove a source or target channel by raw ID |
| Command | Description |
|---|---|
/embedsettings |
Configure embed appearance — run with no arguments to see current values |
/embedhelp |
Full in-Discord guide explaining every customization option with examples |
/toggledm |
Toggle DM receipts when you post a trade alert |
/embedsettings parameters:
| Parameter | Description | Example |
|---|---|---|
color |
Left-border color of every embed | #FF5733 — type clear to reset |
footer |
Text at the bottom of every embed | My Trading Server — type clear to reset |
footer_image |
Small icon shown next to the footer text | direct image URL — type clear to remove |
thumbnail |
Image shown in the top-right corner of every embed | direct image URL — type clear to remove |
timestamp |
Show the post time at the bottom of each embed | True / False |
convert_to_embed |
Forward messages as rich embeds vs plain text | True / False |
You can set multiple options in a single command:
/embedsettings color:#FF5733 footer:My Server thumbnail:https://example.com/logo.png
Run /embedhelp in Discord for a full guide with examples for every setting.
| Command | Description |
|---|---|
/settings |
Show all current settings for this server |
/showsources |
List all configured source channels and their targets |
/showservers |
List all servers the bot is in (owner only) |
/ping |
Check bot latency and confirm the bot is responsive |
When a message is posted in a source channel, the bot automatically forwards it to the target channel as a formatted embed — including the author's name, avatar, timestamp, and any attachments.
- Use
/setsourceto add a source channel (forwards to the default target) - Use
/setadvancedsourceto bind a specific source → target pair - Use
/embedsettings convert_to_embed:Falseto forward as plain text instead - Multiple attachments are all forwarded, not just the first
- Forwarding errors (e.g. missing permissions) are logged and do not crash the bot
Logs are written to logs/bot.log automatically on startup. The file rotates at 5 MB and keeps 3 backups (bot.log.1, bot.log.2, bot.log.3).
Log format:
2026-04-17 14:32:01 [INFO ] bot: Connected as TradeBot — in 3 server(s)
2026-04-17 14:32:05 [INFO ] cogs.trades: Trade posted: daytrade AAPL (msg 123456) by user in guild 789
2026-04-17 14:35:12 [WARNING ] cogs.config: Missing permissions to forward message to #alerts in guild 789
2026-04-17 14:40:00 [WARNING ] database: Database connection stale — reconnecting
Logs are also printed to the console while the bot is running.
bot.py — Entry point; loads cogs, initialises database, handles shutdown
config.py — All configuration loaded from environment variables / .env
database.py — SQLite schema, migrations, query functions, connection resilience
helpers.py — Auth helpers, embed builders, TradeConfirmView
logger.py — Logging setup (rotating file + console handlers)
cogs/
config.py — Channel/role setup, embed settings, message forwarding
trades.py — Trade alert commands (daytrade, swingtrade, update, edittrade)
info.py — Info/display commands (settings, showservers, showsources, ping)
.env.example — Template for environment configuration
requirements.txt — Python dependencies
CHANGELOG.md — Version history
CONTRIBUTING.md — Contribution guidelines
.github/
ISSUE_TEMPLATE/ — Bug report and feature request templates
bot.db — SQLite database (created on first run, do not commit)
logs/ — Log files (created on first run, do not commit)
By default only the bot owner (the account that owns the application in the Developer Portal) can use commands.
To allow additional users, add their Discord IDs to TRUSTED_USER_IDS in your .env file:
TRUSTED_USER_IDS=123456789012345678,987654321098765432Set ENABLE_TRUSTED_USERS=false in .env to restrict all commands to the bot owner only.
Run the bot directly:
python3.13 bot.pyOn a VPS (DigitalOcean, Linode, etc.) use systemd, screen, or tmux to keep it running in the background. The bot handles SIGTERM gracefully, so systemd restarts work cleanly.
These platforms require a Procfile in the project root. Create a file named Procfile (no extension) with:
worker: python3.13 bot.py
Use worker not web — Discord bots don't listen on a port, and a web dyno will fail the platform's health check.
On Heroku, set environment variables as config vars instead of a .env file:
heroku config:set DISCORD_BOT_TOKEN='your_token_here'
heroku config:set BOT_NAME='TradeBot'- Never commit your bot token. Use
.envor platform config vars only. .env,bot.db, andlogs/are already listed in.gitignore— do not remove them.- Rotate your token immediately at the Developer Portal if it is ever exposed in source code or git history.