Skip to the content.

CGS Engine: US Equity Trading System with Interactive Brokers

CGS Tech represents the next evolution of the Unified Quant-AI Trading Framework, expanding beyond Bitcoin trading into traditional equity markets through Interactive Brokers (IBKR). This new dimension builds upon our proven mathematical foundations and explainable AI principles that have been successfully deployed in cryptocurrency markets, now applied to US equity markets.

As the second dimension of the CGS Engine, this system extends our core trading philosophy — combining rigorous mathematical modeling with explainable AI — to create adaptive, high-performance trading strategies for stocks, ETFs, and equity derivatives. The same quant-AI framework that analyzes Bitcoin market dynamics now analyzes NYSE, NASDAQ, and AMEX market conditions.

From Crypto to Equities: Just as we leverage Binance API for cryptocurrency trading, we now leverage IBKR’s institutional-grade trading infrastructure for US equities. The underlying CGS algorithms remain consistent, but optimized for traditional market structures, trading hours, and regulatory requirements.

Built with Python, IBKR Trader Workstation API, and PostgreSQL, this system delivers the same complete trading lifecycle — from strategy development and backtesting to live execution and performance monitoring — now available for traditional equity markets.


Table of Contents

  1. System Overview
  2. Architecture & Design
  3. Prerequisites & Installation
  4. IBKR Setup & Configuration
  5. System Components
  6. Usage Guide
  7. Risk Management
  8. Performance Monitoring
  9. Best Practices
  10. Troubleshooting

System Overview

Expanding CGS Engine Capabilities

The CGS Engine operates across two complementary dimensions:

  1. Crypto Dimension (Existing): Bitcoin and cryptocurrency trading via Binance API
    • 24/7 market access
    • High volatility strategies
    • Crypto-specific dynamics
  2. Equity Dimension (New): US stock and ETF trading via Interactive Brokers
    • Traditional market hours
    • Institutional-grade infrastructure
    • Regulatory compliance

Unified Framework: Both dimensions share the same core CGS algorithms, risk management principles, and explainable AI approach. Strategies developed in one dimension can be adapted to the other with market-specific optimizations.

Key Features

Target Market


Architecture & Design

System Architecture Diagram

System Architecture

Architecture diagram showing the layered structure from External Layer (IBKR Gateway and Data Providers) through Data Ingestion, Processing, Execution, and Persistence layers.

Technology Stack

Core Technologies

Key Dependencies

ib-insync>=0.9.86
pandas>=1.5.0
numpy>=1.23.0
talib>=0.4.24
vectorbt>=0.25.0
psycopg2-binary>=2.9.0
scikit-learn>=1.2.0
torch>=2.0.0
dash>=2.10.0
python-dotenv>=1.0.0

Data Flow Architecture

Data Flow Sequence

Sequence diagram showing the complete data flow from IBKR Gateway through Data Handler, Strategy Engine, Risk Manager, Order Manager, Database, and Dashboard, covering all four phases: Collection, Processing, Execution, and Monitoring.


Prerequisites & Installation

System Requirements

Prerequisites

macOS Installation

# Install Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install TA-Lib
brew install ta-lib

# Install PostgreSQL
brew install postgresql@15
brew services start postgresql@15

# Install Node.js for mermaid-filter
brew install node
npm install --global mermaid-filter

Linux Installation (Ubuntu/Debian)

# Install system dependencies
sudo apt-get update
sudo apt-get install -y build-essential libssl-dev libffi-dev

# Install TA-Lib
wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar -xzf ta-lib-0.4.0-src.tar.gz
cd ta-lib/
./configure --prefix=/usr
make
sudo make install

# Install PostgreSQL
sudo apt-get install -y postgresql-15 postgresql-contrib-15
sudo systemctl start postgresql

# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo npm install --global mermaid-filter

Windows Installation

# Install TA-Lib dependencies via Visual Studio
# Download pre-built TA-Lib from: https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib

# Install PostgreSQL
# Download installer from: https://www.postgresql.org/download/windows/

# Install Node.js
# Download installer from: https://nodejs.org/

Installation Steps

1. Clone Repository

git clone https://github.com/yourusername/cgs_tech.git
cd cgs_tech

2. Create Virtual Environment

# Create virtual environment
python -m venv venv

# Activate virtual environment
# macOS/Linux:
source venv/bin/activate
# Windows:
venv\Scripts\activate

3. Install Python Dependencies

# Upgrade pip
pip install --upgrade pip

# Install package and dependencies
pip install -e .

# Install additional IBKR dependencies
pip install ib-insync>=0.9.86

4. Database Setup

# Create PostgreSQL database
psql -U postgres -c "CREATE DATABASE cgs_trading;"
psql -U postgres -c "CREATE USER cgs_user WITH PASSWORD 'your_secure_password';"
psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE cgs_trading TO cgs_user;"

# Initialize database schema
psql -U cgs_user -d cgs_trading -f src/sql/V001_create_tables.sql
psql -U cgs_user -d cgs_trading -f src/sql/V002_create_base_view.sql
psql -U cgs_trading -U cgs_user -d cgs_trading -f src/sql/V003_create_time_view.sql

5. Environment Configuration

# Copy example environment file
cp env_example .env

# Edit .env with your configuration
nano .env

IBKR Setup & Configuration

1. Install IBKR Trader Workstation (TWS) or IBKR Gateway

Option A: TWS (Trader Workstation)

Option B: IBKR Gateway

2. Configure IBKR Connection

TWS Configuration

  1. Open TWS
  2. Go to ConfigureAPISettings
  3. Enable Enable ActiveX and Socket Clients
  4. Set Socket Port: 7497 (paper trading) or 7496 (live trading)
  5. Add trusted IP: Your system’s IP address
  6. Check Read-Only API if you only need data

IBKR Gateway Configuration

  1. Launch IBKR Gateway
  2. Login with your IBKR credentials
  3. Configure API settings similar to TWS
  4. Note the port number (7497 for paper, 7496 for live)

3. Environment Variables

Update .env file:

# IBKR Connection
IBKR_HOST=127.0.0.1
IBKR_PORT=7497
IBKR_CLIENT_ID=1

# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=cgs_trading
DB_USER=cgs_user
DB_PASSWORD=your_secure_password

# Trading Configuration
TRADING_MODE=paper  # paper or live
ACCOUNT_ID=your_account_id

# Risk Management
MAX_POSITION_SIZE=10000.00
MAX_PORTFOLIO_EXPOSURE=0.95
STOP_LOSS_THRESHOLD=0.02
MAX_DAILY_LOSS=0.05

# Strategy Parameters
DEFAULT_HOLDING_PERIOD=50
DEFAULT_STOP_LOSS=-0.02
DEFAULT_LEVERAGE=1.0

4. Test IBKR Connection

from ib_insync import IB

# Test connection
ib = IB()
try:
    ib.connect('127.0.0.1', 7497, clientId=1)
    print("Connected to IBKR successfully!")
    print(f"Connected accounts: {ib.accountValues()}")
    ib.disconnect()
except Exception as e:
    print(f"Connection failed: {e}")

System Components

1. Data Handler (src/data_sources/)

File: ibkr_data_handler.py

"""
IBKR Data Handler for US Equity Markets
Handles real-time and historical market data from Interactive Brokers
"""

from ib_insync import IB, Stock, Contract
import pandas as pd
from datetime import datetime, timedelta
import pytz

class IBKRDataHandler:
    def __init__(self, host='127.0.0.1', port=7497, client_id=1):
        self.ib = IB()
        self.ib.connect(host, port, clientId=client_id)
        
    def get_realtime_quote(self, symbol):
        """Get real-time quote for a stock"""
        contract = Stock(symbol, 'SMART', 'USD')
        self.ib.qualifyContracts(contract)
        
        ticker = self.ib.reqMktData(contract, '', False, False)
        self.ib.sleep(0.1)
        
        return {
            'bid': ticker.bid,
            'ask': ticker.ask,
            'last': ticker.last,
            'volume': ticker.volume
        }
    
    def get_historical_data(self, symbol, end_date, duration, bar_size):
        """
        Get historical data from IBKR
        
        Args:
            symbol: Stock symbol (e.g., 'AAPL', 'TSLA')
            end_date: End date for data
            duration: Duration string (e.g., '1 Y', '6 M')
            bar_size: Bar size (e.g., '1 min', '5 mins', '1 day')
        
        Returns:
            DataFrame with OHLCV data
        """
        contract = Stock(symbol, 'SMART', 'USD')
        self.ib.qualifyContracts(contract)
        
        bars = self.ib.reqHistoricalData(
            contract,
            endDateTime=end_date,
            durationStr=duration,
            barSizeSetting=bar_size,
            whatToShow='TRADES',
            useRTH=True,
            formatDate=1
        )
        
        df = pd.DataFrame(bars)
        return df
    
    def get_account_info(self):
        """Get account information"""
        account_values = self.ib.accountValues()
        return {av.tag: av.value for av in account_values}
    
    def get_positions(self):
        """Get current positions"""
        positions = self.ib.positions()
        return positions

2. Order Manager (src/execution/)

File: ibkr_order_manager.py

"""
Order Manager for IBKR
Handles order submission, modification, and cancellation
"""

from ib_insync import IB, Stock, LimitOrder, MarketOrder, StopOrder
from datetime import datetime

class IBKROrderManager:
    def __init__(self, ib_instance):
        self.ib = ib_instance
        
    def place_limit_order(self, symbol, quantity, limit_price, action='BUY'):
        """
        Place a limit order
        
        Args:
            symbol: Stock symbol
            quantity: Number of shares
            limit_price: Limit price
            action: 'BUY' or 'SELL'
        """
        contract = Stock(symbol, 'SMART', 'USD')
        self.ib.qualifyContracts(contract)
        
        order = LimitOrder(action, quantity, limit_price)
        trade = self.ib.placeOrder(contract, order)
        
        return trade
    
    def place_market_order(self, symbol, quantity, action='BUY'):
        """Place a market order"""
        contract = Stock(symbol, 'SMART', 'USD')
        self.ib.qualifyContracts(contract)
        
        order = MarketOrder(action, quantity)
        trade = self.ib.placeOrder(contract, order)
        
        return trade
    
    def place_stop_order(self, symbol, quantity, stop_price, action='BUY'):
        """Place a stop order"""
        contract = Stock(symbol, 'SMART', 'USD')
        self.ib.qualifyContracts(contract)
        
        if action == 'BUY':
            order = StopOrder('BUY', quantity, stop_price)
        else:
            order = StopOrder('SELL', quantity, stop_price)
            
        trade = self.ib.placeOrder(contract, order)
        return trade
    
    def cancel_order(self, order_id):
        """Cancel an order"""
        self.ib.cancelOrder(order_id)
    
    def get_open_orders(self):
        """Get all open orders"""
        return self.ib.openOrders()

3. Strategy Engine (src/indicators/)

Files:

Example: TSLP for US Equities

"""
TSLP CGS Base Strategy for US Equity Trading
"""

import numpy as np
import talib
from indicators.base import BaseIndicator

class TSLPStockStrategy(BaseIndicator):
    def __init__(self, name="TSLPStockStrategy", params=None):
        super().__init__(name, params)
        self.timeperiod = params.get("timeperiod", 200)
        self.nbdev = params.get("nbdev", 0.5)
        self.holding_period = params.get("holding_period", 50)
        self.stoploss = params.get("stoploss", -0.02)
        self.current_position = None
        
    def calculate_signals(self, data):
        """
        Calculate trading signals for US equities
        
        Args:
            data: DataFrame with OHLCV data
            
        Returns:
            DataFrame with signals
        """
        df = data.copy()
        
        # Calculate Bollinger Bands
        upper, middle, lower = talib.BBANDS(
            df['Close'].values,
            timeperiod=self.timeperiod,
            nbdevup=self.nbdev,
            nbdevdn=self.nbdev
        )
        
        df['Upper'] = upper
        df['Middle'] = middle
        df['Lower'] = lower
        
        # Generate signals
        df['Signal'] = 0
        
        # Long entry: price crosses above upper band
        long_entry = (df['Close'] > df['Upper']) & (df['Close'].shift(1) <= df['Upper'].shift(1))
        
        # Short entry: price crosses below lower band
        short_entry = (df['Close'] < df['Lower']) & (df['Close'].shift(1) >= df['Lower'].shift(1))
        
        df.loc[long_entry, 'Signal'] = 1
        df.loc[short_entry, 'Signal'] = -1
        
        return df

4. Risk Manager (src/risk/)

File: risk_manager.py

"""
Risk Management System
Implements position sizing, stop-loss, and exposure limits
"""

import numpy as np
from datetime import datetime, timedelta

class RiskManager:
    def __init__(self, config):
        self.max_position_size = config.get('MAX_POSITION_SIZE', 10000.0)
        self.max_portfolio_exposure = config.get('MAX_PORTFOLIO_EXPOSURE', 0.95)
        self.stop_loss_threshold = config.get('STOP_LOSS_THRESHOLD', 0.02)
        self.max_daily_loss = config.get('MAX_DAILY_LOSS', 0.05)
        
    def calculate_position_size(self, account_value, price, volatility, signal_strength):
        """
        Calculate optimal position size based on risk parameters
        
        Args:
            account_value: Total account value
            price: Entry price
            volatility: ATR or volatility measure
            signal_strength: Confidence in signal (0-1)
        
        Returns:
            Number of shares to trade
        """
        # Risk per trade: 1% of account value
        risk_per_trade = account_value * 0.01
        
        # Calculate position size
        stop_distance = price * self.stop_loss_threshold
        position_size = risk_per_trade / stop_distance
        
        # Apply signal strength multiplier
        position_size *= signal_strength
        
        # Cap position size
        max_position_value = account_value * self.max_portfolio_exposure
        max_shares = max_position_value / price
        
        shares = min(int(position_size), max_shares)
        return shares
    
    def validate_trade(self, symbol, quantity, price, current_positions):
        """
        Validate if trade should be executed
        
        Args:
            symbol: Stock symbol
            quantity: Number of shares
            price: Entry price
            current_positions: Current portfolio positions
            
        Returns:
            Boolean indicating if trade is valid
        """
        # Check position size limit
        trade_value = quantity * price
        if trade_value > self.max_position_size:
            return False
        
        # Check portfolio exposure
        total_exposure = sum(pos['value'] for pos in current_positions)
        if (total_exposure + trade_value) / self.account_value > self.max_portfolio_exposure:
            return False
        
        # Check daily loss limit
        daily_loss = self.get_daily_pnl()
        if daily_loss / self.account_value < -self.max_daily_loss:
            return False
        
        return True
    
    def get_daily_pnl(self):
        """Calculate today's P&L"""
        # Implementation depends on your trade tracking system
        return 0.0

5. Backtesting Engine

File: notebooks/VBT_cgs_base.ipynb

The system uses vectorbt for comprehensive backtesting:

import vectorbt as vbt
import pandas as pd

# Load historical data
df = pd.read_csv('data/AAPL.csv', index_col='Date', parse_dates=True)

# Apply strategy
signals = your_strategy.calculate_signals(df)

# Backtest with vectorbt
portfolio = vbt.Portfolio.from_signals(
    df,
    entries=signals['Entry'],
    exits=signals['Exit'],
    fees=0.001,  # 0.1% commission
    slippage=0.0005,  # 0.05% slippage
    freq='1d'
)

# Analyze performance
print(portfolio.stats())
portfolio.plot().show()

Usage Guide

1. Initialize System

from ib_insync import IB
from src.data_sources.ibkr_data_handler import IBKRDataHandler
from src.execution.ibkr_order_manager import IBKROrderManager
from src.indicators.TSLP_cgs_base import TSLPStockStrategy
from src.risk.risk_manager import RiskManager

# Connect to IBKR
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)

# Initialize components
data_handler = IBKRDataHandler(ib)
order_manager = IBKROrderManager(ib)
strategy = TSLPStockStrategy(params={'timeperiod': 200, 'holding_period': 50})
risk_manager = RiskManager(config)

2. Real-time Trading Loop

import time
from datetime import datetime

def trading_loop(symbols, strategy, risk_manager, order_manager):
    """
    Main trading loop for real-time execution
    """
    while True:
        for symbol in symbols:
            try:
                # Get real-time market data
                quote = data_handler.get_realtime_quote(symbol)
                df = data_handler.get_historical_data(
                    symbol, 
                    datetime.now(), 
                    '1 Y', 
                    '1 day'
                )
                
                # Calculate signals
                signals = strategy.calculate_signals(df)
                latest_signal = signals.iloc[-1]
                
                # Get current positions
                positions = data_handler.get_positions()
                
                # Process signal
                if latest_signal['Signal'] == 1:  # Buy signal
                    account_info = data_handler.get_account_info()
                    quantity = risk_manager.calculate_position_size(
                        float(account_info['TotalCashValue']),
                        quote['bid'],
                        latest_signal['Volatility'],
                        latest_signal['SignalStrength']
                    )
                    
                    if risk_manager.validate_trade(symbol, quantity, quote['bid'], positions):
                        order_manager.place_limit_order(
                            symbol, 
                            quantity, 
                            quote['bid'], 
                            'BUY'
                        )
                        
                elif latest_signal['Signal'] == -1:  # Sell signal
                    # Check if we have a position
                    if symbol in positions:
                        order_manager.place_market_order(
                            symbol,
                            positions[symbol]['quantity'],
                            'SELL'
                        )
            
            except Exception as e:
                print(f"Error processing {symbol}: {e}")
                continue
        
        # Sleep before next iteration
        time.sleep(60)  # Wait 1 minute between checks

3. Run Strategy on Specific Stock

# Trade AAPL using TSLP strategy
trading_loop(['AAPL'], strategy, risk_manager, order_manager)

4. Multi-Stock Portfolio Trading

# Trade multiple stocks
symbols = ['AAPL', 'MSFT', 'GOOGL', 'TSLA', 'NVDA']
trading_loop(symbols, strategy, risk_manager, order_manager)

Risk Management

Built-in Risk Controls

  1. Position Limits
    • Maximum position size per stock
    • Total portfolio exposure limit
    • Individual position sizing based on volatility
  2. Stop-Loss Protection
    • Automatic stop-loss on all positions
    • Configurable stop-loss thresholds
    • Trailing stop capabilities
  3. Daily Loss Limits
    • Maximum daily loss percentage
    • Automatic trading halt on breach
    • Alert notifications
  4. Exposure Management
    • Maximum portfolio exposure
    • Sector concentration limits
    • Correlation-based position management

Emergency Controls

# Emergency stop function
def emergency_stop(order_manager):
    """
    Close all positions and cancel open orders
    """
    # Cancel all open orders
    for order in order_manager.get_open_orders():
        order_manager.cancel_order(order.orderId)
    
    # Close all positions
    positions = data_handler.get_positions()
    for symbol, position in positions.items():
        order_manager.place_market_order(
            symbol,
            position['quantity'],
            'SELL'
        )

Performance Monitoring

Real-time Dashboard

# Start the monitoring dashboard
python src/app.py

Access dashboard at: http://localhost:8081

Key Metrics

Performance Analytics

import pandas as pd
from src.analytics.performance_analyzer import PerformanceAnalyzer

# Load trade history
trades_df = pd.read_csv('logs/trades.csv')

# Analyze performance
analyzer = PerformanceAnalyzer(trades_df)
metrics = analyzer.calculate_metrics()

print(f"Total Return: {metrics['total_return']:.2%}")
print(f"Sharpe Ratio: {metrics['sharpe_ratio']:.2f}")
print(f"Max Drawdown: {metrics['max_drawdown']:.2%}")
print(f"Win Rate: {metrics['win_rate']:.2%}")

Best Practices

1. Start with Paper Trading

2. Risk Management

3. System Monitoring

4. Strategy Development

5. Execution Quality


Troubleshooting

Common Issues

1. IBKR Connection Issues

Problem: Cannot connect to TWS/Gateway

Solution:

# Check if TWS/Gateway is running
# Verify port numbers (7497 for paper, 7496 for live)
# Check firewall settings
# Ensure IP address is trusted in TWS settings

2. Insufficient Data

Problem: Not enough historical data for analysis

Solution:

# Request more historical data
bars = ib.reqHistoricalData(
    contract,
    endDateTime='',
    durationStr='1 Y',  # Increase duration
    barSizeSetting='1 day',
    whatToShow='TRADES',
    useRTH=True
)

3. Order Rejection

Problem: Orders being rejected by IBKR

Solution:

4. High Latency

Problem: Delayed execution

Solution:

Debug Mode

Enable debug logging:

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('debug.log'),
        logging.StreamHandler()
    ]
)

Example: Complete Trading System

"""
Complete US Equity Trading System Example
"""

import os
from dotenv import load_dotenv
from ib_insync import IB

from src.data_sources.ibkr_data_handler import IBKRDataHandler
from src.execution.ibkr_order_manager import IBKROrderManager
from src.indicators.TSLP_cgs_base import TSLPStockStrategy
from src.risk.risk_manager import RiskManager

# Load configuration
load_dotenv()

def main():
    # Connect to IBKR
    ib = IB()
    ib.connect(
        os.getenv('IBKR_HOST'),
        int(os.getenv('IBKR_PORT')),
        clientId=int(os.getenv('IBKR_CLIENT_ID'))
    )
    
    # Initialize components
    data_handler = IBKRDataHandler(ib)
    order_manager = IBKROrderManager(ib)
    
    strategy_params = {
        'timeperiod': 200,
        'nbdev': 0.5,
        'holding_period': 50,
        'stoploss': -0.02
    }
    strategy = TSLPStockStrategy(params=strategy_params)
    
    config = {
        'MAX_POSITION_SIZE': float(os.getenv('MAX_POSITION_SIZE')),
        'MAX_PORTFOLIO_EXPOSURE': float(os.getenv('MAX_PORTFOLIO_EXPOSURE')),
        'STOP_LOSS_THRESHOLD': float(os.getenv('STOP_LOSS_THRESHOLD'))
    }
    risk_manager = RiskManager(config)
    
    # Trading symbols
    symbols = ['AAPL', 'MSFT', 'GOOGL', 'TSLA']
    
    # Start trading loop
    print("Starting US Equity Trading System...")
    trading_loop(symbols, strategy, risk_manager, order_manager)

if __name__ == "__main__":
    main()

Additional Resources


Support

For issues, questions, or contributions:


License

Copyright (C) 2025 CGS Engine Inc, All Rights Reserved


Disclaimer: Trading stocks involves risk. Past performance does not guarantee future results. Always test strategies in paper trading before deploying capital. This system is for educational and research purposes. Use at your own risk.