Skip to content
IOITIPublic

About

WATA (Warrants Automated Trading Assistant) is a Python-based automated trading system for executing Knock-out warrants on Saxo Bank. It processes webhook signals, performs rule validation, executes trades via API, and provides real-time monitoring with Telegram notifications or built-in reporting dashboard. Built on a microservice architecture.

Topics

Resources

Stars

6 stars

Watchers

3 watching

Forks

Latest commit

Β 

History

165 Commits

Folders and files

Repository files navigation

WATA Logo

WATA - Warrants Automated Trading Assistant

Automated trading system for Saxo Bank's Knock-out warrants (Turbos), executing trades via webhook signals.

GitHub repo size GitHub contributors GitHub issues GitHub license GitHub last commit GitHub Release Date GitHub Stars GitHub Forks


Warning

This is a personal learning project and not production-ready software.

Do not risk money which you are afraid to lose. USE THE SOFTWARE AT YOUR OWN RISK. THE AUTHORS AND ALL AFFILIATES ASSUME NO RESPONSIBILITY FOR YOUR TRADING RESULTS.

Always start by running WATA with small money amounts to test the system and its performance. Use a secondary Saxo account if possible. Understand the risks involved in trading before you start, and do not engage money before you understand how it works and what profit/loss you should expect.

Risk Warning: WATA CAN LOSE ALL YOUR MONEY due to:

  • Insufficient code testing
  • Limited security measures on your server
  • Lack of fail-safe mechanisms
  • No comprehensive monitoring included
  • Absence of fail-over systems
  • Limited user experience
  • Change of Saxo Bank API
  • Because trading with leverage is very risky

This software is provided "as is" without warranty. The authors accept no liability for any damages arising from its use.

🎯 Purpose

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
  • Cached Instrument Selection: Maintains a background watchlist of candidate turbos for configured indices and directions
  • Performance Tracking: Provides comprehensive analytics and reporting for trade analysis
  • Real-time Monitoring: Uses Saxo WebSocket updates for open positions and delivers notifications via Telegram
  • Scalability: Uses asynchronous services, PostgreSQL, and a microservice architecture

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

πŸ—οΈ Architecture

WATA runs as a set of Docker Compose services:

Component (role) Purpose
Traefik Routes public webhook traffic over HTTPS, obtains TLS certificates, and applies the configured IP allowlist
Web Server (web_server) Validates webhook signals and keeps the newest signal per indice in an in-memory store
Trader (trader) Polls the Web Server for signals, applies trading rules, calls Saxo asynchronously, and persists trading data
Watchlist Manager (watchlist_manager) Builds and refreshes cached best-turbo candidates for configured indices and directions
Position Monitor (position_monitor) Monitors live Saxo position updates and handles stop-loss, take-profit, trailing-stop, and operational events
Scheduler (scheduler) Sends scheduled operations to trading-ops and scheduled close signals to the Web Server
PostgreSQL Primary runtime database for orders, positions, and trade performance
RabbitMQ Carries trading-ops messages and Telegram notifications; the Trader no longer consumes trade signals from a RabbitMQ queue
Telegram (telegram) Delivers trade and service notifications
flowchart TD
    classDef external fill:#f9f9f9,stroke:#aaa,stroke-width:1px,color:#000
    classDef service fill:#e1f5fe,stroke:#03a9f4,stroke-width:1px,color:#000
    classDef execution fill:#e8f5e9,stroke:#4caf50,stroke-width:1px,color:#000
    classDef queue fill:#fff8e1,stroke:#ffc107,stroke-width:1px,color:#000
    classDef database fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px,stroke-dasharray:5 5,color:#000

    subgraph ExtSys["External Systems"]
        direction LR
        TV["TradingView"]
        SaxoREST["Saxo Bank REST API"]
        SaxoWS["Saxo Bank WebSocket"]
        TG["Telegram"]
    end

    subgraph CoreSys["WATA Services"]
        direction TB

        Proxy["Traefik<br>HTTPS ingress"]:::service
        WS["Web Server<br>latest-signal store"]:::service
        TR["Async Trader<br>polls /latest-signals"]:::execution
        WM["Watchlist Manager<br>best-turbo cache"]:::service
        PM["Position Monitor"]:::execution
        SC["Scheduler"]:::service
        RMQ["RabbitMQ<br>trading-ops + telegram_channel"]:::queue
        DB[("PostgreSQL 16")]:::database
    end

    TV -->|HTTPS webhook| Proxy --> WS
    TR -->|GET /latest-signals every 500 ms| WS
    WS -->|newest signal per indice| TR
    TR -->|instrument search and orders| SaxoREST
    TR -->|read and write trading data| DB
    TR -->|cached candidate lookup| WM
    WM -->|candidate search| SaxoREST
    SaxoWS -->|live quote updates| WM
    SaxoWS -->|position updates| PM
    PM -->|position and performance data| DB
    SC -->|scheduled operational messages| RMQ
    RMQ -->|trading-ops| PM
    SC -->|scheduled close signal| WS
    TR -->|notifications| RMQ
    PM -->|notifications| RMQ
    RMQ -->|telegram_channel| TG

    class TV,SaxoREST,SaxoWS,TG external
    class Proxy,WS,WM,SC service
    class TR,PM execution
