Skip to main content

ActTrader SDK for Python

Official Python SDK for ActTrader Trading API. This SDK provides a comprehensive interface to interact with ActTrader's REST API and WebSocket streaming services.

Features

  • 🔐 Authentication - Digest authentication and token-based session management
  • 💰 Account Management - Access account information and manage settings
  • 📊 Market Data - Get real-time and historical market data, symbols, and instruments
  • 📈 Trading Operations - Place, modify, and cancel orders; manage positions
  • 🎯 Lots-Based Trading - Trade with lots (auto-converts to quantity using contract size)
  • 💾 Symbol Cache - Auto-refreshing symbol cache (24-hour intervals)
  • 🔔 Alerts - Create and manage price alerts (deprecated)
  • 🌊 WebSocket Streaming - Real-time market data and trading events
  • 📘 Type Hints - Full Python type hints included
  • Async Support - Modern async/await API

Installation

pip install acttrader-trading-sdk

Quick Start

Initialize the SDK

from acttrader import ActTrader

# Option 1: Initialize with username and password for digest authentication
client = ActTrader(
    base_url='http://rest-api.sysfx.com:18001',
    ws_url='ws://stream.sysfx.com:18002',  # Legacy: single WebSocket URL
    username='your_username',
    password='your_password'
)

# Option 2: Initialize with separate WebSocket URLs (recommended)
client = ActTrader(
    base_url='http://rest-api.sysfx.com:18001',
    order_ws_url='ws://order-stream.sysfx.com:18002',    # Order updates stream
    price_feed_ws_url='ws://pricefeed-stream.sysfx.com:18003',  # Price feed stream
    username='your_username',
    password='your_password'
)

# Option 3: Initialize with existing token
client = ActTrader(
    base_url='http://rest-api.sysfx.com:18001',
    order_ws_url='ws://order-stream.sysfx.com:18002',
    price_feed_ws_url='ws://pricefeed-stream.sysfx.com:18003',
    token='your_existing_token'
)

# Authenticate and initialize symbol cache (required for lots-based trading)
await client.auth.get_token(60)
await client.initialize_symbol_cache()  # Auto-refreshes every 24 hours

API Reference

Authentication

Get Token

# Get authentication token (requires username/password)
result = await client.auth.get_token(60)  # 60 minutes lifetime
token = result.result
print('Token:', token)

# Token is automatically stored in the client

Logout

# Revoke current token
await client.auth.logout()

Reset Password

# Reset user password (sent via email)
await client.auth.reset_password('user_login_id')

Account Management

Get Accounts

# Get all accounts for current user
result = await client.account.get_accounts()
accounts = result.result

for account in accounts:
    print(f"Account {account.AccountID}:")
    print(f"  Balance: {account.Balance} {account.Currency}")
    print(f"  Used Margin: {account.UsedMargin}")

Change Password

# Change user password
await client.account.change_password('old_password', 'new_password')

Market Data

Get Instruments

# Get all active instruments
result = await client.market.get_instruments('Y')
instruments = result.result

for instrument in instruments:
    print(f"{instrument.Name} ({instrument.Type})")

Get Symbols

# Get trading symbols with current prices
result = await client.market.get_symbols()
symbols = result.result

for symbol in symbols:
    print(f"{symbol.Symbol}: Bid {symbol.Sell}, Ask {symbol.Buy}")

Get Detailed Symbol Information

# Get symbols with detailed information (margin, commission, etc.)
result = await client.market.get_symbols_detailed()
details = result.result

for detail in details:
    print(f"{detail.Pair_label}:")
    print(f"  Contract Size: {detail.Contract_size}")
    print(f"  Min Volume: {detail.Min_volume}")
    print(f"  Margin Rate: {detail.Margin_settings.Rate}%")

Get Price Shifts

# Get price shifts for instruments
result = await client.market.get_shifts()
shifts = result.result

Trading

Place Market Order

# Simple order without stop/limit/trail
result = await client.trading.place_market_order({
    'symbol': 'EURUSD',
    'quantity': 100000,  # Direct quantity
    'side': 1,  # 1 = buy, 0 = sell
    'account': 100
})

# 🔥 NEW: Order with LOTS (recommended for forex trading)
result2 = await client.trading.place_market_order({
    'symbol': 'EURUSD',
    'lots': 1.0,        # SDK converts to quantity automatically
    'side': 1,
    'account': 100,
    'stop': 1.0800,     # Optional - stop loss
    'limit': 1.1200,    # Optional - take profit
    'trail': 10,        # Optional - trailing stop (in pips)
    'commentary': 'Optional comment'
})

