Skip to main content

Python wrapper for the Rotman Interactive Trader (RIT) REST API

Project description

RIT API Client

Python Version

A comprehensive Python wrapper for the Rotman Interactive Trader (RIT) REST API with built-in error handling, rate limiting, and pandas DataFrame support.

Features

  • Clean API: Intuitive methods for all RIT endpoints
  • DataFrame Support: Automatic conversion of API responses to pandas DataFrames
  • Error Handling: Robust exception handling for all error scenarios
  • Rate Limiting: Automatic retry logic for rate-limited requests
  • Type Safety: Type hints throughout for better IDE support
  • Case Flexibility: Graceful handling of endpoints not available in specific cases
  • Full Coverage: All endpoints from RIT API specification implemented

Installation

From Source (Development)

# Clone repository
git clone https://github.com/luiss-rotman/rotman-challenge.git
cd rotman-challenge/COM

# Install package in development mode
uv pip install -e .

From PyPI (Once Published)

uv pip install rit-client

Configuration

  1. Create a .env file:

    cp .env.example .env
    
  2. Add your RIT API key:

    RIT_API_KEY=your_actual_api_key_here
    

Quick Start

from rit_client import RITClient

# Initialize client (automatically loads .env)
client = RITClient()

# Get case information
case_info = client.get_case()
print(f"Case: {case_info['name']}, Status: {case_info['status']}")

# Get all securities as a DataFrame
securities = client.get_securities()
print(securities[['ticker', 'position', 'last', 'bid', 'ask']])

# Get news feed
news = client.get_news(limit=5)
for _, item in news.iterrows():
    print(f"{item['headline']}: {item['body']}")

# Get order book for a security
book = client.get_order_book('CRZY')
print("Bids:", book['bid'])
print("Asks:", book['ask'])

API Reference

Case Information

# Get case details
case = client.get_case()

# Check if case is active
if client.is_case_active():
    print("Case is running!")

Trader Information

# Get trader info
trader = client.get_trader()
print(f"NLV: ${trader['nlv']:,.2f}")

# Quick NLV check
nlv = client.get_nlv()

Securities

# Get all securities
securities = client.get_securities()

# Get specific security
security = client.get_security('CRZY')

# Get order book
book = client.get_order_book('CRZY', limit=10)

# Get price history (OHLC)
history = client.get_security_history('CRZY', limit=100)

# Get time & sales
tas = client.get_time_and_sales('CRZY', limit=50)

News

# Get latest news
news = client.get_news(limit=10)

# Get news after specific ID
news = client.get_news(after=150)

# Get single most recent news item
latest = client.get_latest_news()

Orders

Note: Order endpoints may not be available in all cases (e.g., Commodities case).

# Get open orders
orders = client.get_open_orders()

# Submit a market order (with error handling)
try:
    order = client.submit_order(
        ticker='CRZY',
        order_type='MARKET',
        quantity=100,
        action='BUY'
    )
except EndpointNotAvailableException:
    print("Orders not available in this case")

# Submit a limit order
order = client.submit_order(
    ticker='CRZY',
    order_type='LIMIT',
    quantity=100,
    action='SELL',
    price=15.50
)

# Cancel order
client.cancel_order(order_id=123)

# Cancel all orders
cancelled = client.cancel_all_orders()

# Cancel by ticker
cancelled = client.cancel_orders_by_ticker('CRZY')

Assets (Commodities Cases)

# Get available assets
assets = client.get_assets()

# Get asset history
history = client.get_asset_history(ticker='CONTAINER')

# Lease an asset
lease = client.lease_asset('CONTAINER')

# Use a leased asset (e.g., refinery)
result = client.use_leased_asset(
    lease_id=1,
    from_tickers=['CRUDE'],
    quantities=[100]
)

# Get active leases
leases = client.get_leases()

# Cancel a lease
client.cancel_lease(lease_id=1)

Trading Limits

# Get trading limits
limits = client.get_limits()
print(limits[['name', 'gross', 'net', 'gross_limit', 'net_limit']])

Tenders

# Get active tenders
tenders = client.get_tenders()

# Accept a tender
client.accept_tender(tender_id=5, price=10.50)

# Decline a tender
client.decline_tender(tender_id=5)

Utility Methods

# Get complete market snapshot
snapshot = client.get_market_snapshot()
# Returns: {'case', 'trader', 'securities', 'limits', 'news', 'orders'}

print(snapshot['securities'])
print(snapshot['news'])

Error Handling

The library provides specific exceptions for different error scenarios:

from rit_client import RITClient
from rit_exceptions import (
    RateLimitException,
    AuthenticationException,
    EndpointNotAvailableException,
    OrderException,
    InvalidParameterException
)

client = RITClient()

