/txTrader

Securities Trading API controller using Twisted (IB-TWS, CQG, Realtick)

Primary LanguagePythonMIT LicenseMIT

txTrader - Twisted Trading API Controller

txTrader aims to eliminate the complexity of managing and interacting with multiple trading system APIs, presenting a native python interface.

Features

  • Cross-Platform securities trading API management engine
  • Provides a trader's eye view of the interaction with the trading system API.
  • Decouples business logic from low-level implementation details of interaction with the broker's API
  • Maintains internal data structures used to verify each step of the order management / trade execution transaction.
  • Supports fault-tolerance by maintaining a continuous connection with the API in the event of application failure.
  • Frees trading software design from timing and architectural constraints imposed by the API implementation.
  • Built on the mature and reliable twisted python networking engine.

Description

This system aims to present an interface to trading software composed of objects, procedures, and events that fit naturally into the design of an automated trading system. Common trading system APIs often expose implementation details such as message packet parsing, message and field IDs. They often have specific OS and development environment requirements. Their use commonly requires the client application to support advanced programming techniques like blocking, threading, and event handling mechanisms. This design seems to represent the point of view of the trading software implementer. A goal of txTrader is to decouple the application software from strict timing and sequencing requirements.

This software implements interfaces to the API for CQG's CQGNet application and Interactive Brokers' Trader Workstation. A version has been implemented for the Realtick API, but has a dependency on a closed-source gateway. The system provides access to real-time market data, historical pricing, bar charts, order management, execution reports, and position data.

The gateway is built on the twisted python networking engine. Clients can establish a long-lived TCP/IP streaming data connection using the Netstring protocol, and/or utilize a set of JSON-RPC functions. Both services are password protected using basic authentication and a password handshake. Support for TLS connections with server and client certificates is planned.

Common interface code is used to provide a normalized interface to the managed API. While the contents of the returned objects may differ, many fields are common to the supported environments.

Status change events are available on the TCP/IP streaming service. The data are JSON formatted objects.

Client Access

The txtrader-client module exposes the server functions to a client program as local python callables. The txtrader-monitor module is used to receive asynchronous events from the TCP channel. The object is configured by passing a dict with channel names and python functions to be called when data of the desired type is received.

The JSON-RPC functions may be accessed without using the client library as follows:

curl "http://${TXTRADER_USERNAME}:${TXTRADER_PASSWORD}@${TXTRADER_HOST}:${TXTRADER_HTTP_PORT}/query_orders"

See the client access projects for usage examples.

Dependencies

TxTrader's server daemons depend on external libraries for each configured API:

Installation

The fastest way to get started is to use PyPI

pip install txtrader txtrader-client txtrader-monitor

Run as a local daemon process

txtraderd &

Run in a Docker container

docker start rstms/txtrader:latest

Configuration

At startup of a local process or as a docker container, environment variables are read to set configuration. Each variable has a default value that will be used if it is not present.

To read configuration from a file, use a tool like envdir or cfgdir or a bash script may be used to set the desired variables.

Variable Description
TXTRADER_USERNAME txtrader_user
TXTRADER_PASSWORD txtrader_pass
TXTRADER_HTTP_PORT 50080
TXTRADER_TCP_PORT 50090
TXTRADER_DAEMON_REACTOR poll
TXTRADER_DAEMON_LOGFILE -
TXTRADER_MODE rtx
TXTRADER_DAEMON_PIDFILE ''
TXTRADER_API_HOST localhost
TXTRADER_API_PORT 51070
TXTRADER_API_ACCOUNT api_account
TXTRADER_API_TIMEZONE America/New_York
TXTRADER_API_ROUTE DEMO
TXTRADER_API_CLIENT_ID 0
TXTRADER_ENABLE_TICKER 0
TXTRADER_ENABLE_HIGH_LOW 1
TXTRADER_ENABLE_BARCHART 1
TXTRADER_ENABLE_SYMBOL_BARCHART 0
TXTRADER_ENABLE_SECONDS_TICK 1
TXTRADER_ENABLE_EXCEPTION_HALT 0
TXTRADER_LOG_API_MESSAGES 0
TXTRADER_DEBUG_API_MESSAGES 0
TXTRADER_LOG_CLIENT_MESSAGES 0
TXTRADER_LOG_HTTP_REQUESTS 1
TXTRADER_LOG_HTTP_RESPONSES 0
TXTRADER_LOG_ORDER_UPDATES 0
TXTRADER_TIME_OFFSET 0
TXTRADER_SUPPRESS_ERROR_CODES 2100
TXTRADER_TIMEOUT_DEFAULT 15
TXTRADER_TIMEOUT_ACCOUNT 15
TXTRADER_TIMEOUT_ADDSYMBOL 15
TXTRADER_TIMEOUT_BARCHART 10
TXTRADER_TIMEOUT_ORDER 300
TXTRADER_TIMEOUT_ORDERSTATUS 3600
TXTRADER_TIMEOUT_POSITION 20
TXTRADER_TIMEOUT_TIMER 10
TXTRADER_ENABLE_AUTO_RESET 1
TXTRADER_LOCAL_RESET_TIME "05:00"

Security

This version of the sofware is designed to be used on private internal infrastructure. It is NOT intended to be exposed to the public Internet. TxTrader currently doesn't implement HTTPS and the password mechanism is rudimentary. It is strongly recommended that access control be implemented at the network level.

Security mechanisms used in existing deployments include:

  • virtual machine private networking
  • local private network addressing
  • VPN
  • docker container networking
  • ssh port forwarding
  • firewall rules

Contact the author for additional info: mkrueger@rstms.net

JSONRPC Server

The server implements the following JSONRPC calls:


TxTrader Securities Trading API Controller 1.14.25 2020-08-10 02:23:00

add_symbol('symbol')

        Request subscription to a symbol for price updates and order entry
        
cancel_order('id')

        Request cancellation of a pending order
        
del_symbol('symbol')

        Delete subscription to a symbol for price updates and order entry
        
gateway_logoff()

        Logoff from gateway
        
gateway_logon('username', 'password')

        logon to gateway
        
get_order_route() => {'route_name', None | {parameter_name: parameter_value, ...}}

        Return current order route as a dict
        
global_cancel()

        Request cancellation of all pending orders
        
help() => {'command': 'command(parameters) => return', ...}

        Return dict containing brief documentation for each command
        
limit_order('account', 'route', 'symbol', price, quantity) => {'field':, data, ...}

        Submit a limit order, returning dict containing new order fields
        
market_order('account', 'route', 'symbol', quantity) => {'field':, data, ...}

        Submit a market order, returning dict containing new order fields
        
query_account(account, fields) => {'key': (value, currency), ...}

        Query account data for account. fields is list of fields to select; None=all fields
        
query_accounts() => ['account_name', ...]

        Return array of account names
        
query_bars('symbol', bar_period, 'start', 'end')
              => ['Status: OK', [time, open, high, low, close, volume], ...]

        Return array containing status strings and lists of bar data if successful
        
query_execution('id') => {'fieldname': data, ...}

        Return dict containing execution report data fields
        
query_executions() => {'exec_id': {'field': data, ...}, ...}

        Return dict keyed by execution id containing dicts of execution report data fields
        
query_order('id') => {'fieldname': data, ...}

        Return dict containing order/ticket status fields for given order id
        
query_executions() => {'exec_id': {'field': data, ...}, ...}

        Return dict keyed by execution id containing dicts of execution report data fields given order_id
        
query_orders() => {'order_id': {'field': data, ...}, ...}

        Return dict keyed by order id containing dicts of order data fields
        
query_positions() => {'account': {'fieldname': data, ...}, ...}

        Return dict keyed by account containing dicts of position data fields
        
query_symbol('symbol') => {'fieldname': data, ...}

        Return dict containing current data for given symbol
        
query_symbol_bars('symbol') => [[barchart data], ...]

        Return array of current live bar data for given symbol
        
query_symbol_data('symbol') => {'fieldname': data, ...}

        Return dict containing rawdata for given symbol
        
query_symbols() => ['symbol', ...]

        Return the list of active symbols
        
query_tickets() => {'order_id': {'field': data, ...}, ...}

        Return dict keyed by order id containing dicts of staged order ticket data fields
        
set_account('account')

        Select current active trading account.
        
set_order_route(route) => True if success, else False

        Set order route data given route {'route_name': {parameter: value, ...} (JSON string will be parsed into a route dict)}
        
set_primary_exchange(symbol, exchange)

        Set primary exchange for symbol (default is SMART), delete mapping if exchange is None.
        
shutdown(message) 

        Request server shutdown
        
stage_market_order('tag', 'account', 'route', 'symbol', quantity) => {'fieldname': data, ...}

        Submit a staged market order (displays as staged in GUI, requiring manual aproval), returning dict containing new order fields
        
status() => 'status string'

        return string describing current API connection status
        
stop_order('account', 'route', 'symbol', price, quantity) => {'field':, data, ...}

        Submit a stop order, returning dict containing new order fields
        
stoplimit_order('account', 'route', 'symbol', stop_price, limit_price, quantity) => {'field':, data, ...}

        Submit a stop-limit order, returning dict containing new order fields
        
time() => 'time string'

        Return formatted timestamp string (YYYY-MM-DD HH:MM:SS) matching latest datafeed time update
        
uptime() => 'uptime string'

        Return string showing start time and elapsed time for current server instance
        
version() => 'version string'

        Return string containing release version of current server instance