acttrader-trading-sdk


Nameacttrader-trading-sdk JSON
Version 1.0.1 PyPI version JSON
download
home_pagehttps://github.com/acttrader/python-trading-sdk
SummaryOfficial Python SDK for ActTrader Trading API
upload_time2025-10-24 08:35:58
maintainerNone
docs_urlNone
authorAct
requires_python>=3.8
licenseNone
keywords acttrader trading forex api sdk trading-api market-data websocket financial broker
VCS
bugtrack_url
requirements requests websockets aiohttp asyncio-mqtt pydantic typing-extensions requests-ntlm python-dateutil ujson
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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

```bash
pip install acttrader-trading-sdk
```

## Quick Start

### Initialize the SDK

```python
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

```python
# 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

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

#### Reset Password

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

### Account Management

#### Get Accounts

```python
# 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

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

### Market Data

#### Get Instruments

```python
# 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

```python
# 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

```python
# 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

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

### Trading

#### Place Market Order

```python
# 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

```python
# 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

```python
# 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

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

#### Cancel Order

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

#### Close Trade

```python
# 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

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

#### Get Open Orders

```python
# 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

```python
# 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

```python
# 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

```python
# 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.

```python
# 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)

```python
# 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)

```python
# 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)
```python
# 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)
```python
# 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

```python
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:

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

Example error handling:

```python
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:

```python
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