Loading

πŸ“Š Trading Workflow

  1. Signal Reception

    • Receive webhook traffic through Traefik HTTPS and validate the token and payload schema
    • Keep the newest signal for each indice in the Web Server's in-memory store
    • The Trader polls /latest-signals every 500 ms by default; older signals for an indice are ignored
  2. Rule Validation

    • Verify market hours and timestamp freshness
    • Check allowed indices, duplicate positions, and configured risk limits
    • Use the Watchlist Manager's cached candidates when available and validate instrument eligibility
  3. Trade Execution

    • Use asynchronous Saxo API calls for instrument search, order calculation, placement, and confirmation
    • Persist orders, positions, and performance data in PostgreSQL
  4. Real-Time Position Monitoring

    • The Position Monitor consumes Saxo WebSocket updates instead of relying on the old 7-second REST polling loop
    • Evaluate stop-loss, take-profit, and trailing-stop rules; receive scheduled operational events through trading-ops
  5. Reporting and Notifications

    • Generate daily statistics and trade reports, including closed-trade and daily-profit history
    • Send trade and service notifications through the Telegram service

telegram_notifcation.png

πŸ’Ύ Database System

PostgreSQL 16 is the primary runtime database. The application uses an asyncpg connection pool and creates its schema on startup.

  • Order tracking: Orders and execution details
  • Position management: Open and closed positions, including profit/loss data
  • Performance analytics: Trade performance and daily statistics
  • DuckDB migration: src/database/migration.py imports existing DuckDB data into PostgreSQL. DuckDB is no longer used by the live trading services.

πŸ” Authentication and Security

Saxo Bank API Authentication

WATA uses OAuth 2.0 for Saxo Bank API integration:

  1. When authenticating, the application send you a URL via Telegram (or logs of container)
  2. 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.)
  3. After authorization, you'll be redirected to a page with a URL containing a code parameter
  4. Copy the code and run watasaxoauth on your server (you will be prompted to enter the code securely)
  5. The application completes authentication using this code

Command Reference:

  • watasaxoauth: Run this command and you'll be prompted to enter the authorization code securely (the code won't be visible when typing)
  • 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

Please refer to the dedicated docs pages for Saxo Authentication for more details.

Webhook Security

WATA uses token-based authentication to secure webhook endpoints:

  1. Each webhook request must include a valid token in the URL (e.g., /webhook?token=YOUR_TOKEN)
  2. This token is securely generated and stored with strong encryption
  3. Manage your webhook token with the watawebtoken command

Command Reference:

  • watawebtoken: View your current webhook token
  • watawebtoken --new: Generate a new webhook token
  • The command provides instructions on how to use the token in your webhook URL

Security Features:

  • All tokens are encrypted before storage
  • File permissions are restricted to the owner only
  • The deployed Traefik route applies an IP allowlist for TradingView webhook traffic

In the Docker Compose deployment, Traefik redirects HTTP to HTTPS and obtains certificates through Let's Encrypt. Configure API_DOMAIN and ACME_EMAIL in deploy/.env, point the domain at the server, and allow inbound ports 80 and 443. HTTPS and the IP allowlist supplement the webhook token; they do not replace it.

πŸ“– Detailed How-To Guide

For a comprehensive, step-by-step guide on setting up and using WATA, including:

  • Detailed prerequisites and estimated costs
  • Setting up Saxo Bank integration
  • Configuring Telegram notifications
  • Deploying and configuring WATA
  • Setting up TradingView webhooks
  • Starting and monitoring your trading

Please refer to our detailed HOW-TO Guide.

πŸš€ Setup & Deployment

Prerequisites

  • Saxo Bank account with API access
  • Dedicated Ubuntu server (on VPS or local machine)
  • Docker and Docker Compose installed
  • Python 3.12+
  • Ansible (for automated deployment)
  • Telegram bot for notifications
  • (Optional) TradingView account for webhook signals

Detailed Setup

For detailed setup instructions, refer to our HOW-TO Guide.

Quick Start

  1. Configure Inventory

    • Copy the example Ansible inventory file:
      cp deploy/tools/ansible/inventory/inventory_example.ini deploy/tools/ansible/inventory/inventory.ini
    • Edit inventory.ini with your server details
  2. Build Application

    • Build the package:
      ./package.sh
  3. 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
  4. Configure Application

    • On the server, set up your credentials in etc/config.json (see below in Configuration section)
  5. Manage Application Use the following aliases on your server:

    • watastart: Start the application
    • watastop: Stop the application
    • watalogs: View application logs
    • watastatus: Check application status
    • watasaxoauth: Launch the secure authorization code submission process
    • watawebtoken: View your webhook authentication token
    • watawebtoken --new: Generate a new webhook token

Docker Compose Setup

The current stack is defined in deploy/docker-compose.yml; it does not use the old setup service or a separate Compose override. It includes Traefik, PostgreSQL, RabbitMQ, the Web Server, Trader, Scheduler, Telegram, Position Monitor, and Watchlist Manager.

The Compose file uses health checks and service dependencies for PostgreSQL, RabbitMQ, and Traefik. Traefik is the public HTTPS ingress; the other application services communicate over the internal Compose network.

Configuration

After deployment, you need to set up your configuration:

  1. Configure Environment Variables

    # Navigate to the deploy directory
    cd /app/deploy
    
    # Copy the example .env file
    cp .env.example .env
    
    # Edit passwords and the public API hostname
    nano .env

    Set RABBITMQ_PASSWORD, ACME_EMAIL, and API_DOMAIN. Also set a strong POSTGRES_PASSWORD in .env; the Compose file has a fallback if it is omitted, but it should not be used for a real deployment. Point API_DOMAIN to the server so Traefik can issue the HTTPS certificate.

  2. Copy the Example Config

    cp /app/etc/config_example.json /app/etc/config.json
  3. Update Configuration Edit /app/etc/config.json with your specific settings:

    • Saxo Bank Authentication

      "authentication": {
        "saxo": {
          "app_config_object": {
            "AppName": "your_app_name",
            "AppKey": "your_app_key",
            "AppSecret": "your_app_secret"
          }
        }
      }
    • WebServer Security

      "webserver": {
        "persistant": {
          "token_path": "/app/var/lib/web_server/persist_token.json"
        },
        "app_secret": "YOUR_STRONG_SECRET_KEY"
      }
    • Telegram Notifications

      "telegram": {
        "bot_token": "your_bot_token",
        "chat_id": "your_chat_id",
        "bot_name": "your_bot_name"
      }
    • Trading Rules

      • allowed_indices: Configure allowed trading indices
      • market_closed_dates: Set market holidays
      • day_trading: Define profit targets and limits
    • Other Settings

      • Logging configuration
      • RabbitMQ connection details
      • PostgreSQL DSN and pool sizing (postgresql)
      • Saxo streaming refresh and reconnect settings (trade.config.general.streaming)
      • Cached candidate settings (trade.config.watchlist_manager)
      • Signal polling endpoint and interval (trade.config.signal_polling)

    The duckdb configuration is retained for the one-time migration source and legacy reporting export; it is not the live trading database. See the v0.6.x migration notes for the DuckDB-to-PostgreSQL migration steps.

    For a complete and detailed explanation of all configuration options, please refer to the CONFIGURATION Guide.

  4. Restart Services

    watastop
    watastart

