Python wrapper for the Rotman Interactive Trader (RIT) REST API
Project description
RIT API Client
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
-
Create a
.envfile:cp .env.example .env
-
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-Afterheader from API - Configurable max retries and delays
- Raises
RateLimitExceptionif 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
- Always use try-except for endpoint calls that may not be available
- Check case status before placing orders
- Respect rate limits by adding delays in loops
- Save data regularly during long-running cases
- 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_DELAYin.env - Reduce polling frequency
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
82d56c5700c9e95e662497e5501df10ef2281f95c6e0bd481993422f835b8232
|
|
| MD5 |
a051095d45db5c4d1e27dc199be886c3
|
|
| BLAKE2b-256 |
36da448db1cb12a5f3ce7a6066f688aa8af3cfd00ea97bc0ecd44c708903ab27
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4032c3df13139a7cd852255b83f9491e2f2423913925d0febf5fc8306fd127ac
|
|
| MD5 |
6707f1d70629822dd30c436c687251e1
|
|
| BLAKE2b-256 |
43ceeddc588eabdacfd88719aee26433ae532f7de65db489169ad976db5c502c
|