A Docker-based Bitcoin Dollar Cost Averaging (DCA) bot that automatically purchases Bitcoin on a daily schedule via cryptocurrency exchanges and sends notifications through Telegram.
NOTE: This bot is built with CCXT to support multiple exchanges, but it has been fully tested only with OKX. When using other exchanges, the bot will attempt to work but may have unexpected behavior. Contributions to improve support for other exchanges are welcome!
- Multi-Exchange Support: Built with CCXT to support multiple exchanges (currently fully tested with OKX)
- Automated DCA: Buy a configurable amount of Bitcoin daily at a specified UTC time
- Telegram Integration: Receive notifications and check stats via Telegram bot
- MongoDB Integration: Track trade history and performance
- Balance Tracking: Monitor USDT balance and days left at current rate
- Security Features: Transaction limits, exchange subaccount isolation, dry-run mode
- Docker Support: Easy deployment and management
- Detailed Stats: View your DCA performance statistics
- Portfolio Tracking: Track existing BTC holdings alongside DCA purchases
- Docker and Docker Compose
- OKX API credentials
- Telegram Bot Token
- MongoDB Atlas account (free tier)
-
Clone the repository:
git clone https://github.com/yourusername/dca-bot.git cd dca-bot
-
Create your
.env
file:make init-env
-
Edit the
.env
file with your credentials. -
Build and start the bot:
make build make start
-
View logs:
make logs
- Log in to your OKX account.
- Go to "User Center" > "API Management".
- Click "Create API" and follow the prompts.
- For security, set IP restrictions to only allow your server's IP.
- Enable "Trade" permission and disable all others.
- Save your API Key, Secret Key, and Passphrase.
For enhanced security, create a dedicated subaccount for the DCA bot:
- Go to "Assets" > "Subaccounts".
- Click "Create Subaccount" and follow the prompts.
- Once created, transfer only the USDT you want to use for DCA.
- Create a dedicated API key for this subaccount following the steps above.
- Message @BotFather on Telegram.
- Send
/newbot
and follow the instructions to create a new bot. - You'll receive a token for your bot. Save this for your
.env
file. - Message @userinfobot to get your user ID.
- Create a free account on MongoDB Atlas.
- Create a new cluster (the free tier is sufficient).
- Set up a database user and password.
- Configure network access (allow access from anywhere or your specific IP).
- Get your connection string and add it to your
.env
file.
Detailed guide:
- Sign up or log in at MongoDB Atlas.
- Click "Create" to create a new project.
- Click "Build a Database" and select the FREE tier.
- Choose your preferred cloud provider and region.
- Name your cluster (e.g., "dca-bot").
- Click "Create Cluster" (it may take a few minutes to deploy).
- In the "Security" section:
- Click "Database Access" > "Add New Database User".
- Create a username and password (save these).
- Set privileges to "Read and Write to Any Database".
- In "Network Access":
- Click "Add IP Address".
- For development, you can choose "Allow Access from Anywhere" or add your specific IP.
- Once your cluster is deployed, click "Connect":
- Select "Connect your application".
- Copy the connection string.
- Replace
<username>
,<password>
, and<dbname>
in the string with your details.
Variable | Description | Example |
---|---|---|
EXCHANGE_ID |
Exchange to use (via CCXT) | okx (default, only fully tested exchange) |
OKX_API_KEY |
OKX API key | a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6 |
OKX_API_SECRET |
OKX API secret | YOUR_SECRET_KEY |
OKX_API_PASSPHRASE |
OKX API passphrase | your_passphrase |
OKX_SUBACCOUNT_NAME |
OKX subaccount name | dca_bot |
TELEGRAM_BOT_TOKEN |
Telegram bot token | 123456789:ABCdefGhIJKlmnOPQRstUVwxYZ |
TELEGRAM_USER_ID |
Your Telegram user ID | 123456789 |
DCA_AMOUNT_USD |
USD amount to buy daily | 100.0 |
DCA_PERIOD |
DCA execution period | 1_day , 1_minute or 1_hour |
DCA_TIME_UTC |
Time to execute DCA (UTC) | 18:00 |
PORTFOLIO_INITIAL_BTC |
Initial BTC holdings | 0.5 |
PORTFOLIO_INITIAL_AVG_PRICE |
Average price of initial BTC | 40000.0 |
MONGODB_URI |
MongoDB connection string | mongodb+srv://... |
DCA_START_TIME_UTC |
Time to start DCA jobs (HH:MM UTC) or 'now' | 18:00 or now |
SEND_TRADE_NOTIFICATIONS |
Send notification after each trade? | true or false |
REPORT_TIMES_UTC |
Comma-separated HH:MM UTC times for reports (optional) | 09:00,21:00 |
REPORT_LOOKBACK_HOURS |
Lookback period for reports (optional) | 12 |
DRY_RUN |
Test mode without real trades | true or false |
LOG_LEVEL |
Logging verbosity | INFO |
RUN_IMMEDIATELY |
Run DCA on startup | true or false |
/start
- Show welcome message and current stats/stats
- Display detailed DCA statistics/balance
- Show current balance and days left
Use the provided Makefile for common operations:
make help # Show all available commands
make build # Build the Docker image
make start # Start the container
make stop # Stop the container
make logs # View container logs
make restart # Restart the container
make status # Check container status
make clean # Stop and remove container
make clear-db # Clear the database by dropping trades collection
make run-local # Run application locally
make init-env # Create .env file from example
make dry-run # Run in dry-run mode
The DCA bot includes production tests built with pytest to verify functionality in your environment.
The test suite performs three key checks:
- Trading Test: Purchases a small amount of Bitcoin ($1) and immediately sells it back
- Telegram Test: Sends a test notification to your configured Telegram user
- Database Test: Verifies MongoDB connection, creates a test collection, and performs basic operations
Run the tests in Docker with:
make test
This will execute all tests using your production credentials. Since it uses real accounts, it will make a small ($1) actual purchase and sale of Bitcoin.
If you want to avoid making actual trades, you can set DRY_RUN=true
in your .env file before running the tests:
# Edit .env to set DRY_RUN=true
make test
The tests are built using:
- pytest: Industry-standard Python testing framework
- pytest-asyncio: For testing asynchronous Telegram functionality
- Assertions: Clear test conditions with descriptive messages
- Automatic skipping: Trade tests are skipped in dry-run mode
This provides a robust verification of all system components.
This bot handles financial operations, so security is critical. Here are the security measures implemented:
- OKX Subaccount: Using a dedicated subaccount isolates funds from your main account.
- Transaction Validation: All transaction amounts are validated to prevent excessive purchases.
- Limited API Permissions: Only enable the "Trade" permission, nothing else.
- IP Restrictions: Configure OKX API to only accept requests from your server IP.
- Dry Run Mode: Test the bot without making actual trades.
- Single User Access: Only your Telegram user ID can interact with the bot.
- Isolated Docker Environment: Containerization provides additional security.
- API Key Compromise: If your API key is stolen, an attacker could trade on your behalf. Mitigate by using a subaccount with limited funds.
- Server Compromise: If your server is compromised, your keys could be exposed. Regularly update your server and follow security best practices.
- Bugs: Software bugs could potentially lead to incorrect trades. Start with small DCA amounts and monitor closely.
- Start Small: Begin with small DCA amounts until you're confident in the setup.
- Enable Dry Run: Test with
DRY_RUN=true
before making real trades. - Regular Monitoring: Check your Telegram notifications and OKX account regularly.
- Fund Management: Only deposit enough USDT for a few weeks of DCA at a time.
- Bot not responding: Check Docker logs with
make logs
- No trades executed: Verify your OKX API credentials and permissions
- MongoDB connection issues: Check your MongoDB Atlas connection string and network settings
- Tests failing: Ensure you've set up the correct credentials in
.env.test
- Docker test issues: Make sure Docker and Docker Compose are installed and running properly
MIT License
- CCXT for exchange integration
- python-telegram-bot for Telegram bot functionality
- pymongo for MongoDB integration
The bot is built using CCXT, which provides a unified API for trading across many cryptocurrency exchanges. Currently, the bot has been fully tested with:
- OKX: All features fully tested and supported
Other exchanges supported by CCXT should work with minimal modifications, but they haven't been fully tested. The application architecture is designed to make adding support for other exchanges straightforward.
To use another exchange supported by CCXT:
- Set
EXCHANGE_ID
in your.env
file to the exchange identifier (e.g.,binance
,coinbase
,kucoin
) - Provide the appropriate API credentials for that exchange in your
.env
file - Note that subaccount support and specific trading parameters may vary between exchanges
If you encounter issues with a specific exchange, contributions to improve support are welcome.
Here are some common configuration patterns:
1. Daily DCA with Immediate Notification (No Periodic Reports)
- Buy $10 every day at 09:00 UTC.
- Get a Telegram notification immediately after each purchase.
- No separate periodic summary reports.
DCA_AMOUNT_USD=10.0
DCA_PERIOD=1_day
DCA_START_TIME_UTC=09:00
SEND_TRADE_NOTIFICATIONS=true
REPORT_TIMES_UTC=
REPORT_LOOKBACK_HOURS=12
2. Hourly DCA with Periodic Reports (No Immediate Notifications)
- Buy $5 every hour, starting immediately on bot startup.
- Do not receive a notification after each individual purchase.
- Receive a summary report every 12 hours (at 08:00 and 20:00 UTC) covering the trades from the previous 12 hours.
DCA_AMOUNT_USD=5.0
DCA_PERIOD=1_hour
DCA_START_TIME_UTC=now
SEND_TRADE_NOTIFICATIONS=false
REPORT_TIMES_UTC=08:00,20:00
REPORT_LOOKBACK_HOURS=12
3. Minute-by-Minute DCA with Both Immediate Notifications and Reports
- Buy $1 every minute, starting immediately.
- Receive a notification after every single purchase (can be noisy!).
- Receive a summary report every 6 hours.
DCA_AMOUNT_USD=1.0
DCA_PERIOD=1_minute
DCA_START_TIME_UTC=now
SEND_TRADE_NOTIFICATIONS=true
REPORT_TIMES_UTC=00:00,06:00,12:00,18:00
REPORT_LOOKBACK_HOURS=6