```bash
# 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).

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/acttrader/python-trading-sdk",
    "name": "acttrader-trading-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "acttrader, trading, forex, api, sdk, trading-api, market-data, websocket, financial, broker",
    "author": "Act",
    "author_email": "support@acttrader.com",
    "download_url": "https://files.pythonhosted.org/packages/06/ff/3fbccf8e91543db703abaeb060782781f94f13ea49a26675622c649099c1/acttrader_trading_sdk-1.0.1.tar.gz",
    "platform": null,
    "description": "# ActTrader SDK for Python\n\nOfficial Python SDK for ActTrader Trading API. This SDK provides a comprehensive interface to interact with ActTrader's REST API and WebSocket streaming services.\n\n## Features\n\n- \ud83d\udd10 **Authentication** - Digest authentication and token-based session management\n- \ud83d\udcb0 **Account Management** - Access account information and manage settings\n- \ud83d\udcca **Market Data** - Get real-time and historical market data, symbols, and instruments\n- \ud83d\udcc8 **Trading Operations** - Place, modify, and cancel orders; manage positions\n- \ud83c\udfaf **Lots-Based Trading** - Trade with lots (auto-converts to quantity using contract size)\n- \ud83d\udcbe **Symbol Cache** - Auto-refreshing symbol cache (24-hour intervals)\n- \ud83d\udd14 **Alerts** - Create and manage price alerts (deprecated)\n- \ud83c\udf0a **WebSocket Streaming** - Real-time market data and trading events\n- \ud83d\udcd8 **Type Hints** - Full Python type hints included\n- \u26a1 **Async Support** - Modern async/await API\n\n## Installation\n\n```bash\npip install acttrader-trading-sdk\n```\n\n## Quick Start\n\n### Initialize the SDK\n\n```python\nfrom acttrader import ActTrader\n\n# Option 1: Initialize with username and password for digest authentication\nclient = ActTrader(\n    base_url='http://rest-api.sysfx.com:18001',\n    ws_url='ws://stream.sysfx.com:18002',  # Legacy: single WebSocket URL\n    username='your_username',\n    password='your_password'\n)\n\n# Option 2: Initialize with separate WebSocket URLs (recommended)\nclient = ActTrader(\n    base_url='http://rest-api.sysfx.com:18001',\n    order_ws_url='ws://order-stream.sysfx.com:18002',    # Order updates stream\n    price_feed_ws_url='ws://pricefeed-stream.sysfx.com:18003',  # Price feed stream\n    username='your_username',\n    password='your_password'\n)\n\n# Option 3: Initialize with existing token\nclient = ActTrader(\n    base_url='http://rest-api.sysfx.com:18001',\n    order_ws_url='ws://order-stream.sysfx.com:18002',\n    price_feed_ws_url='ws://pricefeed-stream.sysfx.com:18003',\n    token='your_existing_token'\n)\n\n# Authenticate and initialize symbol cache (required for lots-based trading)\nawait client.auth.get_token(60)\nawait client.initialize_symbol_cache()  # Auto-refreshes every 24 hours\n```\n\n## API Reference\n\n### Authentication\n\n#### Get Token\n\n```python\n# Get authentication token (requires username/password)\nresult = await client.auth.get_token(60)  # 60 minutes lifetime\ntoken = result.result\nprint('Token:', token)\n\n# Token is automatically stored in the client\n```\n\n#### Logout\n\n```python\n# Revoke current token\nawait client.auth.logout()\n```\n\n#### Reset Password\n\n```python\n# Reset user password (sent via email)\nawait client.auth.reset_password('user_login_id')\n```\n\n### Account Management\n\n#### Get Accounts\n\n```python\n# Get all accounts for current user\nresult = await client.account.get_accounts()\naccounts = result.result\n\nfor account in accounts:\n    print(f\"Account {account.AccountID}:\")\n    print(f\"  Balance: {account.Balance} {account.Currency}\")\n    print(f\"  Used Margin: {account.UsedMargin}\")\n```\n\n#### Change Password\n\n```python\n# Change user password\nawait client.account.change_password('old_password', 'new_password')\n```\n\n### Market Data\n\n#### Get Instruments\n\n```python\n# Get all active instruments\nresult = await client.market.get_instruments('Y')\ninstruments = result.result\n\nfor instrument in instruments:\n    print(f\"{instrument.Name} ({instrument.Type})\")\n```\n\n#### Get Symbols\n\n```python\n# Get trading symbols with current prices\nresult = await client.market.get_symbols()\nsymbols = result.result\n\nfor symbol in symbols:\n    print(f\"{symbol.Symbol}: Bid {symbol.Sell}, Ask {symbol.Buy}\")\n```\n\n#### Get Detailed Symbol Information\n\n```python\n# Get symbols with detailed information (margin, commission, etc.)\nresult = await client.market.get_symbols_detailed()\ndetails = result.result\n\nfor detail in details:\n    print(f\"{detail.Pair_label}:\")\n    print(f\"  Contract Size: {detail.Contract_size}\")\n    print(f\"  Min Volume: {detail.Min_volume}\")\n    print(f\"  Margin Rate: {detail.Margin_settings.Rate}%\")\n```\n\n#### Get Price Shifts\n\n```python\n# Get price shifts for instruments\nresult = await client.market.get_shifts()\nshifts = result.result\n```\n\n### Trading\n\n#### Place Market Order\n\n```python\n# Simple order without stop/limit/trail\nresult = await client.trading.place_market_order({\n    'symbol': 'EURUSD',\n    'quantity': 100000,  # Direct quantity\n    'side': 1,  # 1 = buy, 0 = sell\n    'account': 100\n})\n\n# \ud83d\udd25 NEW: Order with LOTS (recommended for forex trading)\nresult2 = await client.trading.place_market_order({\n    'symbol': 'EURUSD',\n    'lots': 1.0,        # SDK converts to quantity automatically\n    'side': 1,\n    'account': 100,\n    'stop': 1.0800,     # Optional - stop loss\n    'limit': 1.1200,    # Optional - take profit\n    'trail': 10,        # Optional - trailing stop (in pips)\n    'commentary': 'Optional comment'\n})\n\n# Mini lot (0.1 lots)\nresult3 = await client.trading.place_market_order({\n    'symbol': 'EURUSD',\n    'lots': 0.1,        # 0.1 lots = 10,000 quantity\n    'side': 1,\n    'account': 100\n})\n\nprint('Order placed:', result.result.OrderID)\n```\n\n**Note:** \n- Use **either** `lots` **or** `quantity`, not both\n- `stop`, `limit`, `trail`, and `commentary` are all optional\n- Symbol cache must be initialized to use lots: `await client.initialize_symbol_cache()`\n\n#### Place Pending Order\n\n```python\n# Place a pending order (Entry Stop or Entry Limit)\nresult = await client.trading.place_pending_order({\n    'symbol': 'EURUSD',\n    'quantity': 1000,\n    'side': 0,  # 0 = sell, 1 = buy\n    'account': 100,\n    'price': 1.0950,\n    'stop': 1.1000,\n    'limit': 1.0900\n})\n```\n\n#### Place Stop/Limit Orders\n\n```python\n# Place stop loss on existing trade\nawait client.trading.place_stop({\n    'trade': 12345,\n    'price': 1.0800\n})\n\n# Place stop using pips instead of price\nawait client.trading.place_stop({\n    'trade': 12345,\n    'pips': 50\n})\n\n# Place take profit on existing trade\nawait client.trading.place_limit({\n    'trade': 12345,\n    'price': 1.1200\n})\n\n# Place trailing stop\nawait client.trading.place_trail({\n    'trade': 12345,\n    'trail': 10  # 10 pips\n})\n```\n\n#### Modify Order\n\n```python\n# Modify pending order\nawait client.trading.modify_order(\n    247668792,  # Order ID\n    1.0080,     # New price\n    2000        # New quantity\n)\n```\n\n#### Cancel Order\n\n```python\n# Cancel pending order\nawait client.trading.cancel_order(247668792)\n```\n\n#### Close Trade\n\n```python\n# Close open position\nresult = await client.trading.close_trade(\n    247568770,  # Trade ID\n    1000,       # Quantity to close\n    'N'         # Hedge: 'Y' or 'N'\n)\n\nprint('Closing order:', result.result.OrderID)\n```\n\n#### Hedge Trade\n\n```python\n# Hedge an open position\nresult = await client.trading.hedge_trade(\n    247568770,  # Trade ID\n    1000        # Quantity to hedge\n)\n```\n\n#### Get Open Orders\n\n```python\n# Get all open orders\nresult = await client.trading.get_open_orders()\norders = result.result\n\nfor order in orders:\n    print(f\"Order {order.OrderID}:\")\n    print(f\"  {order.Symbol} {order.Side === 1 ? 'BUY' : 'SELL'}\")\n    print(f\"  Quantity: {order.Quantity} @ {order.Price}\")\n    print(f\"  Type: {order.Type}, Status: {order.Pending}\")\n```\n\n#### Get Open Trades\n\n```python\n# Get all open positions\nresult = await client.trading.get_open_trades()\ntrades = result.result\n\nfor trade in trades:\n    print(f\"Trade {trade.TradeID}:\")\n    print(f\"  {trade.Symbol} {trade.Side === 1 ? 'BUY' : 'SELL'}\")\n    print(f\"  Quantity: {trade.Quantity} @ {trade.Price}\")\n    print(f\"  Commission: {trade.Commission}\")\n```\n\n#### Get Trade History\n\n```python\n# Get historical trades\nresult = await client.trading.get_trade_history({\n    'from_date': '2021-04-01T00:00',\n    'till': '2021-04-30T23:59',\n    'account': 100\n})\n\nhistory = result.result\n\nfor trade in history:\n    print(f\"Trade {trade.TradeID}:\")\n    print(f\"  Open: {trade.OpenPrice} -> Close: {trade.ClosePrice}\")\n    print(f\"  P&L: {trade.ProfitLoss}\")\n```\n\n#### Get Removed Orders\n\n```python\n# Get removed orders history\nresult = await client.trading.get_removed_orders({\n    'from_date': '2021-04-01T00:00',\n    'till': '2021-04-30T23:59',\n    'account': 100\n})\n```\n\n### Alerts (Deprecated)\n\n\u26a0\ufe0f **Note:** The alert module is deprecated. Please check with ActTrader for alternative solutions.\n\n```python\n# Get active alerts\nresult = await client.alert.get_alerts()\n\n# Create alert\nalert_result = await client.alert.create_alert(\n    'EUR/USD',  # Symbol\n    1.1800,     # Price\n    'BID',      # Type: 'BID' or 'ASK'\n    'Target price'  # Commentary\n)\n\n# Modify alert\nawait client.alert.modify_alert(123, 1.1850, 'BID', 'Updated target')\n\n# Remove alert\nawait client.alert.remove_alert(123)\n\n# Get triggered alerts\ntriggered = await client.alert.get_triggered_alerts(\n    '202109010000',  # From date (YYYYMMDDHH24MI)\n    '202109302359'   # Till date (YYYYMMDDHH24MI)\n)\n```\n\n### WebSocket Streaming\n\nReal-time market data and trading events via WebSocket. The SDK supports **two separate WebSocket streams** for optimal performance and separation of concerns:\n\n1. **Order Updates Stream** - Handles order events, trade events, account updates, and legacy ticker data\n2. **Price Feed Stream** - Handles price feed messages with OHLC data\n\n#### Dual WebSocket Setup (Recommended)\n\n```python\n# Create separate streaming clients\norder_stream = client.stream_orders()      # Order updates\nprice_stream = client.stream_price_feed()   # Price feed data\n\n# Connect to order updates stream\norder_stream.on('connected', lambda: print('Order stream connected'))\norder_stream.on('order', lambda data: print('Order event:', data))\norder_stream.on('trade', lambda data: print('Trade event:', data))\n\nawait order_stream.connect()\nawait order_stream.subscribe(['EURUSD', 'GBPUSD'])\n\n# Connect to price feed stream\nprice_stream.on('connected', lambda: print('Price feed stream connected'))\nprice_stream.on('pricefeed', lambda data: print('Price feed with OHLC:', data))\n\nawait price_stream.connect()\nawait price_stream.subscribe(['EURUSD', 'GBPUSD'])\n```\n\n#### Legacy Single WebSocket (Deprecated)\n\n```python\n# Create streaming client (legacy approach)\nstream = client.stream()\n\n# Connect to WebSocket\nawait stream.connect()\n\n# Handle connection events\nstream.on('connected', lambda: print('Connected to streaming server'))\nstream.on('disconnected', lambda: print('Disconnected from streaming server'))\nstream.on('error', lambda error: print('WebSocket error:', error))\n\n# Subscribe to symbols\nawait stream.subscribe(['EURUSD', 'GBPUSD', 'USDJPY'])\n\n# Handle ticker updates (price changes) - Legacy format\nstream.on('ticker', lambda data: print('Ticker update:', data))\n\n# Handle price feed updates (new format with OHLC data)\nstream.on('pricefeed', lambda data: print('Price feed update:', data))\n\n# Handle order book updates\nstream.on('orderbook', lambda data: print('Order book update:', data))\n\n# Handle order events (insert/update/delete)\nstream.on('order', lambda data: print('Order event:', data))\n\n# Handle account balance updates\nstream.on('account', lambda data: print('Account update:', data))\n\n# Handle trade events\nstream.on('trade', lambda data: print('Trade event:', data))\n\n# Handle alert triggers\nstream.on('alert', lambda data: print('Alert triggered:', data))\n\n# Handle equity warnings\nstream.on('equity_warning', lambda data: print('Equity Warning!', data))\n\n# Unsubscribe from symbols\nawait stream.unsubscribe(['USDJPY'])\n\n# Disconnect\nawait stream.disconnect()\n```\n\n#### Message Formats\n\nThe SDK supports two WebSocket message formats:\n\n**1. Legacy Ticker Format** (Order Updates)\n```python\n# Event: 'ticker'\n{\n    \"event\": \"ticker\",\n    \"payload\": [\n        {\n            \"m\": \"EURUSD\",\n            \"time\": \"2025-10-15T11:25:34.092Z\",\n            \"bid\": 1.16295,\n            \"ask\": 1.16302\n        }\n    ]\n}\n```\n\n**2. Price Feed Format** (Market Data with OHLC)\n```python\n# Event: 'pricefeed'\n{\n    \"m\": \"ticker\",\n    \"d\": [\n        {\n            \"m\": \"EURUSD\",\n            \"time\": \"2025-10-15T11:25:34.092Z\",\n            \"bid\": 1.16295,\n            \"ask\": 1.16302,\n            \"day_open\": 1.16064,\n            \"day_high\": 1.16453,\n            \"day_low\": 1.16012\n        }\n    ]\n}\n```\n\n**Usage Recommendation:**\n- Use `ticker` event for order updates and basic price data\n- Use `pricefeed` event for market data analysis with OHLC information\n\n## Complete Example\n\n```python\nimport asyncio\nfrom acttrader import ActTrader\n\nasync def main():\n    # Initialize client\n    client = ActTrader(\n        base_url='http://rest-api.sysfx.com:18001',\n        ws_url='ws://stream.sysfx.com:18002',\n        username='your_username',\n        password='your_password'\n    )\n    \n    try:\n        # Get authentication token\n        token_result = await client.auth.get_token(60)\n        print('Authenticated with token:', token_result.result)\n        \n        # Initialize symbol cache (required for lots-based trading)\n        await client.initialize_symbol_cache()\n        print('Symbol cache initialized')\n        \n        # Get accounts\n        accounts_result = await client.account.get_accounts()\n        accounts = accounts_result.result\n        print(f'Found {len(accounts)} accounts')\n        \n        # Get market symbols\n        symbols_result = await client.market.get_symbols()\n        symbols = symbols_result.result\n        print(f'Available symbols: {len(symbols)}')\n        \n        # Place a market order using LOTS (recommended)\n        order_result = await client.trading.place_market_order({\n            'symbol': 'EURUSD',\n            'lots': 0.1,       # 0.1 lots (auto-converted to quantity)\n            'side': 1,         # Buy\n            'account': accounts[0].AccountID,\n            'stop': 1.0800,    # Stop loss\n            'limit': 1.1200,   # Take profit\n            'commentary': 'Test order'\n        })\n        print('Order placed:', order_result.result.OrderID)\n        \n        # Get open trades\n        trades_result = await client.trading.get_open_trades()\n        print('Open trades:', len(trades_result.result))\n        \n        # Start streaming\n        stream = client.stream()\n        \n        def on_connected():\n            print('Streaming connected')\n            asyncio.create_task(stream.subscribe(['EURUSD', 'GBPUSD']))\n        \n        def on_ticker(data):\n            print('Price update:', data)\n        \n        stream.on('connected', on_connected)\n        stream.on('ticker', on_ticker)\n        \n        await stream.connect()\n        \n        # Keep process running\n        await asyncio.sleep(30)\n        \n        await stream.disconnect()\n        await client.auth.logout()\n        \n    except Exception as error:\n        print('Error:', error)\n\nif __name__ == '__main__':\n    asyncio.run(main())\n```\n\n## Error Handling\n\nAll API methods return a response object with the following structure:\n\n```python\nclass ApiResponse:\n    success: bool\n    message: Optional[str] = None\n    result: Optional[Any] = None\n```\n\nExample error handling:\n\n```python\ntry:\n    result = await client.trading.place_market_order({\n        'symbol': 'EURUSD',\n        'quantity': 1000,\n        'side': 1,\n        'account': 100\n    })\n    \n    if result.success:\n        print('Order ID:', result.result.OrderID)\n    else:\n        print('Order failed:', result.message)\nexcept Exception as error:\n    print('API Error:', error)\n```\n\n## Type Hints\n\nThis SDK is written with full Python type hints:\n\n```python\nfrom acttrader import ActTrader, Account, Symbol, Order, Trade, OrderSide, OrderType, ApiResponse\n\n# Full type safety\nclient = ActTrader({...})\n\nresult: ApiResponse[List[Account]] = await client.account.get_accounts()\naccounts: List[Account] = result.result\n```\n\n## API Endpoints\n\nAll dates are in Eastern Time (EST/EDT)\n\n### REST API\n- Base URL: `http://rest-api.sysfx.com:18001/`\n- API Version: v2\n- Format: `/api/v2/{module}/{endpoint}`\n\n### WebSocket\n- URL: `ws://stream.sysfx.com:18002/`\n- Connection: `ws://stream.sysfx.com:18002/ws?token={your_token}`\n\n## Development\n\n### Build from Source\n\n```bash\n# Install dependencies\npip install -r requirements.txt\n\n# Install in development mode\npip install -e .\n```\n\n### Project Structure\n\n```\nacttrader-trading-sdk/\n\u251c\u2500\u2500 acttrader/\n\u2502   \u251c\u2500\u2500 __init__.py              # Main SDK entry point\n\u2502   \u251c\u2500\u2500 main.py                  # Main ActTrader class\n\u2502   \u251c\u2500\u2500 client.py                # HTTP client with authentication\n\u2502   \u251c\u2500\u2500 types.py                 # Python type definitions\n\u2502   \u251c\u2500\u2500 digest_auth.py           # Digest authentication\n\u2502   \u251c\u2500\u2500 symbol_cache.py          # Symbol cache functionality\n\u2502   \u2514\u2500\u2500 modules/\n\u2502       \u251c\u2500\u2500 __init__.py          # Module exports\n\u2502       \u251c\u2500\u2500 auth.py              # Authentication module\n\u2502       \u251c\u2500\u2500 account.py           # Account management module\n\u2502       \u251c\u2500\u2500 market.py            # Market data module\n\u2502       \u251c\u2500\u2500 trading.py           # Trading operations module\n\u2502       \u251c\u2500\u2500 alert.py             # Alerts module (deprecated)\n\u2502       \u2514\u2500\u2500 streaming.py         # WebSocket streaming client\n\u251c\u2500\u2500 examples/                    # Example scripts\n\u251c\u2500\u2500 tests/                       # Test suite\n\u251c\u2500\u2500 setup.py                     # Package setup\n\u251c\u2500\u2500 requirements.txt             # Dependencies\n\u2514\u2500\u2500 README.md                    # This file\n```\n\n## License\n\nISC\n\n## Support\n\nFor API documentation and support, please contact ActTrader.\n\n## Contributing\n\nContributions are welcome! Please ensure your code follows the existing style and includes appropriate tests.\n\n---\n\n**Note:** This SDK requires valid ActTrader credentials and access to ActTrader API servers. All dates/times are in Eastern Time (EST/EDT).\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Official Python SDK for ActTrader Trading API",
    "version": "1.0.1",
    "project_urls": {
        "Bug Reports": "https://github.com/acttrader/python-sdk/issues",
        "Documentation": "https://github.com/acttrader/python-sdk#readme",
        "Homepage": "https://github.com/acttrader/python-sdk",
        "Source": "https://github.com/acttrader/python-sdk"
    },
    "split_keywords": [
        "acttrader",
        " trading",
        " forex",
        " api",
        " sdk",
        " trading-api",
        " market-data",
        " websocket",
        " financial",
        " broker"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "eec1c83bf03160365347354ca6e06fa49a3d54b34785faaf8525047fd4ef1d9c",
                "md5": "5cb174e8f87fc7a7a490fbbe556bba79",
                "sha256": "4f1ba7c225da23e26218487647df985738be4538fd40be402d09531b0f62f4c3"
            },
            "downloads": -1,
            "filename": "acttrader_trading_sdk-1.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5cb174e8f87fc7a7a490fbbe556bba79",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 29093,
            "upload_time": "2025-10-24T08:35:56",
            "upload_time_iso_8601": "2025-10-24T08:35:56.444682Z",
            "url": "https://files.pythonhosted.org/packages/ee/c1/c83bf03160365347354ca6e06fa49a3d54b34785faaf8525047fd4ef1d9c/acttrader_trading_sdk-1.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "06ff3fbccf8e91543db703abaeb060782781f94f13ea49a26675622c649099c1",
                "md5": "1999afc765c63b071799c14100e2e9bc",
                "sha256": "6f3a7a753459ca53b43bf4e5ab8bf166fecf730bb21d1e38baf51e5cd97b9600"
            },
            "downloads": -1,
            "filename": "acttrader_trading_sdk-1.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "1999afc765c63b071799c14100e2e9bc",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 31455,
            "upload_time": "2025-10-24T08:35:58",
            "upload_time_iso_8601": "2025-10-24T08:35:58.849668Z",
            "url": "https://files.pythonhosted.org/packages/06/ff/3fbccf8e91543db703abaeb060782781f94f13ea49a26675622c649099c1/acttrader_trading_sdk-1.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-24 08:35:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "acttrader",
    "github_project": "python-trading-sdk",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "requests",
            "specs": [
                [
                    ">=",
                    "2.28.0"
                ]
            ]
        },
        {
            "name": "websockets",
            "specs": [
                [
                    ">=",
                    "11.0.0"
                ]
            ]
        },
        {
            "name": "aiohttp",
            "specs": [
                [
                    ">=",
                    "3.8.0"
                ]
            ]
        },
        {
            "name": "asyncio-mqtt",
            "specs": [
                [
                    ">=",
                    "0.13.0"
                ]
            ]
        },
        {
            "name": "pydantic",
            "specs": [
                [
                    ">=",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "typing-extensions",
            "specs": [
                [
                    ">=",
                    "4.0.0"
                ]
            ]
        },
        {
            "name": "requests-ntlm",
            "specs": [
                [
                    ">=",
                    "1.2.0"
                ]
            ]
        },
        {
            "name": "python-dateutil",
            "specs": [
                [
                    ">=",
                    "2.8.0"
                ]
            ]
        },
        {
            "name": "ujson",
            "specs": [
                [
                    ">=",
                    "5.0.0"
                ]
            ]
        }
    ],
    "lcname": "acttrader-trading-sdk"
}
        
Act
Elapsed time: 8.57555s