Skip to content

AmpyFin/yfinance-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

63 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

yfinance-go β€” Yahoo Finance Client for Go

Go Version License Go Report Card GoDoc

⚠️ IMPORTANT DISCLAIMER ⚠️

This project is NOT affiliated with, endorsed by, or sponsored by Yahoo Finance or Yahoo Inc.

This is an independent, open-source Go client that accesses publicly available financial data from Yahoo Finance's website. Yahoo Finance does not provide an official API for this data, and this client operates by scraping publicly accessible web pages.

Use at your own risk. Yahoo Finance may change their website structure at any time, which could break this client. We make no guarantees about data accuracy, availability, or compliance with Yahoo Finance's terms of service.

Legal Notice: Users are responsible for ensuring their use of this software complies with Yahoo Finance's terms of service and applicable laws in their jurisdiction.


🎯 Problem We're Solving

The Challenge: Most financial data clients suffer from inconsistent data formats, unreliable APIs, and poor error handling. When building financial applications, developers often face:

  • Inconsistent Data Formats: Different APIs return data in various shapes and formats
  • Floating Point Precision Issues: Financial calculations require exact decimal precision
  • Rate Limiting Problems: Unbounded requests lead to API bans and throttling
  • Poor Error Handling: Limited retry logic and circuit breaking
  • Currency Conversion Complexity: Multi-currency support is often missing or buggy
  • No Standardization: Each client has its own data structures and conventions

Our Solution: A production-grade Go client that provides:

βœ… Standardized Data Formats - Consistent ampy-proto message structures
βœ… High Precision Decimals - Scaled decimal arithmetic for financial accuracy
βœ… Robust Rate Limiting - Built-in backoff, circuit breakers, and session rotation
βœ… Multi-Currency Support - Automatic currency conversion with FX providers
βœ… Production Ready - Comprehensive error handling, observability, and monitoring
βœ… Easy Integration - Simple API with both library and CLI interfaces


πŸš€ Installation

As a Go Module

go get github.com/AmpyFin/yfinance-go

From Source

git clone https://github.com/AmpyFin/yfinance-go.git
cd yfinance-go
go build ./cmd/yfin

πŸ“– Quick Start

Basic Usage

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/AmpyFin/yfinance-go"
)

func main() {
    // Create a new client
    client := yfinance.NewClient()
    ctx := context.Background()
    
    // Fetch daily bars for Apple
    start := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
    end := time.Date(2024, 1, 31, 0, 0, 0, 0, time.UTC)
    
    bars, err := client.FetchDailyBars(ctx, "AAPL", start, end, true, "my-run-id")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Fetched %d bars for AAPL\n", len(bars.Bars))
    for _, bar := range bars.Bars {
        price := float64(bar.Close.Scaled) / float64(bar.Close.Scale)
        fmt.Printf("Date: %s, Close: %.4f %s\n", 
            bar.EventTime.Format("2006-01-02"),
            price, bar.CurrencyCode)
    }
}

πŸ”§ API Reference

Client Creation

// Default client with standard configuration
client := yfinance.NewClient()

// Client with session rotation (recommended for production)
client := yfinance.NewClientWithSessionRotation()

Available Functions

πŸ“Š Historical Data

FetchDailyBars - Get daily OHLCV data

bars, err := client.FetchDailyBars(ctx, "AAPL", start, end, adjusted, runID)

FetchIntradayBars - Get intraday data (1m, 5m, 15m, 30m, 60m)

bars, err := client.FetchIntradayBars(ctx, "AAPL", start, end, "1m", runID)

Note: Intraday data may not be available for all symbols and may return HTTP 422 errors for some requests.

FetchWeeklyBars - Get weekly OHLCV data

bars, err := client.FetchWeeklyBars(ctx, "AAPL", start, end, adjusted, runID)

FetchMonthlyBars - Get monthly OHLCV data

bars, err := client.FetchMonthlyBars(ctx, "AAPL", start, end, adjusted, runID)

πŸ’° Real-time Data

FetchQuote - Get current market quote

quote, err := client.FetchQuote(ctx, "AAPL", runID)

FetchMarketData - Get comprehensive market data

marketData, err := client.FetchMarketData(ctx, "AAPL", runID)

🏒 Company Information

FetchCompanyInfo - Get basic company information

companyInfo, err := client.FetchCompanyInfo(ctx, "AAPL", runID)

