Files
The-Ouroboros/docs/architecture.md
agentson 881bbb4240
Some checks failed
CI / test (pull_request) Has been cancelled
docs: add Telegram notifications documentation (issue #35)
Update project documentation to include Telegram notification feature
that was added in issues #31-34.

Changes:
- CLAUDE.md: Add Telegram quick setup section with examples
- README.md (Korean): Add 텔레그램 알림 section with setup guide
- docs/architecture.md: Add Notifications component documentation
  - New section explaining TelegramClient architecture
  - Add notification step to data flow diagram
  - Add Telegram config to environment variables
  - Document error handling for notification failures

Documentation covers:
- Quick setup instructions (bot creation, chat ID, env config)
- Notification types (trades, circuit breaker, fat-finger, etc.)
- Fail-safe behavior (notifications never crash trading)
- Links to detailed guide in src/notifications/README.md

Project structure updated to reflect notifications/ directory and
updated test count (273 tests).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-04 23:48:01 +09:00

9.8 KiB

System Architecture

Overview

Self-evolving AI trading agent for global stock markets via KIS (Korea Investment & Securities) API. The main loop in src/main.py orchestrates four components in a 60-second cycle per stock across multiple markets.

Core Components

1. Broker (src/broker/)

KISBroker (kis_api.py) — Async KIS API client for domestic Korean market

  • Automatic OAuth token refresh (valid for 24 hours)
  • Leaky-bucket rate limiter (10 requests per second)
  • POST body hash-key signing for order authentication
  • Custom SSL context with disabled hostname verification for VTS (virtual trading) endpoint due to known certificate mismatch

OverseasBroker (overseas.py) — KIS overseas stock API wrapper

  • Reuses KISBroker infrastructure (session, token, rate limiter) via composition
  • Supports 9 global markets: US (NASDAQ/NYSE/AMEX), Japan, Hong Kong, China (Shanghai/Shenzhen), Vietnam (Hanoi/HCM)
  • Different API endpoints for overseas price/balance/order operations

Market Schedule (src/markets/schedule.py) — Timezone-aware market management

  • MarketInfo dataclass with timezone, trading hours, lunch breaks
  • Automatic DST handling via zoneinfo.ZoneInfo
  • is_market_open() checks weekends, trading hours, lunch breaks
  • get_open_markets() returns currently active markets
  • get_next_market_open() finds next market to open and when

2. Brain (src/brain/gemini_client.py)

GeminiClient — AI decision engine powered by Google Gemini

  • Constructs structured prompts from market data
  • Parses JSON responses into TradeDecision objects (action, confidence, rationale)
  • Forces HOLD when confidence < threshold (default 80)
  • Falls back to safe HOLD on any parse/API error
  • Handles markdown-wrapped JSON, malformed responses, invalid actions

3. Risk Manager (src/core/risk_manager.py)

RiskManager — Safety circuit breaker and order validation

⚠️ READ-ONLY by policy (see docs/agents.md)

  • Circuit Breaker: Halts all trading via SystemExit when daily P&L drops below -3.0%
    • Threshold may only be made stricter, never relaxed
    • Calculated as (total_eval - purchase_total) / purchase_total * 100
  • Fat-Finger Protection: Rejects orders exceeding 30% of available cash
    • Must always be enforced, cannot be disabled

4. Notifications (src/notifications/telegram_client.py)

TelegramClient — Real-time event notifications via Telegram Bot API

  • Sends alerts for trades, circuit breakers, fat-finger rejections, system events
  • Non-blocking: failures are logged but never crash trading
  • Rate-limited: 1 message/second default to respect Telegram API limits
  • Auto-disabled when credentials missing
  • Gracefully handles API errors, network timeouts, invalid tokens

Notification Types:

  • Trade execution (BUY/SELL with confidence)
  • Circuit breaker trips (critical alert)
  • Fat-finger protection triggers (order rejection)
  • Market open/close events
  • System startup/shutdown status

Setup: See src/notifications/README.md for bot creation and configuration.

5. Evolution (src/evolution/optimizer.py)

StrategyOptimizer — Self-improvement loop

  • Analyzes high-confidence losing trades from SQLite
  • Asks Gemini to generate new BaseStrategy subclasses
  • Validates generated strategies by running full pytest suite
  • Simulates PR creation for human review
  • Only activates strategies that pass all tests

Data Flow

┌─────────────────────────────────────────────────────────────┐
│ Main Loop (60s cycle per stock, per market)                │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Market Schedule Check             │
        │ - Get open markets                │
        │ - Filter by enabled markets       │
        │ - Wait if all closed              │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Broker: Fetch Market Data        │
        │ - Domestic: orderbook + balance  │
        │ - Overseas: price + balance      │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Calculate P&L                     │
        │ pnl_pct = (eval - cost) / cost   │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Brain: Get Decision               │
        │ - Build prompt with market data   │
        │ - Call Gemini API                 │
        │ - Parse JSON response             │
        │ - Return TradeDecision            │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Risk Manager: Validate Order      │
        │ - Check circuit breaker           │
        │ - Check fat-finger limit          │
        │ - Raise if validation fails       │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Broker: Execute Order             │
        │ - Domestic: send_order()          │
        │ - Overseas: send_overseas_order() │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Notifications: Send Alert         │
        │ - Trade execution notification    │
        │ - Non-blocking (errors logged)    │
        │ - Rate-limited to 1/sec           │
        └──────────────────┬────────────────┘
                           │
                           ▼
        ┌──────────────────────────────────┐
        │ Database: Log Trade               │
        │ - SQLite (data/trades.db)         │
        │ - Track: action, confidence,      │
        │   rationale, market, exchange     │
        └───────────────────────────────────┘

Database Schema

SQLite (src/db.py)

CREATE TABLE trades (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    timestamp TEXT NOT NULL,
    stock_code TEXT NOT NULL,
    action TEXT NOT NULL,          -- BUY | SELL | HOLD
    confidence INTEGER NOT NULL,   -- 0-100
    rationale TEXT,
    quantity INTEGER,
    price REAL,
    pnl REAL DEFAULT 0.0,
    market TEXT DEFAULT 'KR',       -- KR | US_NASDAQ | JP | etc.
    exchange_code TEXT DEFAULT 'KRX' -- KRX | NASD | NYSE | etc.
);

Auto-migration: Adds market and exchange_code columns if missing for backward compatibility.

Configuration

Pydantic Settings (src/config.py)

Loaded from .env file:

# Required
KIS_APP_KEY=your_app_key
KIS_APP_SECRET=your_app_secret
KIS_ACCOUNT_NO=XXXXXXXX-XX
GEMINI_API_KEY=your_gemini_key

# Optional
MODE=paper                    # paper | live
DB_PATH=data/trades.db
CONFIDENCE_THRESHOLD=80
MAX_LOSS_PCT=3.0
MAX_ORDER_PCT=30.0
ENABLED_MARKETS=KR,US_NASDAQ  # Comma-separated market codes

# Telegram Notifications (optional)
TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz
TELEGRAM_CHAT_ID=123456789
TELEGRAM_ENABLED=true

Tests use in-memory SQLite (DB_PATH=":memory:") and dummy credentials via tests/conftest.py.

Error Handling

Connection Errors (Broker API)

  • Retry with exponential backoff (2^attempt seconds)
  • Max 3 retries per stock
  • After exhaustion, skip stock and continue with next

API Quota Errors (Gemini)

  • Return safe HOLD decision with confidence=0
  • Log error but don't crash
  • Agent continues trading on next cycle

Circuit Breaker Tripped

  • Immediately halt via SystemExit
  • Log critical message
  • Requires manual intervention to restart

Market Closed

  • Wait until next market opens
  • Use get_next_market_open() to calculate wait time
  • Sleep until market open time

Telegram API Errors

  • Log warning but continue trading
  • Missing credentials → auto-disable notifications
  • Network timeout → skip notification, no retry
  • Invalid token → log error, trading unaffected
  • Rate limit exceeded → queued via rate limiter

Guarantee: Notification failures never interrupt trading operations.