# Mini lot (0.1 lots)
result3 = await client.trading.place_market_order({
    'symbol': 'EURUSD',
    'lots': 0.1,        # 0.1 lots = 10,000 quantity
    'side': 1,
    'account': 100
})

print('Order placed:', result.result.OrderID)

Note:

  • Use either lots or quantity, not both
  • stop, limit, trail, and commentary are all optional
  • Symbol cache must be initialized to use lots: await client.initialize_symbol_cache()

Place Pending Order

# Place a pending order (Entry Stop or Entry Limit)
result = await client.trading.place_pending_order({
    'symbol': 'EURUSD',
    'quantity': 1000,
    'side': 0,  # 0 = sell, 1 = buy
    'account': 100,
    'price': 1.0950,
    'stop': 1.1000,
    'limit': 1.0900
})

Place Stop/Limit Orders

# Place stop loss on existing trade
await client.trading.place_stop({
    'trade': 12345,
    'price': 1.0800
})

# Place stop using pips instead of price
await client.trading.place_stop({
    'trade': 12345,
    'pips': 50
})

# Place take profit on existing trade
await client.trading.place_limit({
    'trade': 12345,
    'price': 1.1200
})

# Place trailing stop
await client.trading.place_trail({
    'trade': 12345,
    'trail': 10  # 10 pips
})

Modify Order

# Modify pending order
await client.trading.modify_order(
    247668792,  # Order ID
    1.0080,     # New price
    2000        # New quantity
)

Cancel Order

# Cancel pending order
await client.trading.cancel_order(247668792)

Close Trade

# Close open position
result = await client.trading.close_trade(
    247568770,  # Trade ID
    1000,       # Quantity to close
    'N'         # Hedge: 'Y' or 'N'
)

print('Closing order:', result.result.OrderID)

Hedge Trade

# Hedge an open position
result = await client.trading.hedge_trade(
    247568770,  # Trade ID
    1000        # Quantity to hedge
)

Get Open Orders

# Get all open orders
result = await client.trading.get_open_orders()
orders = result.result

for order in orders:
    print(f"Order {order.OrderID}:")
    print(f"  {order.Symbol} {order.Side === 1 ? 'BUY' : 'SELL'}")
    print(f"  Quantity: {order.Quantity} @ {order.Price}")
    print(f"  Type: {order.Type}, Status: {order.Pending}")

Get Open Trades

# Get all open positions
result = await client.trading.get_open_trades()
trades = result.result

for trade in trades:
    print(f"Trade {trade.TradeID}:")
    print(f"  {trade.Symbol} {trade.Side === 1 ? 'BUY' : 'SELL'}")
    print(f"  Quantity: {trade.Quantity} @ {trade.Price}")
    print(f"  Commission: {trade.Commission}")

Get Trade History

# Get historical trades
result = await client.trading.get_trade_history({
    'from_date': '2021-04-01T00:00',
    'till': '2021-04-30T23:59',
    'account': 100
})

history = result.result

for trade in history:
    print(f"Trade {trade.TradeID}:")
    print(f"  Open: {trade.OpenPrice} -> Close: {trade.ClosePrice}")
    print(f"  P&L: {trade.ProfitLoss}")

Get Removed Orders

# Get removed orders history
result = await client.trading.get_removed_orders({
    'from_date': '2021-04-01T00:00',
    'till': '2021-04-30T23:59',
    'account': 100
})

Alerts (Deprecated)

⚠️ Note: The alert module is deprecated. Please check with ActTrader for alternative solutions.

# Get active alerts
result = await client.alert.get_alerts()

# Create alert
alert_result = await client.alert.create_alert(
    'EUR/USD',  # Symbol
    1.1800,     # Price
    'BID',      # Type: 'BID' or 'ASK'
    'Target price'  # Commentary
)

# Modify alert
await client.alert.modify_alert(123, 1.1850, 'BID', 'Updated target')

# Remove alert
await client.alert.remove_alert(123)

# Get triggered alerts
triggered = await client.alert.get_triggered_alerts(
    '202109010000',  # From date (YYYYMMDDHH24MI)
    '202109302359'   # Till date (YYYYMMDDHH24MI)
)

WebSocket Streaming

Real-time market data and trading events via WebSocket. The SDK supports two separate WebSocket streams for optimal performance and separation of concerns:

  1. Order Updates Stream - Handles order events, trade events, account updates, and legacy ticker data
  2. Price Feed Stream - Handles price feed messages with OHLC data

Dual WebSocket Setup (Recommended)

# Create separate streaming clients
order_stream = client.stream_orders()      # Order updates
price_stream = client.stream_price_feed()   # Price feed data

# Connect to order updates stream
order_stream.on('connected', lambda: print('Order stream connected'))
order_stream.on('order', lambda data: print('Order event:', data))
order_stream.on('trade', lambda data: print('Trade event:', data))

await order_stream.connect()
await order_stream.subscribe(['EURUSD', 'GBPUSD'])

# Connect to price feed stream
price_stream.on('connected', lambda: print('Price feed stream connected'))
price_stream.on('pricefeed', lambda data: print('Price feed with OHLC:', data))

await price_stream.connect()
await price_stream.subscribe(['EURUSD', 'GBPUSD'])

Legacy Single WebSocket (Deprecated)

# Create streaming client (legacy approach)
stream = client.stream()

# Connect to WebSocket
await stream.connect()

# Handle connection events
stream.on('connected', lambda: print('Connected to streaming server'))
stream.on('disconnected', lambda: print('Disconnected from streaming server'))
stream.on('error', lambda error: print('WebSocket error:', error))

# Subscribe to symbols
await stream.subscribe(['EURUSD', 'GBPUSD', 'USDJPY'])

# Handle ticker updates (price changes) - Legacy format
stream.on('ticker', lambda data: print('Ticker update:', data))

# Handle price feed updates (new format with OHLC data)
stream.on('pricefeed', lambda data: print('Price feed update:', data))

# Handle order book updates
stream.on('orderbook', lambda data: print('Order book update:', data))

# Handle order events (insert/update/delete)
stream.on('order', lambda data: print('Order event:', data))

# Handle account balance updates
stream.on('account', lambda data: print('Account update:', data))

# Handle trade events
stream.on('trade', lambda data: print('Trade event:', data))

# Handle alert triggers
stream.on('alert', lambda data: print('Alert triggered:', data))

# Handle equity warnings
stream.on('equity_warning', lambda data: print('Equity Warning!', data))

# Unsubscribe from symbols
await stream.unsubscribe(['USDJPY'])

# Disconnect
await stream.disconnect()

Message Formats

The SDK supports two WebSocket message formats:

1. Legacy Ticker Format (Order Updates)

# Event: 'ticker'
{
    "event": "ticker",
    "payload": [
        {
            "m": "EURUSD",
            "time": "2025-10-15T11:25:34.092Z",
            "bid": 1.16295,
            "ask": 1.16302
        }
    ]
}

2. Price Feed Format (Market Data with OHLC)

# Event: 'pricefeed'
{
    "m": "ticker",
    "d": [
        {
            "m": "EURUSD",
            "time": "2025-10-15T11:25:34.092Z",
            "bid": 1.16295,
            "ask": 1.16302,
            "day_open": 1.16064,
            "day_high": 1.16453,
            "day_low": 1.16012
        }
    ]
}

Usage Recommendation:

  • Use ticker event for order updates and basic price data
  • Use pricefeed event for market data analysis with OHLC information

Complete Example

import asyncio
from acttrader import ActTrader

async def main():
    # Initialize client
    client = ActTrader(
        base_url='http://rest-api.sysfx.com:18001',
        ws_url='ws://stream.sysfx.com:18002',
        username='your_username',
        password='your_password'
    )
    
    try:
        # Get authentication token
        token_result = await client.auth.get_token(60)
        print('Authenticated with token:', token_result.result)
        
        # Initialize symbol cache (required for lots-based trading)
        await client.initialize_symbol_cache()
        print('Symbol cache initialized')
        
        # Get accounts
        accounts_result = await client.account.get_accounts()
        accounts = accounts_result.result
        print(f'Found {len(accounts)} accounts')
        
        # Get market symbols
        symbols_result = await client.market.get_symbols()
        symbols = symbols_result.result
        print(f'Available symbols: {len(symbols)}')
        
        # Place a market order using LOTS (recommended)
        order_result = await client.trading.place_market_order({
            'symbol': 'EURUSD',
            'lots': 0.1,       # 0.1 lots (auto-converted to quantity)
            'side': 1,         # Buy
            'account': accounts[0].AccountID,
            'stop': 1.0800,    # Stop loss
            'limit': 1.1200,   # Take profit
            'commentary': 'Test order'
        })
        print('Order placed:', order_result.result.OrderID)
        
        # Get open trades
        trades_result = await client.trading.get_open_trades()
        print('Open trades:', len(trades_result.result))
        
        # Start streaming
        stream = client.stream()
        
        def on_connected():
            print('Streaming connected')
            asyncio.create_task(stream.subscribe(['EURUSD', 'GBPUSD']))
        
        def on_ticker(data):
            print('Price update:', data)
        
        stream.on('connected', on_connected)
        stream.on('ticker', on_ticker)
        
        await stream.connect()
        
        # Keep process running
        await asyncio.sleep(30)
        
        await stream.disconnect()
        await client.auth.logout()
        
    except Exception as error:
        print('Error:', error)

if __name__ == '__main__':
    asyncio.run(main())

Error Handling

All API methods return a response object with the following structure:

class ApiResponse:
    success: bool
    message: Optional[str] = None
    result: Optional[Any] = None

Example error handling:

try:
    result = await client.trading.place_market_order({
        'symbol': 'EURUSD',
        'quantity': 1000,
        'side': 1,
        'account': 100
    })
    
    if result.success:
        print('Order ID:', result.result.OrderID)
    else:
        print('Order failed:', result.message)
except Exception as error:
    print('API Error:', error)

Type Hints

This SDK is written with full Python type hints:

from acttrader import ActTrader, Account, Symbol, Order, Trade, OrderSide, OrderType, ApiResponse

# Full type safety
client = ActTrader({...})

result: ApiResponse[List[Account]] = await client.account.get_accounts()
accounts: List[Account] = result.result

API Endpoints

All dates are in Eastern Time (EST/EDT)

REST API

  • Base URL: http://rest-api.sysfx.com:18001/
  • API Version: v2
  • Format: /api/v2/{module}/{endpoint}

WebSocket

  • URL: ws://stream.sysfx.com:18002/
  • Connection: ws://stream.sysfx.com:18002/ws?token={your_token}

Development

Build from Source

# Install dependencies
pip install -r requirements.txt

# Install in development mode
pip install -e .

Project Structure

acttrader-trading-sdk/
├── acttrader/
│   ├── __init__.py              # Main SDK entry point
│   ├── main.py                  # Main ActTrader class
│   ├── client.py                # HTTP client with authentication
│   ├── types.py                 # Python type definitions
│   ├── digest_auth.py           # Digest authentication
│   ├── symbol_cache.py          # Symbol cache functionality
│   └── modules/
│       ├── __init__.py          # Module exports
│       ├── auth.py              # Authentication module
│       ├── account.py           # Account management module
│       ├── market.py            # Market data module
│       ├── trading.py           # Trading operations module
│       ├── alert.py             # Alerts module (deprecated)
│       └── streaming.py         # WebSocket streaming client
├── examples/                    # Example scripts
├── tests/                       # Test suite
├── setup.py                     # Package setup
├── requirements.txt             # Dependencies
└── README.md                    # This file

License

ISC

Support

For API documentation and support, please contact ActTrader.

Contributing

Contributions are welcome! Please ensure your code follows the existing style and includes appropriate tests.


Note: This SDK requires valid ActTrader credentials and access to ActTrader API servers. All dates/times are in Eastern Time (EST/EDT).

Release files for acttrader-trading-sdk 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for acttrader-trading-sdk 1.0.1
File Size Uploaded
acttrader_trading_sdk-1.0.1.tar.gz 31.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for acttrader-trading-sdk 1.0.1
File Interpreter ABI Platform
acttrader_trading_sdk-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 60.5 kB

Release files / acttrader_trading_sdk-1.0.1.tar.gz

Download URL acttrader_trading_sdk-1.0.1.tar.gz
Size 31.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6f3a7a753459ca53b43bf4e5ab8bf166fecf730bb21d1e38baf51e5cd97b9600
BLAKE2b-256 checksum
How to use checksums
06ff3fbccf8e91543db703abaeb060782781f94f13ea49a26675622c649099c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.2

Release files / acttrader_trading_sdk-1.0.1-py3-none-any.whl

Download URL acttrader_trading_sdk-1.0.1-py3-none-any.whl
Size 29.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4f1ba7c225da23e26218487647df985738be4538fd40be402d09531b0f62f4c3
BLAKE2b-256 checksum
How to use checksums
eec1c83bf03160365347354ca6e06fa49a3d54b34785faaf8525047fd4ef1d9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.2

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page