Price History using Yahoo Finance avatar
Price History using Yahoo Finance
Under maintenance

Pricing

from $0.03 / 1,000 results

Go to Apify Store
Price History using Yahoo Finance

Price History using Yahoo Finance

Under maintenance

This Actor fetches historical stock price data from Yahoo Finance. It retrieves OHLCV (Open, High, Low, Close, Volume) data with adjusted closing prices and auto-calculated daily returns for financial analysis and backtesting.

Pricing

from $0.03 / 1,000 results

Rating

0.0

(0)

Developer

JC

JC

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

Yahoo Finance Historical Stock Data Actor

Fetch historical OHLCV stock price data from Yahoo Finance with adjusted closing prices and automated daily returns calculation. Perfect for backtesting trading strategies, financial analysis, portfolio research, and quantitative analysis with support for multiple ticker symbols and flexible time ranges.

Quick Start

Once you've installed the dependencies, start the Actor:

$apify run

Once your Actor is ready, you can push it to the Apify Console:

apify login # first, you need to log in if you haven't already done so
apify push

Project Structure

.actor/
├── actor.json # Actor configuration and metadata
├── input_schema.json # Input validation & Console form definition
└── output_schema.json # Output data structure specification
src/
└── main.js # Actor entry point - fetches Yahoo Finance data
analysis/
└── analysis.py # Python analysis script with Analyzer class
Dockerfile # Container image definition
package.json # Node.js dependencies and scripts

For more information, see the Actor definition documentation.

How it works

This Actor automates the process of fetching historical stock price data from the Yahoo Finance API and stores structured financial data in a dataset for analysis and backtesting.

  • The Actor accepts ticker symbols (AAPL, MSFT, GOOGL, etc.) and a time range from the input
  • It queries Yahoo Finance's API for complete OHLCV (Open, High, Low, Close, Volume) data
  • Daily returns are automatically calculated for each trading day using percentage change formula
  • Adjusted closing prices account for stock splits and dividends
  • Data is validated and pushed to the dataset for output
  • Built-in rate limiting prevents API throttling when processing multiple tickers

What's included

  • Apify SDK - toolkit for building Actors
  • OHLCV data extraction - Complete historical price and volume data from Yahoo Finance
  • Input validation - configurable ticker symbols, time ranges (1d to max), and rate limiting
  • Dataset - store structured financial data with daily returns
  • Automated returns calculation - daily percentage change calculated for each trading day
  • Error handling - robust error recovery and logging for reliability
  • Rate limiting - configurable delays to respect API limits and prevent throttling
  • Python analysis tools - included Analyzer class for support/resistance, smart money detection, and momentum signals

Resources

Use Cases

  • Backtesting trading strategies - Test algorithmic trading strategies with historical OHLCV data
  • Financial analysis - Analyze price trends, volatility, and volume patterns
  • Portfolio research - Track historical performance of multiple stocks
  • Quantitative analysis - Gather data for machine learning and statistical models
  • Technical analysis - Support and resistance level identification, momentum analysis
  • Investment research - Compare historical performance across different tickers

Getting started

For complete information see this article. In short, you will:

  1. Build the Actor
  2. Run the Actor

Features

  • Historical OHLCV data (Open, High, Low, Close, Volume)
  • Adjusted closing prices for accurate returns
  • Auto-calculated daily returns (percentage change)
  • Configurable rate limiting to avoid API blocks
  • Support for multiple tickers in a single run
  • Flexible time ranges (1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)

Input Configuration

{
"tickers": ["AAPL", "MSFT", "GOOGL"],
"range": "3mo",
"interval": "1d",
"maxRequestsPerCrawl": 100,
"maxConcurrency": 10,
"timeoutSecs": 7200,
"memoryMbytes": 2048,
"rateLimitDelay": 1000,
"restartOnError": false,
"proxyConfiguration": {
"useApifyProxy": true
}
}

Input Parameters

ParameterTypeDefaultDescription
tickersarray["AAPL"]Stock ticker symbols to fetch (max 10)
rangestring"3mo"Time range for historical data (1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)
intervalstring"1d"Time interval for data points (1min, 1h, 1d, 1mo, 1y)
maxRequestsPerCrawlinteger100Maximum number of requests/tickers to process (1-2000)
maxConcurrencyinteger10Number of concurrent requests (1-50)
timeoutSecsinteger7200Maximum runtime in seconds (60-10800)
memoryMbytesinteger2048Memory allocation in MB (528-4096)
restartOnErrorbooleanfalseAutomatically restart if the actor fails
rateLimitDelayinteger1000Milliseconds to wait between ticker requests (100-10000)
proxyConfigurationobject{"useApifyProxy": true}Proxy settings for requests

Output Format

Each row represents one trading day:

{
"ticker": "AAPL",
"date": "2024-12-10",
"open": 195.50,
"high": 197.30,
"low": 194.80,
"close": 196.45,
"volume": 52431900,
"adjClose": 196.45,
"dailyReturn": 0.48,
"fetchedAt": "2024-12-11T08:30:00.000Z"
}

Financial Analysis with Python

The included Python analysis script provides advanced financial analysis capabilities.

Analyzer Class Features

The analysis/analysis.py file contains an Analyzer class with three main analysis methods:

  1. Professional Support & Resistance - Identifies swing highs/lows from the last 3 months of daily data
  2. Smart Money Detection - Spots institutional buying/selling through volume spike analysis
  3. Momentum Signals - Determines if stock is overbought/oversold in short term

Example Usage

