This document provides a comprehensive guide for an AI agent to understand, modify, and maintain the WATA project.
WATA is an automated trading system for executing Knock-out Warrants (Turbos) on the Saxo Bank platform. It operates as a collection of microservices that listen for trading signals (e.g., from TradingView via webhooks) and executes them according to a predefined set of rules.
The system is designed for automated execution, risk management, performance tracking, and real-time monitoring via Telegram.
WATA uses a microservice architecture orchestrated with Docker Compose. A central RabbitMQ message broker facilitates communication between services.
- Docker Compose (
deploy/docker-compose.yml): Defines and configures all the services. All application services use a common base image (wata-base:latest). - Entrypoint Script (
src/start_python_script.sh): This script is theCMDfor the Docker image. It reads theWATA_APP_ROLEenvironment variable to determine which Python script to run, effectively launching the specific service for that container.
| Service Role | WATA_APP_ROLE |
Entry Point Script | Purpose |
|---|---|---|---|
| Trader | trader |
src/main.py |
The core service. It consumes trading signals from RabbitMQ, checks them against trading rules, executes trades via the Saxo API, and manages positions. |
| Web Server | web_server |
src/web_server/__init__.py |
A FastAPI application that exposes a webhook endpoint. It receives signals from external sources, validates them, and publishes them to the trading-action RabbitMQ queue. |
| Scheduler | scheduler |
src/scheduler/__init__.py |
Runs periodic tasks using the schedule library. It can trigger actions like check_positions_on_saxo_api or daily_stats by publishing messages to RabbitMQ. |
| Telegram | telegram |
src/mq_telegram/__init__.py |
Consumes messages from a dedicated RabbitMQ queue and forwards them to a specified Telegram chat, providing real-time notifications and alerts. |
| RabbitMQ | N/A | N/A | The message broker that decouples the services and handles asynchronous communication. |
src/: Contains all the core source code for the application's microservices.main.py: Entry point for the Trader service.web_server/: Code for the Web Server service, including the FastAPI app and token management.scheduler/: Code for the Scheduler service.mq_telegram/: Code for the Telegram Notifier service.saxo_authen/: Handles Saxo Bank OAuth 2.0 authentication flow.saxo_openapi/: A library for interacting with the Saxo OpenAPI.trade/: Contains the core trading logic, includingrules.pyand API action handlers.database/: Manages the DuckDB database interactions.start_python_script.sh: The main entrypoint script for the Docker containers.
etc/: Configuration files.config.json: The main configuration file for the entire application.config_example.json: An example template for the configuration.
deploy/: Contains deployment-related files.docker-compose.yml: The main Docker Compose file for production.Dockerfile: The Dockerfile used to build thewata-baseimage.
reporting/: Scripts and tools for generating performance reports and visualizations.tests/: Contains unit and integration tests.requirements.txt: A complete list of all Python dependencies.setup.py: Defines project metadata and, importantly, the console script entry points.
This file is the primary interface between the application's business logic and the Saxo Bank API. It abstracts the API's complexity into a set of reusable classes:
-
SaxoApiClient: The foundational client for making HTTP requests to the Saxo API. It handles authentication, headers, and basic error handling. -
Service-Oriented Classes:
InstrumentService: Responsible for searching for tradable instruments (e.g., finding a specific Turbo Warrant).OrderService: Responsible for creating and placing trade orders.PositionService: Manages open positions, including fetching their status and performance.
-
High-Level Orchestrators:
TradingOrchestrator: Manages the end-to-end process of opening a new trade, from finding an instrument to placing the order and confirming the position.PerformanceMonitor: Continuously monitors open positions, checking them against stop-loss/take-profit rules and closing them if necessary.
All services are configured via a single JSON file, typically located at /app/etc/config.json inside the containers.
authentication:saxo: Holds OAuth 2.0 credentials (AppName,AppKey,AppSecret) and endpoints for the Saxo API.persistant.token_path: File path for storing the persistent Saxo authentication token.
webserver:persistant.token_path: File path for the webhook authentication token.app_secret: A secret key used for securing the web server.
logging: Configures logging level, path, and format.rabbitmq: Connection details for the RabbitMQ broker.duckdb:persistant.db_path: The file path for the DuckDB database.
trade:rules: An array of rule objects that define the trading logic (see section 6).config: General trading parameters liketurbo_preference,buying_power,position_management(stop-loss/take-profit), API limits, andtimezone.
telegram:bot_token,chat_id,bot_name: Credentials for the Telegram bot.
The setup.py file creates console scripts for managing authentication.
This command is used to complete the OAuth 2.0 flow for Saxo Bank.
- File:
src/saxo_authen/cli.py - Command:
watasaxoauth - Function: When the application requires authentication, the user must run this command and paste the authorization
codeobtained from the Saxo login URL. The script securely reads the code usinggetpassand saves it to a file where the Trader service can pick it up to complete the authentication.
This command manages the static token used to secure the webhook endpoint.
- File:
src/web_server/cli.py - Command:
watawebtoken - Function:
watawebtokenorwatawebtoken --display: Displays the current token.watawebtoken --new: Generates, saves, and displays a new token.
- Usage: The token must be included as a query parameter in webhook URLs (e.g.,
?token=YOUR_TOKEN).
To trigger a trade, send a POST request to the webhook endpoint (/webhook?token=...) with a JSON payload like this:
{
"action": "long",
"indice": "us100",
"signal_timestamp": "2023-07-01T12:00:00Z",
"alert_timestamp": "2023-07-01T12:00:01Z"
}The TradingRule class validates incoming signals against a set of configurable rules before execution. Any modification to trading behavior should likely start here.
- Signal Timestamp Validation: Rejects signals that are older than
max_signal_age_minutes. - Market Hours: Ensures trades only occur within
trading_start_hourandtrading_end_hourand not on dates listed inmarket_closed_dates. It also avoids a "risky" period at the end of the day. - Profit/Loss Limits: Prevents new trades if the
dont_enter_trade_if_day_profit_is_more_thantarget is met or if themax_day_loss_percentis breached. - Allowed Indices: Checks if the signal's
indiceis configured inallowed_indicesand maps it to a Saxoindice_id. - Duplicate Position Check: Prevents opening a new position if a position with the same action (
longorshort) is already open.
The project relies on several key libraries defined in requirements.txt:
fastapi&uvicorn: For the asynchronous web server.pika: For communicating with RabbitMQ.duckdb: For the embedded analytical database.requests&httpx: For making HTTP requests to the Saxo API.schedule: For running periodic tasks in the scheduler service.jsonschema: For validating incoming webhook data.cryptography: For handling encryption of tokens.pydantic: For data validation and settings management.