You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
1 year ago | |
|---|---|---|
| .gitignore | 1 year ago | |
| LICENSE | 1 year ago | |
| MANIFEST.in | 1 year ago | |
| README.md | 1 year ago | |
| requirements.txt | 1 year ago | |
| setup.py | 1 year ago | |
README.md
yfinance-plus 🚀
A drop-in replacement for yfinance with improved rate limiting, intelligent caching, and 401 error handling. Works exactly like the original yfinance but faster, more reliable, and with zero breaking changes.
✨ Key Features
🎯 100% Drop-in Replacement
- Import as
import yfinance_plus as yf - All yfinance functionality works identically
- 99% API coverage (97/98 features supported)
- Zero code changes required
🛡️ Enhanced Rate Limiting & Error Handling
- Automatic 401 error handling with session refresh
- Browser-like headers with 7 different User-Agent strings
- Exponential backoff with intelligent retry logic
- Session rotation every 10 minutes or 50 requests
⚡ Intelligent Caching System
- 247x faster repeated requests with file-based caching
- Smart period matching - longer periods serve shorter requests
- Automatic cache invalidation after 1 hour
- CLI cache management with detailed file information
🔧 Enhanced CLI Tools
yfpcommand for cache and configuration management- Detailed cache inspection with symbol, period, and date range info
- Performance benchmarking and connection testing
- Configuration management with easy-to-use commands
📦 Installation
Method 1: Install from Source (Recommended)
# Clone and install
git clone https://gitea.yirugi.synology.me/yirugi/yfinance_plus.git
cd yfinance-plus
pip install -e .
Method 2: Local Development
# Install dependencies
pip install yfinance>=0.2.65 curl_cffi>=0.5.0 pandas>=1.3.0 numpy>=1.20.0
🚀 Quick Start
Drop-in Replacement Usage
# Simply replace your import - everything else stays the same!
import yfinance_plus as yf
# All original yfinance functionality works identically
ticker = yf.Ticker("AAPL")
hist = ticker.history(period="1mo")
info = ticker.info # Note: property, not method
data = yf.download(["AAPL", "GOOGL"], period="1mo")
# Multiple tickers
tickers = yf.Tickers("MSFT AAPL GOOG")
msft_info = tickers.tickers['MSFT'].info
# New cache management features
yf.clear_cache()
cache_info = yf.get_cache_info()
Performance Comparison
import time
import yfinance_plus as yf
# First request (downloads and caches)
start = time.time()
data1 = yf.Ticker("AAPL").history(period="1mo")
first_time = time.time() - start
print(f"First request: {first_time:.3f}s")
# Second request (from cache)
start = time.time()
data2 = yf.Ticker("AAPL").history(period="1mo")
second_time = time.time() - start
print(f"Second request: {second_time:.3f}s")
print(f"Speedup: {first_time/second_time:.1f}x")
# Output:
# First request: 0.186s
# Second request: 0.001s
# Speedup: 247.9x
🔧 Command Line Interface
Available Commands
yfp --help # Show all available commands
yfp cache info # Show detailed cache information
yfp cache info --limit 5 # Show only 5 most recent files
yfp cache clear # Clear cache with confirmation
yfp cache clear --force # Clear cache without confirmation
yfp config show # Show current configuration
yfp test # Test connection to Yahoo Finance
yfp benchmark # Run performance benchmark
Enhanced Cache Information
$ yfp cache info
🗂️ YFinance Plus Cache Information
==================================================
Cache Directory: /Users/username/.yfinance_cache
Number of Files: 8
Total Size: 30.5 KB
📁 Cache Files:
----------------------------------------------------------------------------------------------------
📄 06dbc103b9a8af2faddce6c95b2caaef 5.4 KB 2025-08-01 21:59:40
Symbol: NVDA Period: 3mo Interval: 1d Rows: 63
Date Range: 2025-05-02 to 2025-08-01
📄 0d84bd5865d16d346aabcaed64cf02f0 2.8 KB 2025-08-01 21:59:40
Symbol: NVDA Period: 1mo Interval: 1d Rows: 22
Date Range: 2025-07-02 to 2025-08-01
Configuration Management
$ yfp config show
⚙️ YFinance Plus Configuration
========================================
Max Retries: 3
Base Delay: 1.0s
Max Delay: 60.0s
Jitter Enabled: True
Cache Enabled: True
Cache Directory: /Users/username/.yfinance_cache
User Agents: 7 configured
Connection Testing
$ yfp test
🔗 Testing connection to Yahoo Finance...
Creating test ticker...
Fetching basic info...
Fetching historical data...
✅ Connection test successful!
Company: Apple Inc.
Historical data points: 5
Cache status: 8 files
💾 Intelligent Caching System
How Smart Caching Works
import yfinance_plus as yf
# 1. First request caches data
ticker = yf.Ticker("AAPL")
data_1mo = ticker.history(period="1mo") # Downloads and caches
# 2. Second identical request uses cache
data_1mo_again = ticker.history(period="1mo") # Instant from cache
# 3. Longer period downloads new data
data_3mo = ticker.history(period="3mo") # Downloads 3mo, caches it
# 4. Shorter request extracts from longer cached data
data_1mo_from_3mo = ticker.history(period="1mo") # Extracted from 3mo cache
What Gets Cached
✅ Cached:
- Historical price data (
history()) - All standard periods (1d, 1mo, 3mo, 1y, etc.)
- All intervals (1m, 5m, 1h, 1d)
- Smart overlap detection - longer periods serve shorter requests
❌ Not Cached:
- Real-time data
- News articles (
news) - Extended hours data (
prepost=True) - Data older than 1 hour (auto-expires)
Cache Management
import yfinance_plus as yf
# Check cache status
cache_info = yf.get_cache_info()
print(f"Cache files: {cache_info['file_count']}")
print(f"Cache size: {cache_info['total_size_mb']:.2f} MB")
# Clear cache
yf.clear_cache()
# Configure caching
yf.set_config(
enable_cache=True,
cache_dir="~/my_custom_cache"
)
⚙️ Configuration
Global Configuration
import yfinance_plus as yf
# Configure global settings
yf.set_config(
max_retries=5, # Number of retry attempts
base_delay=1.0, # Base delay between retries (seconds)
max_delay=60.0, # Maximum delay (seconds)
jitter=True, # Add randomness to delays
enable_cache=True, # Enable intelligent caching
cache_dir="~/my_cache" # Custom cache directory
)
# Get current configuration
config = yf.get_config()
print(f"Max retries: {config.max_retries}")
Configuration Parameters
| Parameter | Default | Description |
|---|---|---|
max_retries |
3 | Maximum retry attempts for failed requests |
base_delay |
1.0 | Base delay between retries (seconds) |
max_delay |
60.0 | Maximum delay between retries (seconds) |
jitter |
True | Add random jitter to delays |
enable_cache |
True | Enable intelligent caching system |
cache_dir |
~/.yfinance_cache |
Cache directory location |
user_agents |
7 agents | List of User-Agent strings to rotate |
🔄 Migration Guide
From yfinance to yfinance-plus
Migration is 100% seamless - just change your import:
# Before
import yfinance as yf
# After
import yfinance_plus as yf
# Everything else works identically!
ticker = yf.Ticker("AAPL")
data = yf.download(["AAPL", "GOOGL"], period="1mo")
tickers = yf.Tickers("MSFT AAPL GOOG")
info = tickers.tickers['MSFT'].info
Common yfinance Patterns That Work
import yfinance_plus as yf
# All standard patterns work identically
ticker = yf.Ticker("AAPL")
# Properties (not methods!)
info = ticker.info # ✅ Correct
dividends = ticker.dividends # ✅ Correct
splits = ticker.splits # ✅ Correct
financials = ticker.financials # ✅ Correct
balance_sheet = ticker.balance_sheet # ✅ Correct
cashflow = ticker.cashflow # ✅ Correct
# Methods
history = ticker.history(period="1mo") # ✅ Correct
options = ticker.options # ✅ Correct
option_chain = ticker.option_chain("2024-01-19") # ✅ Correct
# Bulk operations
data = yf.download(["AAPL", "GOOGL", "MSFT"],
period="1y", interval="1d")
# Multiple tickers
tickers = yf.Tickers("AAPL GOOGL MSFT")
for symbol in tickers.symbols:
hist = tickers.tickers[symbol].history(period="1mo")
🚀 Enhanced Features
401 Error Handling
# Automatic 401 error recovery
import yfinance_plus as yf
ticker = yf.Ticker("AAPL")
# If Yahoo returns 401, automatically:
# 1. Creates new session with fresh headers
# 2. Retries with exponential backoff
# 3. Rotates User-Agent strings
# 4. Works silently in background
info = ticker.info # Just works!
Advanced Rate Limiting
# The wrapper automatically:
# - Detects rate limit errors (429, 401)
# - Refreshes sessions every 10 minutes
# - Uses 7 different User-Agent strings
# - Adds realistic browser cookies
# - Implements exponential backoff
# - No user intervention required
Performance Optimization
import yfinance_plus as yf
# Smart cache usage
ticker = yf.Ticker("AAPL")
# Downloads 1 year of data
hist_1y = ticker.history(period="1y") # ~0.5s, cached
# Uses cached data for shorter periods
hist_6mo = ticker.history(period="6mo") # ~0.001s, from cache
hist_3mo = ticker.history(period="3mo") # ~0.001s, from cache
hist_1mo = ticker.history(period="1mo") # ~0.001s, from cache
# Result: 4 requests in ~0.5s instead of ~2.0s
📊 API Compatibility
100% Compatible Functions
| Function | yfinance | yfinance-plus | Enhancements |
|---|---|---|---|
Ticker(symbol) |
✅ | ✅ | + Caching + Rate limiting |
download(tickers) |
✅ | ✅ | + Better error handling |
Tickers(symbols) |
✅ | ✅ | + Enhanced performance |
ticker.history() |
✅ | ✅ | + Intelligent caching |
ticker.info |
✅ | ✅ | + 401 error handling |
ticker.financials |
✅ | ✅ | + Automatic retries |
ticker.dividends |
✅ | ✅ | + Session management |
ticker.splits |
✅ | ✅ | + Rate limiting |
| All other methods | ✅ | ✅ | + Enhanced reliability |
New Enhanced Functions
| Function | Description |
|---|---|
yf.clear_cache() |
Clear all cached data |
yf.get_cache_info() |
Get detailed cache statistics |
yf.set_config(**kwargs) |
Configure global settings |
yf.get_config() |
Get current configuration |
🔍 Technical Details
Browser Emulation
# Automatically rotates between realistic headers:
user_agents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
# ... 3 more variants
]
# Plus realistic browser cookies:
cookies = {
'A1': 'd=AQABBC123456YLoCIgEBwQJ7vgAB&S=AQAAAg',
'GUC': 'AQEBAQFm1234k0L',
'B': 'c=1234567&b=3&s=4u',
# ... more realistic cookies
}
Intelligent Cache Strategy
# Cache key generation
cache_key = hash(f"{symbol}_{period}_{interval}_{start}_{end}")
# Smart period matching
if requested_period <= cached_period:
return cached_data.tail(requested_rows) # Extract from cache
else:
fetch_new_data() # Download longer period
Error Recovery
# Automatic error handling
if "401" in error or "unauthorized" in error:
refresh_session() # New headers and cookies
exponential_backoff() # Wait before retry
retry_request() # Try again
🧪 Testing
Running Tests
# Run comprehensive tests
python test_drop_in_replacement.py
python test_comprehensive_wrapping.py
# CLI tests
yfp test
yfp benchmark
yfp cache info
Test Results
🚀 Comprehensive yfinance Enhanced Wrapping Test
======================================================================
📊 Functionality coverage: 97/98 (99.0%)
✅ EXCELLENT: Nearly all yfinance functionality is working!
Cache speedup: 247.9x
Bulk download speedup: 4.36x
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
⚠️ Disclaimer
This project is for educational and research purposes. Please respect Yahoo Finance's terms of service and rate limits. The yfinance-plus wrapper is designed to be more respectful of their servers while providing better reliability for legitimate use cases.
🙏 Acknowledgments
- Built on top of the excellent yfinance library
- Uses curl_cffi for advanced browser emulation
- Inspired by the need for more reliable financial data access
Made with ❤️ for the Python financial data community