FetchFundamentalsQuarterly - Get quarterly financials (requires paid subscription)

fundamentals, err := client.FetchFundamentalsQuarterly(ctx, "AAPL", runID)

πŸ•ΈοΈ Scrape Fallback System

When Yahoo Finance API endpoints are unavailable, rate-limited, or require paid subscriptions, yfinance-go automatically falls back to web scraping with full data consistency guarantees.

Key Features

  • Automatic Fallback: Seamlessly switches between API and scraping
  • Data Consistency: Identical output formats regardless of source
  • Production Safety: Respects robots.txt, implements proper rate limiting
  • Comprehensive Coverage: Access data not available through APIs

Supported Scrape Endpoints

  • Key Statistics: P/E ratios, market cap, financial metrics
  • Financials: Income statements, balance sheets, cash flow
  • Analysis: Comprehensive analyst data including:
    • Earnings estimates (current/next quarter, current/next year)
    • EPS trends (current estimate, 7/30/60/90 days ago)
    • EPS revisions (up/down revisions in last 7/30 days)
    • Revenue estimates (quarterly and annual)
    • Growth estimates
  • Analyst Insights: Target prices, recommendations, analyst counts
  • Profile: Company information, executives, business summary
  • News: Recent news articles and press releases

Quick Scrape Examples

// Scrape key statistics (not available through free API)
keyStats, err := client.ScrapeKeyStatistics(ctx, "AAPL", runID)

// Scrape financial statements
financials, err := client.ScrapeFinancials(ctx, "AAPL", runID)

// Scrape comprehensive analysis data (earnings trends, EPS revisions, revenue estimates)
analysis, err := client.ScrapeAnalysis(ctx, "AAPL", runID)

// Scrape analyst insights (target prices, recommendations)
analystInsights, err := client.ScrapeAnalystInsights(ctx, "AAPL", runID)

// Scrape news articles
news, err := client.ScrapeNews(ctx, "AAPL", runID)

CLI Scraping

# Scrape key statistics with preview
yfin scrape --ticker AAPL --endpoint key-statistics --preview

# Multiple endpoints with JSON output
yfin scrape --ticker AAPL --endpoints key-statistics,financials,news --preview-json

# Soak testing for production validation
yfin soak --universe-file universe.txt --duration 2h --qps 5 --preview

πŸ“– Complete Scrape Documentation β†’


πŸ“ Usage Examples

Example 1: Fetch Daily Bars for Multiple Symbols

package main

import (
    "context"
    "fmt"
    "log"
    "sync"
    "time"

    "github.com/AmpyFin/yfinance-go"
)

func main() {
    client := yfinance.NewClient()
    ctx := context.Background()
    
    symbols := []string{"AAPL", "GOOGL", "MSFT", "TSLA"}
    start := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
    end := time.Date(2024, 1, 31, 0, 0, 0, 0, time.UTC)
    
    var wg sync.WaitGroup
    results := make(chan string, len(symbols))
    
    for _, symbol := range symbols {
        wg.Add(1)
        go func(sym string) {
            defer wg.Done()
            
            bars, err := client.FetchDailyBars(ctx, sym, start, end, true, "batch-run")
            if err != nil {
                results <- fmt.Sprintf("Error fetching %s: %v", sym, err)
                return
            }
            
            results <- fmt.Sprintf("%s: %d bars fetched", sym, len(bars.Bars))
        }(symbol)
    }
    
    wg.Wait()
    close(results)
    
    for result := range results {
        fmt.Println(result)
    }
}

Example 2: Get Current Market Quote

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/AmpyFin/yfinance-go"
)

func main() {
    client := yfinance.NewClient()
    ctx := context.Background()
    
    quote, err := client.FetchQuote(ctx, "AAPL", "quote-run")
    if err != nil {
        log.Fatal(err)
    }
    
	fmt.Printf("Symbol: %s\n", quote.Security.Symbol)
	if quote.RegularMarketPrice != nil {
		price := float64(quote.RegularMarketPrice.Scaled) / float64(quote.RegularMarketPrice.Scale)
		fmt.Printf("Price: %.4f %s\n", price, quote.CurrencyCode)
	}
	if quote.RegularMarketVolume != nil {
		fmt.Printf("Volume: %d\n", *quote.RegularMarketVolume)
	}
	fmt.Printf("Event Time: %s\n", quote.EventTime.Format("2006-01-02 15:04:05"))
}