try:
    order = client.submit_order(
        ticker='CRZY',
        order_type='LIMIT',
        quantity=100,
        action='BUY',
        price=15.0
    )
except EndpointNotAvailableException:
    print("Orders not available in this case (e.g., Commodities)")
except OrderException as e:
    print(f"Order failed: {e}")
except RateLimitException as e:
    print(f"Rate limited, wait {e.wait_time} seconds")
except AuthenticationException:
    print("Check your API key")

Real-Time Data Streaming

import time

client = RITClient()
last_news_id = 0

while client.is_case_active():
    # Get case info
    case = client.get_case()
    print(f"Tick: {case['tick']}")

    # Check for new news
    news = client.get_news(after=last_news_id, limit=10)
    for _, item in news.iterrows():
        if item['news_id'] > last_news_id:
            print(f"NEWS: {item['headline']}")
            last_news_id = item['news_id']

    # Get current securities data
    securities = client.get_securities()

    # Your trading logic here...

    time.sleep(0.5)  # Avoid rate limiting

Data Analysis Example

import pandas as pd

client = RITClient()

# Download historical data
all_history = {}
securities = client.get_securities()

for ticker in securities['ticker']:
    history = client.get_security_history(ticker, limit=100)
    all_history[ticker] = history

# Analyze and save
for ticker, df in all_history.items():
    df.to_csv(f'data/{ticker}_history.csv', index=False)

    # Calculate statistics
    avg_price = df['close'].mean()
    volatility = df['close'].std()
    print(f"{ticker}: Avg={avg_price:.2f}, Vol={volatility:.2f}")

Configuration

All configuration is done via environment variables in .env:

# Required
RIT_API_KEY=your_api_key_here

# Optional (with defaults)
RIT_BASE_URL=http://localhost:9999/v1
RIT_MAX_RETRIES=3
RIT_RETRY_DELAY=0.5
RIT_TIMEOUT=10

You can also pass configuration directly:

client = RITClient(
    api_key='your_key',
    base_url='http://localhost:9999/v1',
    max_retries=5,
    timeout=15
)

Rate Limiting

The client automatically handles rate limiting:

  • Retries requests when rate limited
  • Uses Retry-After header from API
  • Configurable max retries and delays
  • Raises RateLimitException if max retries exceeded

Case Compatibility

Different RIT cases support different endpoints:

Endpoint Commodities Options Algorithm Liquidity
Securities
Orders (POST)
Assets
Leases
Tenders ✅*

*Depends on specific case configuration

The library gracefully handles unavailable endpoints with EndpointNotAvailableException.

Examples

See example_usage.py for comprehensive examples:

python example_usage.py

Module Structure

COM/
├── rit_client.py          # Main client class
├── rit_exceptions.py      # Custom exceptions
├── config.py              # Configuration management
├── example_usage.py       # Usage examples
├── .env.example           # Environment template
├── pyproject.toml         # Dependencies
└── README.md             # This file

Best Practices

  1. Always use try-except for endpoint calls that may not be available
  2. Check case status before placing orders
  3. Respect rate limits by adding delays in loops
  4. Save data regularly during long-running cases
  5. Use dry_run for testing order logic without execution

Troubleshooting

API Key Issues

# Check if API key is loaded
from config import Config
Config.validate()  # Raises error if key missing

Connection Issues

  • Ensure RIT Client is running
  • Check that API is enabled in RIT Client (green API icon)
  • Verify base URL matches RIT Client port

Rate Limiting

  • Add time.sleep() between requests in loops
  • Increase RIT_RETRY_DELAY in .env
  • Reduce polling frequency

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

ritpy-0.1.0.tar.gz (10.6 kB view details)

Uploaded Source

Built Distribution

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

ritpy-0.1.0-py3-none-any.whl (12.4 kB view details)

Uploaded Python 3

File details

Details for the file ritpy-0.1.0.tar.gz.

File metadata

  • Download URL: ritpy-0.1.0.tar.gz
  • Upload date:
  • Size: 10.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.3

File hashes

Hashes for ritpy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 82d56c5700c9e95e662497e5501df10ef2281f95c6e0bd481993422f835b8232
MD5 a051095d45db5c4d1e27dc199be886c3
BLAKE2b-256 36da448db1cb12a5f3ce7a6066f688aa8af3cfd00ea97bc0ecd44c708903ab27

See more details on using hashes here.

File details

Details for the file ritpy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ritpy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.3

File hashes

Hashes for ritpy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4032c3df13139a7cd852255b83f9491e2f2423913925d0febf5fc8306fd127ac
MD5 6707f1d70629822dd30c436c687251e1
BLAKE2b-256 43ceeddc588eabdacfd88719aee26433ae532f7de65db489169ad976db5c502c

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