import pandas as pd
from analysis import Analyzer
# Load data from dataset CSV
analyzer = Analyzer('./data/dataset.csv', ["NVDA", "AMD", "INTC"])
# Get first ticker
ticker1 = analyzer.df['ticker'].iloc[0]
# Find support and resistance levels
support_resistance = analyzer.professional_support_resistance(ticker1)
# Output: {'support': 169.55, 'resistance': 188.0, 'method': 'swing_points', ...}
# Detect institutional trading patterns
smart_money = analyzer.detect_smart_money(ticker1)
# Output: {'accumulation_days': 1, 'distribution_days': 0, 'biggest_buy_day': '2025-11-25', ...}
# Get momentum signal
momentum = analyzer.momentum_signal(ticker1)
# Output: {'5_day_return': '-5.7%', '20_day_return': '-8.0%', 'signal': 'No extreme signal', ...}

Analysis Methods Details

Professional Support & Resistance

Finds actionable support (buy) and resistance (sell) levels using swing point analysis on the last 3 months of daily data.

def professional_support_resistance(self, ticker):
"""
Professional method finding actionable support (buy)/resistance (sell) in last 3 months of daily data
Ideal range/interval: 3 months of daily data (63 trading days)
"""
# Find recent swing highs (local maxima)
three_months_ago = datetime.datetime.now() - pd.DateOffset(months=3)
df = self.df.loc[(self.df['ticker'] == ticker) & (self.df['date'] >= three_months_ago)]
swing_highs = []
for i in range(1, len(df)-1):
if df['high'].iloc[i] > df['high'].iloc[i-1] and df['high'].iloc[i] > df['high'].iloc[i+1]:
swing_highs.append(df['high'].iloc[i])
# Find recent swing lows (local minima)
swing_lows = []
for i in range(1, len(df)-1):
if df['low'].iloc[i] < df['low'].iloc[i-1] and df['low'].iloc[i] < df['low'].iloc[i+1]:
swing_lows.append(df['low'].iloc[i])
# Use most recent swings
resistance = max(swing_highs[-3:]) if swing_highs else df['high'].max()
support = min(swing_lows[-3:]) if swing_lows else df['low'].min()
return {
'support': support,
'resistance': resistance,
'method': 'swing_points',
'most_recent_price': df.sort_values(['date'],ascending=False).iloc[0]['close']
}

Smart Money Detection

Identifies volume spikes (>150% of 20-day average) with meaningful price moves.

def detect_smart_money(self, ticker):
"""Spot institutional buying/selling, i.e. volume spikes with meaningful price moves
Ideal range/interval: 1 month of daily data (21 trading days)
"""
# Calculate 20-day average volume
twenty_days_ago = datetime.datetime.now() - pd.DateOffset(days=20)
df = self.df.loc[(self.df['ticker'] == ticker) & (self.df['date'] >= twenty_days_ago)]
avg_volume = df['volume'].mean()
high_vol_days = df[df['volume'] > avg_volume * 1.5]
# Analyze price action on those days
insights = {
'accumulation_days': high_vol_days[high_vol_days['close'] > high_vol_days['open']].shape[0],
'distribution_days': high_vol_days[high_vol_days['close'] < high_vol_days['open']].shape[0],
'biggest_buy_day': high_vol_days.loc[high_vol_days['volume'].idxmax(), 'date'].strftime('%Y-%m-%d') if not high_vol_days.empty else None,
'volume_trend': 'Increasing' if df['volume'].iloc[0] > avg_volume else 'Decreasing'
}
return insights

Momentum Signal

Calculates 5-day vs 20-day momentum for mean reversion analysis.

def momentum_signal(self, ticker):
"""5-day momentum vs 20-day average for mean reversion to determine whether stock is overbought or oversold short-term"""
df = self.df.loc[self.df['ticker'] == ticker]
current_price = df.sort_values(['date'],ascending=False)['close'].iloc[0]
price_5d_ago = df.sort_values(['date'],ascending=False)['close'].iloc[4]
price_20d_ago = df.sort_values(['date'],ascending=False)['close'].iloc[19]
# Calculate returns
return_5d = ((current_price - price_5d_ago) / price_5d_ago) * 100
return_20d = ((current_price - price_20d_ago) / price_20d_ago) * 100
# Simple mean reversion signal
if return_5d > 8:
signal = "Consider taking profits"
elif return_5d < -8:
signal = "Potential bounce opportunity"
elif return_20d > return_5d > 0:
signal = "Momentum weakening"
else:
signal = "No extreme signal"
return {
'5_day_return': f"{return_5d:.1f}%",
'20_day_return': f"{return_20d:.1f}%",
'signal': signal,
'extreme_move': abs(return_5d) > 8
}

Rate Limiting

The Actor includes built-in rate limiting to respect API limits and avoid throttling. The code implements a configurable delay between ticker requests (default: 1000ms):

const { tickers = ['AAPL'], range = "1y", rateLimitDelay = 1000 } = input || {};

Recommended settings:

  • 1000ms (default): Safe for most use cases
  • 500ms: Faster requests, but may trigger rate limits with many tickers
  • 2000ms+: Extra conservative for large batches (50+ tickers)

Supported Time Ranges and Intervals

Time Ranges: 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max

Intervals: 1min, 1h, 1d, 1mo, 1y

Choose based on your analysis needs - daily (1d) data is most common for backtesting and technical analysis.

Understanding the Data

  • OHLCV: Open, High, Low, Close, and Volume prices for each time period
  • Adjusted Close (adjClose): The closing price adjusted for stock splits and dividend distributions
  • Daily Return (dailyReturn): Percentage change from previous close, calculated as: ((close - previousClose) / previousClose) * 100
  • Volume: Number of shares traded during the period

Tips

  • Use 3+ months of daily data for reliable support/resistance analysis
  • Volume spikes above 150% of 20-day average often indicate institutional activity
  • Daily returns help identify momentum and mean reversion opportunities
  • The adjClose field accounts for stock splits and dividends

Learn More