An automated Python-based trading system for Knock-out warrants (Turbos) on Saxo Bank, executing trades via webhook signals.
This is a personal learning project and not production-ready software.
Risk Warning: WATA can lose all your money due to:
- Insufficient code testing
- Limited security measures
- Lack of fail-safe mechanisms
- No comprehensive monitoring included
- Absence of fail-over systems
- Limited user experience
This software is provided "as is" without warranty. The authors accept no liability for any damages arising from its use.
WATA (Warrants Automated Trading Assistant) is an algorithmic trading system compagnon, designed for automated execution of Knock-out warrants (Turbos) on Saxo Bank. It serves as a reliable bridge between trading signals and actual market execution, offering several key benefits:
- Automated Execution: Eliminates emotional bias and human error by executing trades based on predefined rules and signals (from TradingView, for example)
- Risk Management: Implements systematic position monitoring with stop-loss and take-profit mechanisms
- Performance Tracking: Provides comprehensive analytics and reporting for trade analysis
- Real-time Monitoring: Delivers instant notifications via Telegram for trade execution and system status
- Scalability: Built on a microservice architecture for reliable and maintainable operation
The system is particularly suited for traders who:
- Want to automate their trading strategies
- Need reliable execution of trading signals
- Require comprehensive trade tracking and analysis
- Value real-time monitoring and alerts
- Prefer systematic, rule-based trading over discretionary decisions
WATA uses a microservice architecture with:
| Component (roles) | Purpose |
|---|---|
| Web Server | Receives webhook signals from third party (like: TradingView) |
| Trader | Executes Saxo Bank API operations |
| Scheduler | Manages job orchestrations |
| Telegram | Delivers notifications and alerts |
| RabbitMQ | Handles inter-component messaging |
-
Signal Reception
- Validate incoming webhooks (authentication, schema)
- Parse action type (long, short, close)
-
Rule Validation
- Verify market hours, timestamp freshness
- Check allowed indices and position duplicates
- Apply daily profit limits
-
Trade Execution
- For new positions: instrument search, order calculation, position confirmation
- For closing: position retrieval, order creation, performance reporting
- Automatic position monitoring with stop-loss/take-profit handling
-
Performance Tracking
- Daily statistics generation
- Performance metrics reporting
- Database storage for analysis
WATA uses DuckDB for fast in-memory analytics:
- Order tracking: Complete order and positions history with execution details
- Position management: P&L calculations and performance metrics
- Performance analytics: Daily statistics and trading history
- Advantages: High-speed analytics, corruption prevention, SQL support
WATA uses OAuth 2.0 for Saxo Bank API integration:
- When authenticating, the application send you a URL via Telegram (or logs of container)
- Open this URL in your browser and log in with your Saxo credentials, and do all the steps to authorize the application (2FA, risk warning, etc.)
- After authorization, you'll be redirected to a page with a URL containing a
codeparameter - Copy the code value and run
watasaxoauth <CODE>on your server - The application completes authentication using this code
Command Reference:
watasaxoauth <CODE>: Submit the authorization code- The authorization code is valid only for a short time (typically a few minutes)
Troubleshooting:
- If you receive an invalid/expired code error, repeat the process
- A "Timeout waiting for authorization code" error means the application waited for 5 minutes without receiving the code
- Ubuntu server
- Docker and Docker Compose
- Python 3.12+
- Ansible (for automated deployment)
-
Configure Inventory
- Copy the example Ansible inventory file:
cp deploy/tools/ansible/inventory/inventory_example.ini deploy/tools/ansible/inventory/inventory.ini
- Edit
inventory.iniwith your server details
- Copy the example Ansible inventory file:
-
Build Application
- Build the package:
./package.sh
- Build the package:
-
Deploy Application
- Run the deployment script:
cd deploy/tools ./deploy_app_to_your_server.sh - The script will use Ansible to deploy the application to your server
- Run the deployment script:
-
Configure Application
- On the server, set up your credentials in
etc/config.json(see below in Configuration section)
- On the server, set up your credentials in
-
Manage Application Use the following aliases on your server:
watastart: Start the applicationwatastop: Stop the applicationwatalogs: View application logswatastatus: Check application status
The application uses Docker Compose with an override file for enhanced configuration:
-
Environment Variables
- The system uses a
.envfile in thedeploydirectory to manage sensitive configuration. - The primary use is for setting the RabbitMQ password which is then synchronized with your config.json.
- The system uses a
-
Service Dependencies
- A special
setupservice runs before other services to ensure configuration is properly synchronized. - This setup updates the RabbitMQ password in your config.json file to match the one set in your .env file.
- All other services (web_server, trader, scheduler, telegram) depend on both the setup service and the RabbitMQ service.
- A special
After deployment, you need to set up your configuration:
-
Configure RabbitMQ Password
# Navigate to the deploy directory cd /app/deploy # Copy the example .env file cp .env.example .env # Edit the .env file to set your custom RabbitMQ password nano .env
This sets the password used by RabbitMQ and automatically updates your config.json file through the setup service in docker-compose.
-
Copy the Example Config
cp /app/etc/config_example.json /app/etc/config.json
-
Update Configuration Edit
/app/etc/config.jsonwith your specific settings:-
Saxo Bank Authentication
"authentication": { "saxo": { "username": "your_saxo_username", "password": "your_saxo_password", "app_config_object": { "AppName": "your_app_name", "AppKey": "your_app_key", "AppSecret": "your_app_secret" } } }
-
Telegram Notifications
"telegram": { "bot_token": "your_bot_token", "chat_id": "your_chat_id", "bot_name": "your_bot_name" }
-
Trading Rules
allowed_indice: Configure allowed trading indicesmarket_closed_dates: Set market holidaysprofit_per_days: Define profit targets and limits
-
Other Settings
- Logging configuration
- RabbitMQ connection details
- DuckDB database path
- Webhook authentication
-
-
Restart Services
watastop watastart
Send trading signals to:
POST /webhook?token=YOUR_SECRET_TOKEN
Payload:
{
"action": "long",
"indice": "us100",
"signal_timestamp": "2023-07-01T12:00:00Z",
"alert_timestamp": "2023-07-01T12:00:01Z"
}WATA includes a visualization dashboard built on Observable Framework:
- Daily/cumulative profit tracking
- Performance analysis by action type
- Win-rate and position duration metrics
- Interactive data exploration
To use the reporting system, you need:
- Node.js and npm installed
- DuckDB CLI installed
- Python 3.12+ (with required libraries
./reporting/requirements.txt) - Ansible configured with proper inventory (same as deployment stage)
-
Run the Setup Script
./reporting/setup_dashboard.sh
This script creates a new Observable Framework project in
reporting/trading-dashboard. -
Sync Trading Data
./reporting/sync_reporting_data.sh
This script synchronizes your trading data from the server to your local dashboard:
- Fetches DuckDB data from your production server
- Exports the database to Parquet format
- Generates the necessary JSON files for visualization
- Copies all data to the Observable Framework project
-
Start the Dashboard Server
./reporting/start_report_server.sh
This launches the development server on port 4321. Access the dashboard at: http://localhost:4321
- @ioiti: Project author
- @hootnot: Saxo OpenAPI library
MIT License
Copyright (c) 2025 IOITI