A lightweight Python library for algorithmic trading and market analysis
Project description
OpenStoxlify 📈
A lightweight Python library for algorithmic trading and market analysis with professional-grade visualizations.
✨ Key Features
- Multi-source data: Fetch from Yahoo Finance, Binance, and more
- Context-based API: Clean, fluent interface for strategy development
- Strategy engine: Record and visualize trading signals
- Professional charts: OHLC candles, indicators, and strategy markers
- Flexible outputs: Interactive plots and JSON for programmatic use
🚀 Quick Start
from openstoxlify.context import Context
from openstoxlify.draw import Canvas
from openstoxlify.models.enum import ActionType, DefaultProvider, Period, PlotType
from openstoxlify.models.series import ActionSeries, FloatSeries
from openstoxlify.providers.stoxlify.provider import Provider
# 1. Initialize provider and context
provider = Provider(DefaultProvider.YFinance)
ctx = Context(provider, "AAPL", Period.DAILY)
# 2. Get market data
quotes = ctx.quotes()
# 3. Plot closing prices
for quote in quotes:
ctx.plot("Close", PlotType.LINE, FloatSeries(quote.timestamp, quote.close))
# 4. Add trading signals
ctx.signal(ActionSeries(quotes[0].timestamp, ActionType.LONG, 1.0))
# 5. Visualize
canvas = Canvas(ctx)
canvas.draw()
📦 Installation
Basic Installation
pip install openstoxlify
For Development
git clone https://github.com/michaelahli/openstoxlify.git
cd openstoxlify
make clean setup
source .venv/bin/activate # or `venv/bin/activate`
python examples/getting_started.py
Requirements
| Package | Minimum Version | Notes |
|---|---|---|
| Python | 3.8+ | |
| grpcio | 1.50+ | For data provider communication |
| matplotlib | 3.5+ | Required for visualization |
| protobuf | 4.0+ | For protocol buffers |
Troubleshooting
-
Missing Dependencies:
pip install --upgrade grpcio matplotlib protobuf
-
Permission Issues (Linux/Mac):
pip install --user openstoxlify
-
Conda Users:
conda install -c conda-forge grpcio matplotlib pip install openstoxlify
📊 Core Components
1. Context - The Trading Context Manager
The Context class is the heart of OpenStoxlify. It manages your market data, plots, and trading signals in one place.
from openstoxlify.context import Context
from openstoxlify.providers.stoxlify.provider import Provider
from openstoxlify.models.enum import DefaultProvider, Period
# Initialize provider
provider = Provider(DefaultProvider.YFinance)
# Create trading context
ctx = Context(
provider=provider,
symbol="BTC-USD",
period=Period.DAILY
)
Context Methods:
| Method | Description | Returns |
|---|---|---|
quotes() |
Get market data (cached) | List[Quote] |
plot(label, type, data, screen_index) |
Add plot data | None |
signal(action_series) |
Record trading signal | None |
authenticate(token) |
Authenticate with provider | None |
execute() |
Execute latest trading signal | None |
plots() |
Get all plot data | Dict |
signals() |
Get all trading signals | List |
2. Providers - Data Sources
Supported Providers:
from openstoxlify.models.enum import DefaultProvider
# Available providers
DefaultProvider.YFinance # Yahoo Finance
DefaultProvider.Binance # Binance (crypto)
Available Timeframes:
| Period | Interval | Description |
|---|---|---|
Period.MINUTELY |
1m | 1-minute candles |
Period.QUINTLY |
5m | 5-minute candles |
Period.HALFHOURLY |
30m | 30-minute candles |
Period.HOURLY |
60m | 1-hour candles |
Period.DAILY |
1d | Daily candles |
Period.WEEKLY |
1w | Weekly candles |
Period.MONTHLY |
1mo | Monthly candles |
Example:
from openstoxlify.providers.stoxlify.provider import Provider
from openstoxlify.models.enum import DefaultProvider
provider = Provider(DefaultProvider.Binance)
ctx = Context(provider, "BTCUSDT", Period.HOURLY)
quotes = ctx.quotes()
3. Plotting - Visualize Indicators
Plot technical indicators alongside market data:
from openstoxlify.models.enum import PlotType
from openstoxlify.models.series import FloatSeries
# Plot a single data point
ctx.plot(
label="SMA 20", # Indicator name
plot_type=PlotType.LINE, # Plot style
data=FloatSeries(
timestamp=quote.timestamp,
value=sma_value
),
screen_index=0 # Main chart (0) or subplot (1, 2, ...)
)
Plot Types:
| Type | Description | Use Case |
|---|---|---|
PlotType.LINE |
Continuous line | Moving averages, price lines |
PlotType.HISTOGRAM |
Vertical bars | Volume, MACD histogram |
PlotType.AREA |
Filled area under curve | Bollinger Bands, clouds |
Multi-Screen Layouts:
# Main chart (screen 0)
ctx.plot("Price", PlotType.LINE, FloatSeries(ts, price), screen_index=0)
ctx.plot("SMA 20", PlotType.LINE, FloatSeries(ts, sma20), screen_index=0)
# MACD subplot (screen 1)
ctx.plot("MACD", PlotType.HISTOGRAM, FloatSeries(ts, macd), screen_index=1)
# RSI subplot (screen 2)
ctx.plot("RSI", PlotType.LINE, FloatSeries(ts, rsi), screen_index=2)
4. Trading Signals
Record buy/sell decisions:
from openstoxlify.models.enum import ActionType
from openstoxlify.models.series import ActionSeries
# Record a LONG (buy) signal
ctx.signal(ActionSeries(
timestamp=quote.timestamp,
action=ActionType.LONG,
amount=1.5 # Position size
))
# Record a SHORT (sell) signal
ctx.signal(ActionSeries(
timestamp=quote.timestamp,
action=ActionType.SHORT,
amount=2.0
))
# Record a HOLD (no action)
ctx.signal(ActionSeries(
timestamp=quote.timestamp,
action=ActionType.HOLD,
amount=0.0 # Amount is automatically set to 0 for HOLD
))
Action Types:
| Type | Description | Visual Marker |
|---|---|---|
ActionType.LONG |
Buy/Bullish position | ▲ Blue arrow |
ActionType.SHORT |
Sell/Bearish position | ▼ Purple arrow |
ActionType.HOLD |
No action | (not displayed) |
5. Canvas - Render Charts
The Canvas class generates professional financial charts:
from openstoxlify.draw import Canvas
# Create canvas from context
canvas = Canvas(ctx)
# Draw with default settings
canvas.draw()
# Draw with custom styling
canvas.draw(
show_legend=True,
figsize=(16, 9),
title="My Trading Strategy",
candle_linewidth=1.5,
marker_size=10
)
🎨 Visualization with draw()
Basic Usage
from openstoxlify.context import Context
from openstoxlify.draw import Canvas
from openstoxlify.providers.stoxlify.provider import Provider
provider = Provider(DefaultProvider.YFinance)
ctx = Context(provider, "AAPL", Period.DAILY)
# Add your plots and signals...
canvas = Canvas(ctx)
canvas.draw() # Displays interactive matplotlib chart
Full Customization Example
canvas.draw(
show_legend=True, # Toggle legend visibility
figsize=(16, 9), # Larger figure size
offset_multiplier=0.03, # Adjust trade marker positions
rotation=45, # X-axis label rotation
ha='right', # Horizontal alignment
title="Custom Strategy Backtest",
xlabel="Trading Days",
ylabel="Price (USD)",
candle_linewidth=0.8, # Wick thickness
candle_body_width=3, # Body thickness
marker_size=10, # Trade signal markers
annotation_fontsize=8, # Trade annotation text
histogram_alpha=0.7, # Histogram transparency
area_alpha=0.4, # Area plot transparency
line_width=2.5 # Trend line thickness
)
Chart Features
| Element | Description | Example Visual |
|---|---|---|
| Candlesticks | Green/red based on price direction | 🟩🟥 |
| Signals | Annotated markers for trades | ▲ LONG ▼ SHORT |
| Indicators | Lines, histograms, and filled areas | ━━━━━ |
Example Output
Key Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
show_legend |
bool | True | Show/hide chart legend |
figsize |
tuple | (12, 6) | Figure dimensions (width, height) |
offset_multiplier |
float | 0.05 | Trade marker offset from price |
rotation |
int | 30 | X-axis label rotation angle |
ha |
str | 'right' | X-axis label horizontal alignment |
title |
str | "Market Data Visualizations" | Chart title |
xlabel |
str | "Date" | X-axis label |
ylabel |
str | "Price" | Y-axis label |
candle_linewidth |
float | 1 | Candlestick wick line width |
candle_body_width |
float | 4 | Candlestick body line width |
marker_size |
int | 8 | Trade marker size |
annotation_fontsize |
int | 9 | Trade annotation font size |
histogram_alpha |
float | 0.6 | Histogram bar transparency |
area_alpha |
float | 0.3 | Area plot transparency |
line_width |
float | 2 | Line plot width |
📚 Complete Examples
1. Simple Trading Strategy (from getting_started.py)
from statistics import median
from openstoxlify.context import Context
from openstoxlify.draw import Canvas
from openstoxlify.models.enum import ActionType, DefaultProvider, Period, PlotType
from openstoxlify.models.series import ActionSeries, FloatSeries
from openstoxlify.providers.stoxlify.provider import Provider
# Setup
provider = Provider(DefaultProvider.YFinance)
ctx = Context(provider, "BTC-USD", Period.DAILY)
# Get market data
quotes = ctx.quotes()
# Calculate median price
prices = [quote.close for quote in quotes]
median_value = median(prices)
# Find extremes
lowest = min(quotes, key=lambda q: q.close)
highest = max(quotes, key=lambda q: q.close)
# Plot median line
for quote in quotes:
ctx.plot("Median", PlotType.LINE, FloatSeries(quote.timestamp, median_value))
# Add signals at extremes
ctx.signal(ActionSeries(lowest.timestamp, ActionType.LONG, 1))
ctx.signal(ActionSeries(highest.timestamp, ActionType.SHORT, 1))
# Visualize
canvas = Canvas(ctx)
canvas.draw()
2. Moving Average Crossover
from openstoxlify.context import Context
from openstoxlify.draw import Canvas
from openstoxlify.models.enum import ActionType, DefaultProvider, Period, PlotType
from openstoxlify.models.series import ActionSeries, FloatSeries
from openstoxlify.providers.stoxlify.provider import Provider
def calculate_sma(prices, period):
"""Simple Moving Average"""
return [
sum(prices[i:i+period]) / period
for i in range(len(prices) - period + 1)
]
# Setup
provider = Provider(DefaultProvider.YFinance)
ctx = Context(provider, "AAPL", Period.DAILY)
quotes = ctx.quotes()
# Calculate indicators
closes = [q.close for q in quotes]
sma_20 = calculate_sma(closes, 20)
sma_50 = calculate_sma(closes, 50)
# Plot price and moving averages
for i, quote in enumerate(quotes):
ctx.plot("Price", PlotType.LINE, FloatSeries(quote.timestamp, quote.close))
if i >= 19: # SMA 20 starts at index 19
sma_20_idx = i - 19
ctx.plot("SMA 20", PlotType.LINE, FloatSeries(quote.timestamp, sma_20[sma_20_idx]))
if i >= 49: # SMA 50 starts at index 49
sma_50_idx = i - 49
ctx.plot("SMA 50", PlotType.LINE, FloatSeries(quote.timestamp, sma_50[sma_50_idx]))
# Generate signals on crossovers
if sma_50_idx > 0:
prev_fast = sma_20[sma_20_idx - 1]
prev_slow = sma_50[sma_50_idx - 1]
curr_fast = sma_20[sma_20_idx]
curr_slow = sma_50[sma_50_idx]
# Bullish crossover
if prev_fast <= prev_slow and curr_fast > curr_slow:
ctx.signal(ActionSeries(quote.timestamp, ActionType.LONG, 1.0))
# Bearish crossover
elif prev_fast >= prev_slow and curr_fast < curr_slow:
ctx.signal(ActionSeries(quote.timestamp, ActionType.SHORT, 1.0))
# Visualize
canvas = Canvas(ctx)
canvas.draw(title="SMA Crossover Strategy", figsize=(14, 8))
3. Multi-Indicator Strategy (from subplots.py)
See the full example in examples/subplots.py which demonstrates:
- Multiple screen layouts
- MACD histogram on subplot
- Stochastic oscillator on separate panel
- Combined signal generation from multiple indicators
🔄 Migration Guide (Old API → New API)
Before (Old API)
from openstoxlify.fetch import fetch
from openstoxlify.plotter import plot
from openstoxlify.strategy import act
from openstoxlify.draw import draw
from openstoxlify.models import Period, Provider, PlotType, ActionType
# Old way
market_data = fetch("BTCUSDT", Provider.Binance, Period.MINUTELY)
quotes = market_data.quotes
for quote in quotes:
plot(PlotType.LINE, "Median", quote.timestamp, median_value)
act(ActionType.LONG, lowest.timestamp, 1)
draw()
After (New API)
from openstoxlify.context import Context
from openstoxlify.draw import Canvas
from openstoxlify.models.enum import DefaultProvider, Period, PlotType, ActionType
from openstoxlify.models.series import FloatSeries, ActionSeries
from openstoxlify.providers.stoxlify.provider import Provider
# New way - Context-based
provider = Provider(DefaultProvider.Binance)
ctx = Context(provider, "BTCUSDT", Period.MINUTELY)
quotes = ctx.quotes()
for quote in quotes:
ctx.plot("Median", PlotType.LINE, FloatSeries(quote.timestamp, median_value))
ctx.signal(ActionSeries(lowest.timestamp, ActionType.LONG, 1))
canvas = Canvas(ctx)
canvas.draw()
Key Changes
| Old API | New API |
|---|---|
fetch(symbol, provider, period) |
Context(provider, symbol, period).quotes() |
plot(type, label, ts, value) |
ctx.plot(label, type, FloatSeries(ts, value)) |
act(action, timestamp, amount) |
ctx.signal(ActionSeries(ts, action, amount)) |
draw() |
Canvas(ctx).draw() |
Import from models |
Import from models.enum, models.series |
📖 API Reference
Data Structures
Quote
@dataclass
class Quote:
timestamp: datetime # Time of measurement
high: float # Period high price
low: float # Period low price
open: float # Opening price
close: float # Closing price
volume: float # Trading volume
FloatSeries
@dataclass
class FloatSeries:
timestamp: datetime # Data point time
value: float # Indicator value
ActionSeries
@dataclass
class ActionSeries:
timestamp: datetime # Signal time
action: ActionType # LONG, SHORT, or HOLD
amount: float # Position size
🔐 Authentication & Execution
For live trading with supported providers:
# Authenticate
ctx.authenticate("your-api-token")
# Execute the latest signal
ctx.execute() # Only executes if authenticated
Note: execute() will only run if:
- Context is authenticated
- There's a signal at the latest timestamp
- The signal is not
ActionType.HOLD
💡 Best Practices
- Cache quotes: Context automatically caches
quotes()calls per symbol - Use screen_index: Separate indicators into different panels for clarity
- Consistent timestamps: All timestamps are timezone-aware UTC
- Plot incrementally: Call
ctx.plot()in loops for time-series data - Signal at decision points: Only call
ctx.signal()when strategy makes a decision
🧪 Testing
Run the test suite:
# Run all tests
make test
# Run with coverage
pytest tests/ --cov=openstoxlify --cov-report=html
# Run specific test file
pytest tests/test_context.py -v
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📄 License
MIT © 2026 OpenStoxlify
🔗 Links
⭐ Support
If you find this library helpful, please consider giving it a star on GitHub!
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 openstoxlify-1.1.0.tar.gz.
File metadata
- Download URL: openstoxlify-1.1.0.tar.gz
- Upload date:
- Size: 29.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99fe895cd29910993c55ece1590ad44d1a13ee4c978c68c1c881d83126d4a01f
|
|
| MD5 |
812d10ca008fe24b2a6747353b568173
|
|
| BLAKE2b-256 |
ba9ca21cedc345303b30022c9408ff6d4bc07de7084e68662fcde79e50ee4cce
|
File details
Details for the file openstoxlify-1.1.0-py3-none-any.whl.
File metadata
- Download URL: openstoxlify-1.1.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36072a28dca11ef2bd995072e248aa439b2b728db436cfa74bc657991d394f89
|
|
| MD5 |
28c01d676358400d45de5f7c32cc77fe
|
|
| BLAKE2b-256 |
ae23d2455bc43c15bde5f728a0791935838fba6bebd14ba02f6645bba2b2c8fa
|