async-rithmic


Nameasync-rithmic JSON
Version 1.2.6 PyPI version JSON
download
home_pagehttps://github.com/rundef/async_rithmic
SummaryPython API Integration with Rithmic Protocol Buffer API
upload_time2024-12-10 22:43:03
maintainerNone
docs_urlNone
authorMickael Burguet
requires_python>=3.8
licenseNone
keywords python rithmic
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Python Rithmic API

![PyPI - Version](https://img.shields.io/pypi/v/async_rithmic) 
[![CI](https://github.com/rundef/async_rithmic/actions/workflows/ci.yml/badge.svg)](https://github.com/rundef/async_rithmic/actions/workflows/ci.yml)
![PyPI - Downloads](https://img.shields.io/pypi/dm/async_rithmic)

A robust, async-based Python API designed to interface seamlessly with the Rithmic Protocol Buffer API. This package is built to provide an efficient and reliable connection to Rithmic's trading infrastructure, catering to advanced trading strategies and real-time data handling.

This was originally a fork of [pyrithmic](https://github.com/jacksonwoody/pyrithmic), but the code has been completely rewritten.

## Key Enhancements

This repo introduces several key improvements and new features over the original repository, ensuring compatibility with modern Python environments and providing additional functionality:

- **Python 3.11+ Compatibility**: Refactored code to ensure smooth operation with the latest Python versions.
- **System Name Validation**: Implements pre-login validation of system names, as recommended by Rithmic support, with enhanced error handling during the login process.
- **Account Selection**: Allows users to specify which account to use when calling trading functions, rather than being restricted to the primary account.
- **STOP Orders**: Exposing STOP orders to users
- **Best Bid Offer (BBO) Streaming**: Integrates real-time Best Bid Offer tick streaming. 
- **Historical Time Bars + Time Bars Streaming**

The most significant upgrade is the transition to an async architecture, providing superior performance and responsiveness when dealing with real-time trading and market data.

## Installation

```
pip install async_rithmic
```

## Market data

### Streaming Live Tick Data

Here's an example to get the front month contract for ES and stream market data:

```python
import asyncio
from async_rithmic import RithmicClient, Gateway, DataType, LastTradePresenceBits

async def callback(data: dict):
    if data["presence_bits"] & LastTradePresenceBits.LAST_TRADE:
        print("received", data)

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()

    # Request front month contract
    symbol, exchange = "ES", "CME"
    security_code = await client.get_front_month_contract(symbol, exchange)
    
    # Stream market data
    print(f"Streaming market data for {security_code}")
    data_type = DataType.LAST_TRADE
    client.on_tick += callback
    await client.subscribe_to_market_data(security_code, exchange, data_type)

    # Wait 10 seconds, unsubscribe and disconnect
    await asyncio.sleep(10)
    await client.unsubscribe_from_market_data(security_code, exchange, data_type)
    await client.disconnect()

asyncio.run(main())
```

### Streaming Live Time Bars

```python
import asyncio
from async_rithmic import RithmicClient, Gateway, TimeBarType

async def callback(data: dict):
    print("received", data)

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()

    # Request front month contract
    symbol, exchange = "ES", "CME"
    security_code = await client.get_front_month_contract(symbol, exchange)
    
    # Stream market data
    print(f"Streaming market data for {security_code}")

    client.on_time_bar += callback
    await client.subscribe_to_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)

    # Wait 10 seconds, unsubscribe and disconnect
    await asyncio.sleep(20)
    await client.unsubscribe_from_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)
    await client.disconnect()

asyncio.run(main())
```

## Order API

#### Placing a Market Order:

As a market order will be filled immediately, this script will submit the order and receive a fill straight away:

```python
import asyncio
from datetime import datetime
from async_rithmic import RithmicClient, Gateway, OrderType, ExchangeOrderNotificationType, TransactionType

async def callback(notification):
  if notification.notify_type == ExchangeOrderNotificationType.FILL:
    print("order filled", notification)

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()

    # Request front month contract
    symbol, exchange = "ES", "CME"
    security_code = await client.get_front_month_contract(symbol, exchange)
    
    # Submit order
    client.on_exchange_order_notification += callback

    order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))
    await client.submit_order(
        order_id,
        security_code,
        exchange,
        qty=1,
        order_type=OrderType.MARKET,
        transaction_type=TransactionType.SELL,
        #account_id="ABCD" # Mandatory if you have multiple accounts
        #stop_ticks=20, # Optional: you can specify a stop loss and profit target in ticks
        #target_ticks=40,
        #cancel_at=datetime.now() + timedelta(minutes=2), # Optional: cancellation datetime
    )
    
    await asyncio.sleep(1)

    await client.disconnect()

asyncio.run(main())
```

#### Placing a Limit Order and cancelling it

```python
import asyncio
from datetime import datetime
from async_rithmic import RithmicClient, Gateway, OrderType, TransactionType

async def exchange_order_notification_callback(notification):
  print("exchange order notification", notification)

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()

    # Request front month contract
    symbol, exchange = "ES", "CME"
    security_code = await client.get_front_month_contract(symbol, exchange)
    
    # Submit order
    client.on_exchange_order_notification += exchange_order_notification_callback
    
    order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))
    await client.submit_order(
        order_id,
        security_code,
        exchange,
        qty=1,
        order_type=OrderType.LIMIT,
        transaction_type=TransactionType.BUY,
        price=5300.,
    )
    
    await asyncio.sleep(1)
    await client.cancel_order(order_id=order_id)
    
    await asyncio.sleep(1)
    await client.disconnect()

asyncio.run(main())
```

## History Data API

### Fetch Historical Tick Data

The following example will fetch historical data, in a streaming fashion:

```python
import asyncio
from datetime import datetime
from async_rithmic import RithmicClient, Gateway

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()

    # Fetch historical tick data
    ticks = await client.get_historical_tick_data(
        "ESZ4",
        "CME",
        datetime(2024, 10, 15, 15, 30),
        datetime(2024, 10, 15, 15, 31),
    )

    print(f"Received {len(ticks)} ticks")
    print(f"Last tick timestamp: {ticks[-1]['datetime']}")

    await client.disconnect()

asyncio.run(main())
```

### Fetch Historical Time Bars

```python
import asyncio
from datetime import datetime
from async_rithmic import RithmicClient, Gateway, TimeBarType

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()

    # Fetch historical time bar data
    bars = await client.get_historical_time_bars(
        "ESZ4",
        "CME",
        datetime(2024, 10, 15, 15, 30),
        datetime(2024, 10, 15, 15, 31),
        TimeBarType.SECOND_BAR,
        6
    )
    
    print(f"Received {len(bars)} bars")
    print(f"Last bar timestamp: {bars[-1]['bar_end_datetime']}")

    await client.disconnect()

asyncio.run(main())
```

## Other methods

This code snippet will list your account summary, session orders and positions:

```python
import asyncio
from async_rithmic import RithmicClient, Gateway, InstrumentType

async def main():
    client = RithmicClient(user="", password="", system_name="Rithmic Test", app_name="my_test_app", app_version="1.0", gateway=Gateway.TEST)
    await client.connect()
    
    account_id = "MY_ACCOUNT"
    
    result = await client.search_symbols("MCL", instrument_type=InstrumentType.FUTURE)
    print("Search result:", result)
    
    summary = await client.list_account_summary(account_id=account_id)
    print("Account summary:", summary[0])
    
    orders = await client.list_orders(account_id=account_id)
    print("Orders:", orders)
    
    positions = await client.list_positions(account_id=account_id)
    print("Positions:", positions)

    await client.disconnect()

asyncio.run(main())
```

## Testing

To execute the tests, use the following command: `make tests`

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/rundef/async_rithmic",
    "name": "async-rithmic",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "python rithmic",
    "author": "Mickael Burguet",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/7b/c5/fe07b96e8c75003c40d9b3170f23099674a98560b4530b6c8f17deca50ed/async_rithmic-1.2.6.tar.gz",
    "platform": null,
    "description": "# Python Rithmic API\n\n![PyPI - Version](https://img.shields.io/pypi/v/async_rithmic) \n[![CI](https://github.com/rundef/async_rithmic/actions/workflows/ci.yml/badge.svg)](https://github.com/rundef/async_rithmic/actions/workflows/ci.yml)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/async_rithmic)\n\nA robust, async-based Python API designed to interface seamlessly with the Rithmic Protocol Buffer API. This package is built to provide an efficient and reliable connection to Rithmic's trading infrastructure, catering to advanced trading strategies and real-time data handling.\n\nThis was originally a fork of [pyrithmic](https://github.com/jacksonwoody/pyrithmic), but the code has been completely rewritten.\n\n## Key Enhancements\n\nThis repo introduces several key improvements and new features over the original repository, ensuring compatibility with modern Python environments and providing additional functionality:\n\n- **Python 3.11+ Compatibility**: Refactored code to ensure smooth operation with the latest Python versions.\n- **System Name Validation**: Implements pre-login validation of system names, as recommended by Rithmic support, with enhanced error handling during the login process.\n- **Account Selection**: Allows users to specify which account to use when calling trading functions, rather than being restricted to the primary account.\n- **STOP Orders**: Exposing STOP orders to users\n- **Best Bid Offer (BBO) Streaming**: Integrates real-time Best Bid Offer tick streaming. \n- **Historical Time Bars + Time Bars Streaming**\n\nThe most significant upgrade is the transition to an async architecture, providing superior performance and responsiveness when dealing with real-time trading and market data.\n\n## Installation\n\n```\npip install async_rithmic\n```\n\n## Market data\n\n### Streaming Live Tick Data\n\nHere's an example to get the front month contract for ES and stream market data:\n\n```python\nimport asyncio\nfrom async_rithmic import RithmicClient, Gateway, DataType, LastTradePresenceBits\n\nasync def callback(data: dict):\n    if data[\"presence_bits\"] & LastTradePresenceBits.LAST_TRADE:\n        print(\"received\", data)\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n\n    # Request front month contract\n    symbol, exchange = \"ES\", \"CME\"\n    security_code = await client.get_front_month_contract(symbol, exchange)\n    \n    # Stream market data\n    print(f\"Streaming market data for {security_code}\")\n    data_type = DataType.LAST_TRADE\n    client.on_tick += callback\n    await client.subscribe_to_market_data(security_code, exchange, data_type)\n\n    # Wait 10 seconds, unsubscribe and disconnect\n    await asyncio.sleep(10)\n    await client.unsubscribe_from_market_data(security_code, exchange, data_type)\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n### Streaming Live Time Bars\n\n```python\nimport asyncio\nfrom async_rithmic import RithmicClient, Gateway, TimeBarType\n\nasync def callback(data: dict):\n    print(\"received\", data)\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n\n    # Request front month contract\n    symbol, exchange = \"ES\", \"CME\"\n    security_code = await client.get_front_month_contract(symbol, exchange)\n    \n    # Stream market data\n    print(f\"Streaming market data for {security_code}\")\n\n    client.on_time_bar += callback\n    await client.subscribe_to_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)\n\n    # Wait 10 seconds, unsubscribe and disconnect\n    await asyncio.sleep(20)\n    await client.unsubscribe_from_time_bar_data(security_code, exchange, TimeBarType.SECOND_BAR, 6)\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n## Order API\n\n#### Placing a Market Order:\n\nAs a market order will be filled immediately, this script will submit the order and receive a fill straight away:\n\n```python\nimport asyncio\nfrom datetime import datetime\nfrom async_rithmic import RithmicClient, Gateway, OrderType, ExchangeOrderNotificationType, TransactionType\n\nasync def callback(notification):\n  if notification.notify_type == ExchangeOrderNotificationType.FILL:\n    print(\"order filled\", notification)\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n\n    # Request front month contract\n    symbol, exchange = \"ES\", \"CME\"\n    security_code = await client.get_front_month_contract(symbol, exchange)\n    \n    # Submit order\n    client.on_exchange_order_notification += callback\n\n    order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))\n    await client.submit_order(\n        order_id,\n        security_code,\n        exchange,\n        qty=1,\n        order_type=OrderType.MARKET,\n        transaction_type=TransactionType.SELL,\n        #account_id=\"ABCD\" # Mandatory if you have multiple accounts\n        #stop_ticks=20, # Optional: you can specify a stop loss and profit target in ticks\n        #target_ticks=40,\n        #cancel_at=datetime.now() + timedelta(minutes=2), # Optional: cancellation datetime\n    )\n    \n    await asyncio.sleep(1)\n\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n#### Placing a Limit Order and cancelling it\n\n```python\nimport asyncio\nfrom datetime import datetime\nfrom async_rithmic import RithmicClient, Gateway, OrderType, TransactionType\n\nasync def exchange_order_notification_callback(notification):\n  print(\"exchange order notification\", notification)\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n\n    # Request front month contract\n    symbol, exchange = \"ES\", \"CME\"\n    security_code = await client.get_front_month_contract(symbol, exchange)\n    \n    # Submit order\n    client.on_exchange_order_notification += exchange_order_notification_callback\n    \n    order_id = '{0}_order'.format(datetime.now().strftime('%Y%m%d_%H%M%S'))\n    await client.submit_order(\n        order_id,\n        security_code,\n        exchange,\n        qty=1,\n        order_type=OrderType.LIMIT,\n        transaction_type=TransactionType.BUY,\n        price=5300.,\n    )\n    \n    await asyncio.sleep(1)\n    await client.cancel_order(order_id=order_id)\n    \n    await asyncio.sleep(1)\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n## History Data API\n\n### Fetch Historical Tick Data\n\nThe following example will fetch historical data, in a streaming fashion:\n\n```python\nimport asyncio\nfrom datetime import datetime\nfrom async_rithmic import RithmicClient, Gateway\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n\n    # Fetch historical tick data\n    ticks = await client.get_historical_tick_data(\n        \"ESZ4\",\n        \"CME\",\n        datetime(2024, 10, 15, 15, 30),\n        datetime(2024, 10, 15, 15, 31),\n    )\n\n    print(f\"Received {len(ticks)} ticks\")\n    print(f\"Last tick timestamp: {ticks[-1]['datetime']}\")\n\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n### Fetch Historical Time Bars\n\n```python\nimport asyncio\nfrom datetime import datetime\nfrom async_rithmic import RithmicClient, Gateway, TimeBarType\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n\n    # Fetch historical time bar data\n    bars = await client.get_historical_time_bars(\n        \"ESZ4\",\n        \"CME\",\n        datetime(2024, 10, 15, 15, 30),\n        datetime(2024, 10, 15, 15, 31),\n        TimeBarType.SECOND_BAR,\n        6\n    )\n    \n    print(f\"Received {len(bars)} bars\")\n    print(f\"Last bar timestamp: {bars[-1]['bar_end_datetime']}\")\n\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n## Other methods\n\nThis code snippet will list your account summary, session orders and positions:\n\n```python\nimport asyncio\nfrom async_rithmic import RithmicClient, Gateway, InstrumentType\n\nasync def main():\n    client = RithmicClient(user=\"\", password=\"\", system_name=\"Rithmic Test\", app_name=\"my_test_app\", app_version=\"1.0\", gateway=Gateway.TEST)\n    await client.connect()\n    \n    account_id = \"MY_ACCOUNT\"\n    \n    result = await client.search_symbols(\"MCL\", instrument_type=InstrumentType.FUTURE)\n    print(\"Search result:\", result)\n    \n    summary = await client.list_account_summary(account_id=account_id)\n    print(\"Account summary:\", summary[0])\n    \n    orders = await client.list_orders(account_id=account_id)\n    print(\"Orders:\", orders)\n    \n    positions = await client.list_positions(account_id=account_id)\n    print(\"Positions:\", positions)\n\n    await client.disconnect()\n\nasyncio.run(main())\n```\n\n## Testing\n\nTo execute the tests, use the following command: `make tests`\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Python API Integration with Rithmic Protocol Buffer API",
    "version": "1.2.6",
    "project_urls": {
        "Bug Reports": "https://github.com/rundef/async_rithmic/issues",
        "Documentation": "https://github.com/rundef/async_rithmic",
        "Homepage": "https://github.com/rundef/async_rithmic",
        "Source Code": "https://github.com/rundef/async_rithmic"
    },
    "split_keywords": [
        "python",
        "rithmic"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e17e8e3ba4cb50237e750edd9e3253946b1d9e2df3ef2f1ee9307c8f50a24217",
                "md5": "f86d9df1e6d998c5891c3edc1cb55315",
                "sha256": "06b4e2d05b6efb7234e43fec69781d268754ec1550f2c2e54b237e69461a6bf2"
            },
            "downloads": -1,
            "filename": "async_rithmic-1.2.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f86d9df1e6d998c5891c3edc1cb55315",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 94383,
            "upload_time": "2024-12-10T22:43:01",
            "upload_time_iso_8601": "2024-12-10T22:43:01.850428Z",
            "url": "https://files.pythonhosted.org/packages/e1/7e/8e3ba4cb50237e750edd9e3253946b1d9e2df3ef2f1ee9307c8f50a24217/async_rithmic-1.2.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7bc5fe07b96e8c75003c40d9b3170f23099674a98560b4530b6c8f17deca50ed",
                "md5": "7571f5e079259307c3e743e3a2e79952",
                "sha256": "3501ba895d483d74676caba7e871ff44a34c915a447c881ae6cef641ae02ec69"
            },
            "downloads": -1,
            "filename": "async_rithmic-1.2.6.tar.gz",
            "has_sig": false,
            "md5_digest": "7571f5e079259307c3e743e3a2e79952",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 38993,
            "upload_time": "2024-12-10T22:43:03",
            "upload_time_iso_8601": "2024-12-10T22:43:03.959340Z",
            "url": "https://files.pythonhosted.org/packages/7b/c5/fe07b96e8c75003c40d9b3170f23099674a98560b4530b6c8f17deca50ed/async_rithmic-1.2.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-10 22:43:03",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "rundef",
    "github_project": "async_rithmic",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "async-rithmic"
}
        
Elapsed time: 0.39096s