Usage

For a deployed instance, send TradingView signals to the HTTPS hostname configured by API_DOMAIN. The Web Server stores only the newest signal per indice in memory; older timestamps for that index are ignored, and pending signals are not persisted across a Web Server restart. The Trader polls this store internally.

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"
}

πŸ“ˆ Reporting

WATA generates trading reports and also includes a local visualization dashboard built on Observable Framework:

  • Daily/cumulative profit tracking
  • Performance analysis by action type
  • Win-rate and position duration metrics
  • Closed-trade and daily-profit history
  • Current account balance and milestone projections in daily reports
  • Interactive data exploration

reporting_example.gif

(yeah, I'm still loosing money... but at least ... I know how much !)

Data-source note: PostgreSQL is the live runtime database, but the current Observable dashboard sync scripts still download the legacy DuckDB file from /app/wata/var/lib/duckdb/ and export it with the DuckDB CLI. They do not export records written to PostgreSQL after the migration. Treat this dashboard sync as a legacy DuckDB export until a PostgreSQL export path is added; application-generated daily reports use the runtime database.

Requirements

To use the reporting system, you need:

  • Node.js and npm installed
  • DuckDB CLI for the existing legacy dashboard export
  • Python 3.12+ (with required libraries ./reporting/requirements.txt)
  • Ansible configured with proper inventory (same as deployment stage)

Setting Up the Dashboard

  1. Run the Setup Script

    ./reporting/setup_dashboard.sh

    This script creates a new Observable Framework project in reporting/trading-dashboard.

  2. Sync Trading Data

    ./reporting/sync_reporting_data.sh

    This script synchronizes your trading data from the server to your local dashboard:

    • Fetches the legacy DuckDB file 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
  3. Start the Dashboard Server

    ./reporting/start_report_server.sh

    This launches the development server on port 4321. Access the dashboard at: http://localhost:4321

❓ Frequently Asked Questions

Here are some of the most common questions about WATA:

General

  • Is WATA suitable for beginners?
    WATA requires understanding of trading concepts, Python, and server management. It's recommended for users with intermediate technical skills.

Trading

  • What markets can I trade with WATA?
    WATA supports trading Knock-out warrants (Turbos) available on Saxo Bank, primarily focusing on major indices.

Setup

  • What are the minimum server requirements?
    A basic VPS with 2GB RAM, 50GB SSD, 2 core CPU should be sufficient for getting started.

For a comprehensive list of questions and answers, please see our detailed FAQ documentation.

🀝 Acknowledgements

πŸ› οΈ Contributors

How to Contribute

We welcome contributions to WATA! Here's how you can help:

  1. Report Issues: Submit bugs or suggest features via GitHub issues
  2. Submit Pull Requests: Code improvements, documentation fixes, or new features
  3. Share Feedback: Let us know how you're using WATA and what could be improved

πŸ“„ License

MIT License

Copyright (c) 2025 IOITI

πŸ“š Documentation Website

WATA have a Docusaurus-based documentation website. The website is hosted on GitHub Pages and can be accessed at https://ioiti.github.io/wata-docs/.

Documentation Structure

The documentation is organized into the following sections:

  • Introduction: Overview of WATA
  • How-To Guide: Step-by-step instructions for setting up and using WATA
  • Configuration Guide: Details on how to configure WATA
  • Saxo Authentication: Guide for authenticating with Saxo Bank's API
  • FAQ: Frequently asked questions about WATA

Contributing to Documentation

We welcome contributions to the documentation! If you find any errors or have suggestions for improvements, please submit a pull request or open an issue on this GitHub repository.

About

WATA (Warrants Automated Trading Assistant) is a Python-based automated trading system for executing Knock-out warrants on Saxo Bank. It processes webhook signals, performs rule validation, executes trades via API, and provides real-time monitoring with Telegram notifications or built-in reporting dashboard. Built on a microservice architecture.

Topics

Resources

Stars

6 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages