Skip to main content

Official Python SDK for ActTrader Trading API

Project description

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).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

acttrader_trading_sdk-1.0.1.tar.gz (31.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

acttrader_trading_sdk-1.0.1-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

File details

Details for the file acttrader_trading_sdk-1.0.1.tar.gz.

File metadata

  • Download URL: acttrader_trading_sdk-1.0.1.tar.gz
  • Upload date:
  • Size: 31.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for acttrader_trading_sdk-1.0.1.tar.gz
Algorithm Hash digest
SHA256 6f3a7a753459ca53b43bf4e5ab8bf166fecf730bb21d1e38baf51e5cd97b9600
MD5 1999afc765c63b071799c14100e2e9bc
BLAKE2b-256 06ff3fbccf8e91543db703abaeb060782781f94f13ea49a26675622c649099c1

See more details on using hashes here.

File details

Details for the file acttrader_trading_sdk-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for acttrader_trading_sdk-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4f1ba7c225da23e26218487647df985738be4538fd40be402d09531b0f62f4c3
MD5 5cb174e8f87fc7a7a490fbbe556bba79
BLAKE2b-256 eec1c83bf03160365347354ca6e06fa49a3d54b34785faaf8525047fd4ef1d9c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page