Skip to main content

Python client library for the Volare Signals API

Project description

Volare Signals Python Client

A production-ready Python client library for the Volare Signals API, providing access to algorithmic trading signals, upgrades, downgrades, and more.

Features

  • Full coverage of all Volare Signals API endpoints
  • Both synchronous and asynchronous clients
  • Comprehensive type hints with Pydantic models
  • Automatic retry logic with exponential backoff
  • Rate limit handling and tracking
  • Custom exception hierarchy for granular error handling
  • Context manager support for proper resource cleanup

Installation

Using pip

pip install volare-signals

Using Poetry

poetry add volare-signals

From source

git clone https://github.com/volaretrading/volare-signals-python.git
cd volare-signals-python
pip install -e .

Quick Start

Basic Usage

from volare_signals import VolareSignalsClient

# Create a client with your API key
client = VolareSignalsClient(api_key="vk_your_api_key_here")

# Get signal history for a specific date
response = client.get_history(date="2024-01-15", limit=100)

# Iterate through signals
for signal in response.data.signals:
    print(f"{signal.symbol}: Rating {signal.rating} ({signal.side.value})")

# Check rate limits
print(f"Requests remaining: {response.rate_limit.remaining_minute}/min")

# Don't forget to close the client
client.close()

Using Context Manager (Recommended)

from volare_signals import VolareSignalsClient

with VolareSignalsClient(api_key="vk_your_api_key") as client:
    # Get strong buy signals
    response = client.get_strong_buys(date="2024-01-15")

    for signal in response.data.signals:
        print(f"Strong Buy: {signal.symbol}")
        if signal.entry_price:
            print(f"  Entry Price: ${signal.entry_price:.2f}")

Async Usage

import asyncio
from volare_signals import AsyncVolareSignalsClient

async def main():
    async with AsyncVolareSignalsClient(api_key="vk_your_api_key") as client:
        # Fetch multiple endpoints concurrently
        history, upgrades, downgrades = await asyncio.gather(
            client.get_history(date="2024-01-15"),
            client.get_upgrades(date="2024-01-15", min_change=2),
            client.get_downgrades(date="2024-01-15", max_change=-2),
        )

        print(f"Total signals: {history.data.count}")
        print(f"Upgrades: {upgrades.data.count}")
        print(f"Downgrades: {downgrades.data.count}")

asyncio.run(main())

API Reference

Client Initialization

from volare_signals import VolareSignalsClient, RetryConfig

client = VolareSignalsClient(
    api_key="vk_your_api_key",           # Required: Your API key
    base_url="https://api.volaretrading.com",  # Optional: Override base URL
    timeout=30.0,                         # Optional: Request timeout in seconds
    retry_config=RetryConfig(             # Optional: Retry configuration
        max_retries=3,
        base_delay=1.0,
        max_delay=60.0,
    ),
)

Available Methods

get_history(date, min_rating, max_rating, limit)

Get historical signals for a given date.

response = client.get_history(
    date="2024-01-15",    # Date in YYYY-MM-DD format or date object
    min_rating=5,         # Optional: Minimum rating (1-10)
    max_rating=10,        # Optional: Maximum rating (1-10)
    limit=100,            # Optional: Max signals to return (1-1000)
)

get_strong_buys(date, limit)

Get signals with high ratings (typically 8-10).

response = client.get_strong_buys(date="2024-01-15", limit=50)

get_strong_sells(date, limit)

Get signals with low ratings (typically 1-3).

response = client.get_strong_sells(date="2024-01-15", limit=50)

get_upgrades(date, min_change, limit)

Get signals that were upgraded from a previous rating.

response = client.get_upgrades(
    date="2024-01-15",
    min_change=2,         # Minimum positive rating change
    limit=100,
)

get_downgrades(date, max_change, limit)

Get signals that were downgraded from a previous rating.

response = client.get_downgrades(
    date="2024-01-15",
    max_change=-2,        # Maximum (most negative) rating change
    limit=100,
)

get_new_signals(date, limit)

Get newly generated signals (no previous rating).

response = client.get_new_signals(date="2024-01-15", limit=100)

Data Models

Signal

from volare_signals import Signal, Side

signal: Signal
signal.date           # str: Signal date (YYYY-MM-DD)
signal.symbol         # str: Ticker symbol
signal.rating         # int: Rating from 1-10
signal.side           # Side: LONG or SHORT
signal.previous_rating  # Optional[int]: Previous rating
signal.rating_change  # int: Change from previous rating
signal.entry_price    # Optional[float]: Suggested entry price
signal.supporting_algos  # list[SupportingAlgo]: Contributing algorithms
signal.rating_breakdown  # Optional[dict]: Detailed rating breakdown

Rate Limit Info

from volare_signals import RateLimitInfo

rate_limit: RateLimitInfo
rate_limit.limit_per_minute    # int: Max requests per minute (60)
rate_limit.limit_per_day       # int: Max requests per day (500)
rate_limit.remaining_minute    # Optional[int]: Remaining minute requests
rate_limit.remaining_day       # Optional[int]: Remaining day requests
rate_limit.is_minute_exhausted # bool: Check if minute limit reached
rate_limit.is_day_exhausted    # bool: Check if day limit reached

Error Handling

The client provides a hierarchy of exceptions for different error types:

from volare_signals import (
    VolareAPIError,          # Base exception
    ValidationError,         # 400: Invalid parameters
    AuthenticationError,     # 401: Invalid/missing API key
    ForbiddenError,          # 403: Revoked/expired API key
    RateLimitExceededError,  # 429: Rate limit exceeded
    ServerError,             # 500: Server error
    NetworkError,            # Connection/timeout errors
    RetryExhaustedError,     # All retries failed
)

try:
    response = client.get_history(date="2024-01-15")
except ValidationError as e:
    print(f"Invalid parameter: {e.field} - {e.message}")
except AuthenticationError:
    print("Check your API key")
except RateLimitExceededError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except VolareAPIError as e:
    print(f"API error: {e}")

Retry Configuration

The client includes automatic retry logic for transient errors:

from volare_signals import VolareSignalsClient, RetryConfig

config = RetryConfig(
    max_retries=3,            # Number of retry attempts
    base_delay=1.0,           # Initial delay in seconds
    max_delay=60.0,           # Maximum delay between retries
    exponential_base=2.0,     # Exponential backoff multiplier
    jitter=True,              # Add randomness to delays
    retry_on_server_error=True,  # Retry on 5xx errors
)

client = VolareSignalsClient(
    api_key="vk_your_api_key",
    retry_config=config,
)

Retryable errors:

  • RateLimitExceededError (429)
  • ServerError (500)
  • NetworkError (connection/timeout)

Rate Limits

The Volare Signals API has the following rate limits:

  • 60 requests per minute
  • 500 requests per day

Rate limit information is available in every response:

response = client.get_history(date="2024-01-15")

# From the response
print(f"Remaining this minute: {response.rate_limit.remaining_minute}")
print(f"Remaining today: {response.rate_limit.remaining_day}")

# From the client (last request)
print(f"Last rate limit: {client.last_rate_limit}")

Development

Setup

# Clone the repository
git clone https://github.com/volaretrading/volare-signals-python.git
cd volare-signals-python

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install development dependencies
pip install -e ".[dev]"

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=volare_signals --cov-report=html

# Run specific test file
pytest unit_tests/test_client.py -v

Code Quality

# Format code
ruff format .

# Lint code
ruff check .

# Type check
mypy src/volare_signals

Releasing

The package version is defined in pyproject.toml. To release a new version:

# 1. Update version in pyproject.toml
# 2. Commit the change
git add pyproject.toml
git commit -m "Bump version to X.Y.Z"

# 3. Create a version tag
git tag vX.Y.Z

# 4. Push commit and tag
git push && git push --tags

When a tag matching v* is pushed, CI will automatically build and publish the package to PyPI using trusted publishing.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

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

volare_signals-1.0.3.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

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

volare_signals-1.0.3-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file volare_signals-1.0.3.tar.gz.

File metadata

  • Download URL: volare_signals-1.0.3.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for volare_signals-1.0.3.tar.gz
Algorithm Hash digest
SHA256 f6a4f97f8993aa2fe2757177fc10bdcf2e5aa956966ffe4c641fae274abae09d
MD5 e321d8e8d608eb619311ce67defe6b5d
BLAKE2b-256 6f5494b1cbcb25f4384f7c37098c5356e01b1b29d08188579169455e90c71801

See more details on using hashes here.

Provenance

The following attestation bundles were made for volare_signals-1.0.3.tar.gz:

Publisher: ci.yml on yushdotkapoor/volare-signals-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file volare_signals-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: volare_signals-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for volare_signals-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 d32fea5a3f87c38d8b62a02619dacba4768218d4694e5102b01f5cbc69ed7fbb
MD5 d75a9cd1285a0d335e599f38ba235a2a
BLAKE2b-256 669eaa70d4f2e3e47485dd55f553d57f79953d919bc8a3ad998d4c947947e34f

See more details on using hashes here.

Provenance

The following attestation bundles were made for volare_signals-1.0.3-py3-none-any.whl:

Publisher: ci.yml on yushdotkapoor/volare-signals-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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