Example 3: Fetch Company Information

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/AmpyFin/yfinance-go"
)

func main() {
    client := yfinance.NewClient()
    ctx := context.Background()
    
    companyInfo, err := client.FetchCompanyInfo(ctx, "AAPL", "company-run")
    if err != nil {
        log.Fatal(err)
    }
    
	fmt.Printf("Company: %s\n", companyInfo.LongName)
	fmt.Printf("Exchange: %s\n", companyInfo.Exchange)
	fmt.Printf("Full Exchange: %s\n", companyInfo.FullExchangeName)
	fmt.Printf("Currency: %s\n", companyInfo.Currency)
	fmt.Printf("Instrument Type: %s\n", companyInfo.InstrumentType)
	fmt.Printf("Timezone: %s\n", companyInfo.Timezone)
}

Example 4: Error Handling

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/AmpyFin/yfinance-go"
)

func main() {
	client := yfinance.NewClient()
	ctx := context.Background()
	
	// Fetch data with proper error handling
	bars, err := client.FetchDailyBars(ctx, "AAPL", 
		time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
		time.Date(2024, 1, 31, 0, 0, 0, 0, time.UTC),
		true, "error-handling-run")
	
	if err != nil {
		log.Printf("Error fetching bars: %v", err)
		return
	}
	
	fmt.Printf("Successfully fetched %d bars\n", len(bars.Bars))
	
	// Handle empty results
	if len(bars.Bars) == 0 {
		fmt.Println("No data available for the specified date range")
		return
	}
	
	// Process the data
	for _, bar := range bars.Bars {
		price := float64(bar.Close.Scaled) / float64(bar.Close.Scale)
		fmt.Printf("Date: %s, Close: %.4f %s\n", 
			bar.EventTime.Format("2006-01-02"),
			price, bar.CurrencyCode)
	}
}

πŸ“š Documentation

Note: For the latest release notes, see Release Notes. For the complete changelog, see CHANGELOG.md.

Core Documentation

Method Comparison & Migration

Error Handling & Quality

Scrape Fallback System

Operations & Monitoring

Development & Testing

Audit & Quality Assurance

Operator Runbooks

Examples & Code Samples


πŸ–₯️ CLI Usage

The yfin CLI tool provides command-line access to all functionality:

Note: All CLI commands require a configuration file. Use --config configs/effective.yaml or set up your own config file.

Installation

# Build from source
go build -o yfin ./cmd/yfin

# Or install globally
go install github.com/AmpyFin/yfinance-go/cmd/yfin@latest

Basic Commands

# Fetch daily bars for a single symbol
yfin pull --ticker AAPL --start 2024-01-01 --end 2024-12-31 --adjusted split_dividend --preview --config configs/effective.yaml

# Fetch data for multiple symbols from a file
yfin pull --universe-file symbols.txt --start 2024-01-01 --end 2024-12-31 --publish --env prod --config configs/effective.yaml

# Get current quote
yfin quote --tickers AAPL --preview --config configs/effective.yaml

# Get fundamentals (requires paid subscription)
yfin fundamentals --ticker AAPL --preview --config configs/effective.yaml

Scraping Commands

# Scrape key statistics (not available through free API)
yfin scrape --ticker AAPL --endpoint key-statistics --preview --config configs/effective.yaml

# Multiple endpoints with JSON preview
yfin scrape --ticker AAPL --endpoints key-statistics,financials,analysis --preview-json --config configs/effective.yaml

# News articles preview
yfin scrape --ticker AAPL --endpoint news --preview-news --config configs/effective.yaml

# Health check for endpoints
yfin scrape --ticker AAPL --endpoint key-statistics --check --config configs/effective.yaml

Soak Testing Commands

# Quick smoke test (10 minutes)
yfin soak --universe-file testdata/universe/soak.txt --endpoints key-statistics,news --duration 10m --concurrency 8 --qps 5 --preview --config configs/effective.yaml

# Full production soak test (2 hours)
yfin soak --universe-file testdata/universe/soak.txt --endpoints key-statistics,financials,analysis,profile,news --duration 2h --concurrency 12 --qps 5 --preview --config configs/effective.yaml

CLI Options

Core Options

  • --ticker - Single symbol to fetch
  • --universe-file - File containing list of symbols
  • --start, --end - Date range (UTC)
  • --adjusted - Adjustment policy (raw, split_only, split_dividend)
  • --publish - Publish to ampy-bus
  • --env - Environment (dev, staging, prod)
  • --preview - Show data preview without publishing
  • --concurrency - Number of concurrent requests
  • --qps - Requests per second limit

Scraping Options

  • --endpoint - Single endpoint to scrape
  • --endpoints - Comma-separated list of endpoints
  • --fallback - Fallback strategy (auto, api-only, scrape-only)
  • --preview-json - JSON preview of multiple endpoints
  • --preview-news - Preview news articles
  • --preview-proto - Preview proto summaries
  • --check - Validate endpoint accessibility
  • --force - Override robots.txt (testing only)

Soak Testing Options

  • --duration - Test duration (e.g., 2h, 30m)
  • --memory-check - Enable memory leak detection
  • --probe-interval - Correctness probe interval
  • --failure-rate - Simulated failure rate for testing

πŸ“– Complete CLI Documentation β†’


🎯 Mission & Success Criteria

Mission
Provide a reliable, consistent, and fast Yahoo Finance client in Go that speaks Ampy's canonical contracts (ampy-proto) and optionally emits to ampy-bus, so ingestion pipelines and research tools work identically across providers.

Success looks like

  • Library returns validated ampy-proto messages with correct UTC times, currency semantics, and adjustment flags.
  • CLI supports on-demand pulls and batch backfills; ops can dry‑run, preview, and publish with a single command.
  • Concurrency and backoff keep error rates and 429/503 responses within policy; throughput is tunable and predictable.
  • Golden samples round‑trip across Go β†’ Python/C++ consumers without shape drift.
  • Observability shows latency/throughput, decode failures, and backoff behavior; alerts catch regressions.

πŸ“Š Data Coverage

βœ… Supported Data Types

  • Historical Bars - Daily, weekly, monthly, and intraday OHLCV data
  • Real-time Quotes - Current market prices, bid/ask, volume
  • Company Information - Basic company details, exchange info, industry/sector
  • Market Data - 52-week ranges, market state, trading hours
  • Multi-Currency Support - Automatic currency conversion with FX providers

❌ API Limitations (Available via Scraping)

These data types require paid Yahoo Finance subscriptions through the API, but are available through the scrape fallback system:

  • Financial Statements - Income statement, balance sheet, cash flow βœ… Available via scraping
  • Analyst Recommendations - Price targets, ratings βœ… Available via scraping
  • Key Statistics - P/E ratios, market cap, financial metrics βœ… Available via scraping
  • Company Profiles - Business summary, executives, sector info βœ… Available via scraping
  • News Articles - Recent news and press releases βœ… Available via scraping

❌ Not Supported

  • Options Data - Options chains and pricing
  • Insider Trading - Insider transactions
  • Institutional Holdings - Major shareholders
  • Level 2 Market Data - Order book, bid/ask depth

🌍 Supported Markets

  • US Markets - NYSE, NASDAQ, AMEX
  • International - Major exchanges worldwide
  • Currencies - Forex pairs and cryptocurrency
  • Commodities - Gold, oil, agricultural products
  • Indices - S&P 500, Dow Jones, NASDAQ Composite

⚑ Key Features

πŸ›‘οΈ Production Ready

  • Rate Limiting - Built-in QPS limits and burst control
  • Circuit Breakers - Automatic failure detection and recovery
  • Retry Logic - Exponential backoff with jitter
  • Session Rotation - Prevents IP blocking and rate limits
  • Scrape Fallback - Automatic APIβ†’scrape fallback with robots.txt compliance
  • Observability - Comprehensive metrics, logs, and tracing
  • Soak Testing - Built-in load testing and robustness validation

πŸ’° Financial Accuracy

  • High Precision Decimals - Scaled decimal arithmetic for exact calculations
  • Currency Support - Multi-currency with automatic conversion
  • Corporate Actions - Split and dividend adjustments
  • Market Hours - Proper handling of trading sessions and holidays

πŸš€ Performance

  • Concurrent Requests - Configurable goroutine pools
  • Connection Pooling - Efficient HTTP connection reuse
  • Caching - Built-in response caching for FX rates
  • Batching - Efficient data batching and chunking

πŸ”§ Developer Experience

  • Simple API - Clean, intuitive Go interface
  • Type Safety - Strongly typed data structures
  • Error Handling - Comprehensive error types and messages
  • CLI Tool - Command-line interface for operations
  • Documentation - Extensive examples and API docs

πŸ“‹ Data Formats & Conventions

  1. Time: All timestamps UTC ISO‑8601. Bars use start inclusive, end exclusive; event_time at bar close.
  2. Precision: Prices/amounts are scaled decimals (scaled, scale). Volumes are integers.
  3. Currency: Attach ISO‑4217 code to monetary fields and fundamentals lines.
  4. Identity: Use SecurityId = { symbol, mic?, figi?, isin? }. If MIC is unknown, prefer primary listing inference; document fallback rules.
  5. Adjustments: Bars declare adjusted: true|false and adjustment_policy_id: "raw" | "split_only" | "split_dividend".
  6. Lineage: Every message has meta.run_id, meta.source="yfinance-go", meta.producer="<host|pod>", schema_version.
  7. Batching: Prefer BarBatch for efficiency. Maintain in‑batch order by event_time ascending.
  8. Compatibility: Additive evolution only; breaking changes require new major (bars.v2, fundamentals.v2).

πŸ’° Price Formatting

All prices are stored as ScaledDecimal with explicit scale for financial precision:

// βœ… CORRECT: Use the scale field to convert back to decimal
price := float64(bar.Close.Scaled) / float64(bar.Close.Scale)
fmt.Printf("Price: %.4f %s\n", price, bar.CurrencyCode)

// ❌ WRONG: Don't hardcode division by 10000
// price := bar.Close.Scaled / 10000  // This is incorrect!

Example:

  • Raw Yahoo price: $221.74
  • Stored as: Scaled: 22174, Scale: 2
  • Converted back: 22174 / 100 = 221.74 βœ…


βš™οΈ Configuration

Environment Variables

# Rate limiting
export YFIN_QPS=2.0
export YFIN_BURST=5
export YFIN_CONCURRENCY=32

# Timeouts
export YFIN_TIMEOUT=30s
export YFIN_BACKOFF_BASE=1s
export YFIN_BACKOFF_MAX=10s

# Circuit breaker
export YFIN_CIRCUIT_THRESHOLD=5
export YFIN_CIRCUIT_RESET=30s

# Observability
export YFIN_LOG_LEVEL=info
export YFIN_METRICS_ENABLED=true

Configuration File

# config.yaml
yahoo:
  timeout_ms: 30000
  base_url: "https://query1.finance.yahoo.com"

concurrency:
  global_workers: 32
  max_inflight: 64

rate_limit:
  per_host_qps: 2.0
  burst: 5

retry:
  attempts: 3
  backoff_base_ms: 1000
  backoff_max_ms: 10000

circuit_breaker:
  failure_threshold: 5
  reset_timeout_ms: 30000

observability:
  log_level: "info"
  metrics_enabled: true
  tracing_enabled: false

πŸš€ Quick Start Examples

Run CLI Examples

# Make scripts executable
chmod +x examples/cli/*.sh

# Run AAPL preview examples
./examples/cli/preview_aapl.sh

# Run soak testing examples  
./examples/cli/soak_smoke.sh

# Run batch processing examples
./examples/cli/batch_processing.sh

Build Library Examples

# Build and run library examples
go build -o examples/library/scrape_fallback examples/library/scrape_fallback.go
./examples/library/scrape_fallback

πŸ“– All Examples β†’


🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/AmpyFin/yfinance-go.git
cd yfinance-go

# Install dependencies
go mod download

# Run tests
go test ./...

# Build CLI
go build -o yfin ./cmd/yfin

# Run integration tests
go test -tags=integration ./...

Code Style

  • Follow Go standard formatting (gofmt)
  • Use meaningful variable and function names
  • Add tests for new functionality
  • Update documentation for API changes

πŸ“„ License

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


πŸ™ Acknowledgments

  • Yahoo Finance for providing publicly accessible financial data
  • AmpyFin for the ampy-proto schemas and infrastructure
  • Go Community for excellent libraries and tools
  • Contributors who help improve this project

πŸ“ž Support

Getting Help

  1. Check Documentation: Start with docs/ for comprehensive guides
  2. Review Examples: See examples/ for code samples
  3. Search Issues: Check existing GitHub Issues
  4. Troubleshooting: See docs/scrape/troubleshooting.md
  5. Runbooks: For operational issues, see runbooks/

⭐ If you find this project useful, please give it a star on GitHub!

About

yfinance golang API with pluggable AmpyFin interfaces

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages