kaedwen 1f70dd91dd
Build and Push Docker Image / build-and-push (push) Successful in 3m27s
use /oauth2/callback for oidc
Signed-off-by: kaedwen <kaedwen@heinrich.blue>
2026-07-04 20:34:01 +02:00
2026-07-04 07:20:13 +02:00
2026-07-02 20:09:44 +02:00
2026-07-02 20:09:44 +02:00
2026-07-02 20:09:44 +02:00
2026-07-02 20:09:44 +02:00
2026-07-04 20:34:01 +02:00
2026-07-04 07:20:13 +02:00
2026-07-04 07:20:13 +02:00
2026-07-04 07:20:13 +02:00
2026-07-02 20:09:44 +02:00
2026-07-04 20:34:01 +02:00
2026-07-02 20:09:44 +02:00
2026-07-04 07:35:49 +02:00
2026-07-04 20:26:04 +02:00
2026-07-04 20:26:04 +02:00
2026-07-02 20:09:44 +02:00
2026-07-02 20:09:44 +02:00

AI Trading Application

AI-assisted trading application with Interactive Brokers integration, news aggregation, and configurable trading strategies.

Features

Phase 1: Foundation

  • Go module structure
  • SQLite database with migrations
  • Configuration via environment variables
  • Structured JSON logging
  • Graceful shutdown handling

Phase 2: IB Gateway Integration

  • Interactive Brokers API client
  • Connection with retry logic and exponential backoff
  • Account balance tracking (every 5 minutes)
  • Order placement and cancellation
  • Market data subscription support

Phase 3: News Aggregation

  • RSS feed integration (CNBC, MarketWatch, Reuters)
  • Keyword-based sentiment analysis
  • Article deduplication by URL
  • Symbol extraction from news content
  • Automatic news polling (configurable interval)

Phase 4: Trading Strategies

  • Three configurable strategies: defensive, normal, aggressive
  • Risk parameters per strategy (max trades, position size, stop-loss)
  • Sentiment-based trade signal generation
  • Comprehensive test coverage

Phase 5: Trade Execution Engine

  • Pending trade workflow with configurable timeout
  • Rate limiting (hourly and parallel trade limits)
  • Trade repository with full lifecycle tracking
  • Stop-loss order management
  • Trade executor with order placement
  • User approval/rejection of pending trades
  • Force immediate execution option

Phase 6: Web Dashboard

  • HTML/JavaScript frontend with real-time updates
  • Server-Sent Events (SSE) for live trade notifications
  • OpenID Connect authentication via Authelia (optional)
  • Trade management UI (approve/reject/force)
  • Whitelist Management UI - Add/edit/disable trading symbols with WKN/ISIN
  • Real-time balance and statistics display
  • Tabbed interface (Overview/Trades/Whitelist)
  • Responsive design with modal forms
  • Health check endpoint

Phase 8: LLM-Based Sentiment Analysis (Optional)

  • Ollama integration for contextual sentiment analysis
  • Ensemble mode: weighted average of LLM + keyword scoring
  • Graceful fallback to keyword analyzer on LLM timeout
  • Support for Mistral, Llama2, and other Ollama models
  • Configurable temperature and timeout
  • Enhanced accuracy for complex financial language

Status

Completed: Phases 1-6, 8
Production Ready: Backend complete with optional LLM sentiment enhancement

Optional: LLM-Based Sentiment Analysis

The application can optionally use a local LLM (via Ollama) for more accurate sentiment analysis:

Benefits:

  • Context-aware: understands "beats expectations despite loss" as positive
  • Handles negations, sarcasm, and hedging language
  • Adaptive to new financial terminology
  • Provides confidence scores for position sizing

Setup:

# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh

# Pull model (4GB)
ollama pull mistral

# Start Ollama server
ollama serve  # Runs on http://localhost:11434

Enable in config:

llm_scorer:
  enabled: true
  endpoint: http://localhost:11434
  model_name: mistral
  timeout: 30
  temperature: 0.3
  ensemble_weight: 0.7  # 70% LLM + 30% keyword

Resource Requirements:

  • CPU-only: 2-4s per article (async processing)
  • GPU (NVIDIA 4GB+): 0.5-1s per article
  • Memory: 4-8GB RAM

Fallback: If LLM times out or Ollama is unavailable, automatically falls back to keyword-based sentiment analysis.

Docker Deployment

Quick Start with Docker Compose

# Prepare data directory for distroless nonroot user
mkdir -p data && chown 65532:65532 data

# Build and run
docker-compose up -d

# View logs
docker-compose logs -f aitrade

# Stop
docker-compose down

Image Details

Base Image: Google Distroless (gcr.io/distroless/static-debian12:nonroot)

  • Size: ~23 MB (with healthcheck binary)
  • No CGO: Pure Go with modernc.org/sqlite
  • Embedded Migrations: No external files needed
  • Health Check: Built-in lightweight binary (no curl/wget)
  • Security: Non-root user (UID 65532), minimal attack surface
  • Includes: CA certificates, timezone data

Using Pre-built Image from Gitea Registry

# Pull from registry
docker pull gitea.yourdomain.com/yourusername/aitrade:latest

# Run with environment variables
docker run -d \
  -p 8080:8080 \
  -v $(pwd)/data:/app/data \
  -e TRADING_STRATEGY=normal \
  -e DRY_RUN=true \
  -e LLM_SCORER_ENABLED=false \
  --name aitrade \
  gitea.yourdomain.com/yourusername/aitrade:latest

Docker with Ollama (LLM Sentiment)

# Start both services
docker-compose --profile llm up -d

# Pull Mistral model
docker exec ollama ollama pull mistral

# Enable LLM in aitrade
docker-compose exec aitrade sh -c 'export LLM_SCORER_ENABLED=true'
docker-compose restart aitrade

Build Locally

# Build image
docker build -t aitrade:local .

# Run
docker run -d -p 8080:8080 -v $(pwd)/data:/app/data aitrade:local

CI/CD Pipeline

The repository includes a Gitea Actions workflow (.gitea/workflows/docker.yaml) that automatically:

  • Builds Docker image on push to main/master/develop
  • Tags images with branch name, commit SHA, and semantic version
  • Pushes to Gitea Container Registry
  • Creates latest tag for default branch

Triggered by:

  • Push to main/master/develop branches
  • Git tags matching v* (e.g., v1.0.0)
  • Pull requests (build only, no push)

Required Secret: GITEA_TOKEN with registry write permissions

Quick Start

Option 1: Native Binary

# Build
go build -o aitrade ./cmd/aitrade

# Run
./aitrade
# Using Docker Compose
docker-compose up -d

# Or pull from registry
docker pull gitea.yourdomain.com/username/aitrade:latest
docker run -d -p 8080:8080 -v $(pwd)/data:/app/data gitea.yourdomain.com/username/aitrade:latest

Access

Open browser: http://localhost:8080

Note: IB Gateway must be running for broker integration. See full documentation in docs/DOCKER.md.

Configuration

The application supports two configuration methods:

Create a config.yaml file in one of these locations:

  • ./config.yaml (current directory)
  • ~/.config/aitrade/config.yaml
  • /etc/aitrade/config.yaml
  • Custom path via CONFIG_FILE=/path/to/config.yaml

Example config.yaml:

trading:
  strategy: normal
  dry_run: true
  dry_run_balance: 100000.0
  max_trade_value: 2000.0
  watch_symbols:
    - AAPL
    - MSFT
    - GOOGL

database:
  path: ./data/aitrade.db

web:
  port: "8080"

See config.example.yaml for a complete configuration file.

Option 2: Environment Variables

If no YAML file is found, the application uses environment variables:

# Interactive Brokers
IB_GATEWAY_HOST=127.0.0.1
IB_GATEWAY_PORT=4001
IB_CLIENT_ID=1

# Trading Strategy
TRADING_STRATEGY=normal              # defensive, normal, aggressive
STOP_LOSS_ENABLED=true
STOP_LOSS_PERCENT=3.0

# Auto-Trading
TRADING_ENABLED=true                 # Enable automatic trade generation
TRADING_INTERVAL_SECONDS=60          # How often to analyze market (60s default)
WATCH_SYMBOLS=AAPL,MSFT,GOOGL,TSLA,AMZN  # Symbols to monitor

# SELL Triggers
TAKE_PROFIT_PERCENT=5.0              # Sell when profit reaches 5%
HOLD_TIME_MINUTES=30                 # Minimum hold time before selling
SELL_ON_NEGATIVE_SENTIMENT=true      # Sell on negative news sentiment

# Rate Limiting
MAX_TRADES_PER_HOUR=6
MAX_PARALLEL_TRADES=5
PENDING_TIME_SECONDS=300             # 5 minutes

# Trade Limits
MAX_TRADE_VALUE=2000.0               # Absolute max $ per trade (0 = unlimited)

# Dry Run Mode
DRY_RUN=true                         # Enable paper trading (no real money)
DRY_RUN_BALANCE=100000.0             # Starting virtual balance

# Database
DB_PATH=./data/aitrade.db

# Web
WEB_PORT=8080

# News
NEWS_POLL_INTERVAL=300               # seconds

# LLM Sentiment Scorer (Optional - requires Ollama)
LLM_SCORER_ENABLED=false             # Set to true to enable
LLM_SCORER_ENDPOINT=http://localhost:11434
LLM_SCORER_MODEL=mistral
LLM_SCORER_TIMEOUT_SECONDS=30
LLM_SCORER_TEMPERATURE=0.3
LLM_SCORER_ENSEMBLE_WEIGHT=0.7       # 0.0-1.0 (1.0 = LLM only, 0.7 = 70% LLM + 30% keyword)

# OpenID Connect (Authelia) - Optional
OIDC_ENABLED=false                    # Set to true to enable
OIDC_ISSUER=https://auth.example.com
OIDC_CLIENT_ID=aitrade
OIDC_CLIENT_SECRET=<secret>
OIDC_REDIRECT_URL=http://localhost:8080/callback
OIDC_SCOPES=openid,profile,email

API Endpoints

Public

  • GET /health - Health check
  • GET /callback - OIDC callback (when auth enabled)

Protected (requires auth if OIDC enabled)

  • GET / - Main dashboard
  • GET /trades - Get all trades (JSON)
  • GET /events - SSE stream for real-time updates
  • GET /api/balance - Get current balance
  • GET /api/news - Get recent news
  • POST /api/trades/{id}/approve?force=bool - Approve trade
  • POST /api/trades/{id}/reject - Reject trade (JSON body: {"reason": "..."})

Web Dashboard Features

  • 📊 Three Tabs: Overview / All Trades / Whitelist Management
  • 💹 Real-time statistics (balance, active trades, pending trades)
  • 📈 Complete trade history with reasoning and P&L
  • ⏱️ Live countdown timers for pending trades
  • One-click approve/reject/force actions
  • 🛡️ Whitelist Management: Add/edit/disable symbols with WKN/ISIN identifiers
  • Only whitelisted & enabled symbols can execute trades
  • 🔄 Server-Sent Events for instant updates
  • 🔒 Optional OpenID Connect authentication via Authelia
  • 📱 Responsive design with modal forms

Trading Logic

Position Sizing (Capital Allocation)

The system uses intelligent position sizing that considers:

  1. Strategy Base Percentage

    • Defensive: 1.5% of capital per trade
    • Normal: 4.0% of capital per trade
    • Aggressive: 7.5% of capital per trade
  2. Confidence-Based Scaling

    • High confidence (0.9) → Larger position
    • Low confidence (0.5) → Smaller position
    • Multiplier ranges:
      • Defensive: 0.3x - 0.8x
      • Normal: 0.5x - 1.0x
      • Aggressive: 0.7x - 1.2x
  3. Parallel Trade Allocation

    • Capital is divided by MAX_PARALLEL_TRADES
    • Each trade slot gets: TotalCapital / MaxParallel
    • Example: $100k with 5 parallel → $20k per slot
    • Prevents first trade from consuming all capital
  4. Absolute Maximum per Trade

    • MAX_TRADE_VALUE sets hard limit (default: 0 = unlimited)
    • If calculated trade exceeds limit → quantity reduced to fit
    • If price too high for even 1 share → trade rejected
    • Example: MAX_TRADE_VALUE=$2000, price $3000 → rejected

Formula:

capitalPerSlot = totalCapital / maxParallelTrades
adjustedPercent = basePercent * (0.5 + confidence * 0.5)
positionValue = capitalPerSlot * (adjustedPercent / 100)
quantity = floor(positionValue / currentPrice)

Example (Normal Strategy):

  • Total: $100,000
  • Max Parallel: 5
  • Per Slot: $20,000
  • Confidence: 0.72
  • Base: 4.0%
  • Multiplier: 0.86x
  • Adjusted: 3.44%
  • Position: $20,000 × 3.44% = $688
  • Price: $180
  • Quantity: 3 shares

SELL Triggers

Positions are automatically sold when:

  1. Take Profit: Profit ≥ TAKE_PROFIT_PERCENT (default: 5%)
  2. Negative Sentiment: Strong negative news (if SELL_ON_NEGATIVE_SENTIMENT=true)
  3. Stop Loss: Loss ≥ STOP_LOSS_PERCENT (default: 3%)

All SELL trades require minimum hold time (HOLD_TIME_MINUTES) before execution.

go build -o aitrade ./cmd/aitrade

Running

./aitrade

Note: IB Gateway or TWS must be running and configured to accept API connections on the specified port.

Testing

go test ./...

Architecture

/projects/Private/aitrade/
├── cmd/aitrade/           # Application entry point
├── pkg/
│   ├── app/
│   │   ├── client/        # IB Gateway client
│   │   ├── news/          # News aggregation
│   │   ├── strategy/      # Trading strategies
│   │   └── app.go         # Main orchestrator
│   ├── config/            # Configuration
│   ├── db/                # Database layer
│   └── model/             # Data models
└── migrations/            # SQL migrations

Strategy Comparison

Strategy Max Parallel Max/Hour Position Size Stop-Loss Sentiment Threshold
Defensive 2 3 1.5% 2% >0.5 (3+ pos news)
Normal 5 6 4.0% 3% >0.3 (2+ pos news)
Aggressive 10 12 7.5% 5% >0.0 (1+ pos news)

Database Schema

  • trades - Trade lifecycle tracking (pending → submitted → filled → completed)
  • balances - Account balance snapshots
  • news_articles - Aggregated news with sentiment scores
  • schema_migrations - Migration version tracking

License

Private project

S
Description
No description provided
Readme
25 MiB
Languages
Go 81.2%
JavaScript 10%
HTML 4.4%
CSS 3.8%
Dockerfile 0.6%