Fetching Historical Market Data with yfinance and AkShare: A Practical Guide
Use yfinance to download dividend-adjusted U.S. equity prices and AkShare to pull Chinese A-share data, then merge the resulting pandas DataFrames to feed multi-region factor pipelines in the paperswithbacktest/awesome-systematic-trading repository.
The paperswithbacktest/awesome-systematic-trading repository hosts hundreds of reproducible quantitative strategies that depend on clean, historical price feeds. Fetching historical market data with yfinance and AkShare enables researchers to populate the factor-construction workflows found in files like static/strategies/volatility-risk-premium-effect.py without requiring expensive data subscriptions. Both libraries return native pandas objects that align with the repository’s standardized data pipeline.
The Standard Data Integration Workflow
Across the repository’s strategy files, data ingestion follows a consistent four-step pattern:
- Import the fetching library at the top of the script.
- Pull raw data using high-level APIs such as
yf.download()orak.stock_zh_a_hist(). - Clean and align the index to datetime and forward-fill missing values.
- Integrate the series into the master price matrix referenced by factor-construction utilities.
You can observe this exact workflow in static/strategies/asset-class-momentum-rotational-system.py, where multiple price series are aligned before momentum calculations.
Fetching U.S. Equity Data with yfinance
For strategies requiring American market data, the fetch_yf_price function wraps the library’s download utility to return a cleaned DataFrame suitable for backtesting. This pattern mirrors the data-loading logic found in static/strategies/volatility-risk-premium-effect.py and static/strategies/value-factor-effect-within-countries.py.
import yfinance as yf
import pandas as pd
def fetch_yf_price(tickers: list[str],
start: str = "2000-01-01",
end: str = "2024-12-31") -> pd.DataFrame:
"""
Returns a DataFrame whose columns are tickers and rows are adjusted
closing prices. The index is a DatetimeIndex aligned to market days.
"""
price_df = yf.download(tickers,
start=start,
end=end,
actions=False, # no dividends/splits here
progress=False)['Adj Close']
# Ensure the index is a proper datetime type and fill occasional gaps.
price_df.index = pd.to_datetime(price_df.index)
price_df = price_df.ffill().dropna(how="all")
return price_df
# Example usage:
tickers = ["AAPL", "MSFT", "SPY"]
prices = fetch_yf_price(tickers)
print(prices.head())
Accessing Chinese Markets with AkShare
For strategies targeting Chinese equities—such as those analyzing the currency-momentum factor—the fetch_akshare_price function retrieves front-adjusted daily bars using the stock_zh_a_hist endpoint. The resulting DataFrame integrates directly into the same factor pipelines used for U.S. data, as demonstrated in static/strategies/currency-momentum-factor.py.
import akshare as ak
import pandas as pd
def fetch_akshare_price(symbol: str,
start: str = "2005-01-01",
end: str = "2024-12-31") -> pd.DataFrame:
"""
Pulls daily OHLCV data for a Chinese A‑share (e.g., 'sh600519')
and returns a DataFrame indexed by trade date.
"""
raw = ak.stock_zh_a_hist(symbol=symbol,
period="daily",
start_date=start.replace("-", ""),
end_date=end.replace("-", ""),
adjust="qfq") # 前复权
raw["date"] = pd.to_datetime(raw["date"])
raw.set_index("date", inplace=True)
# Keep only the adjusted close price (named 'close' after qfq)
price = raw[["close"]].rename(columns={"close": symbol})
price = price.ffill()
return price
# Example usage:
sh600519 = fetch_akshare_price("sh600519")
print(sh600519.head())
Merging Multi-Region Datasets
Cross-market strategies require aligning heterogeneous calendars. The combine_price_frames function concatenates U.S. and Chinese price series, forward-filling to handle non-overlapping trading days. This approach reflects the data-handling methodology in static/strategies/turn-of-the-month-in-equity-indexes.py, where unified price matrices drive calendar-based signals.
def combine_price_frames(us_prices: pd.DataFrame,
cn_price: pd.DataFrame) -> pd.DataFrame:
"""
Aligns U.S. and Chinese price series on a common calendar.
Missing dates on either side are forward‑filled.
"""
combined = pd.concat([us_prices, cn_price], axis=1)
combined = combined.ffill().dropna(how="all")
return combined
# Pull data
us = fetch_yf_price(["AAPL", "MSFT"])
cn = fetch_akshare_price("sh600519")
# Merge
all_prices = combine_price_frames(us, cn)
print(all_prices.head())
Reference Implementation in Strategy Files
The following files in static/strategies/ illustrate how external market data feeds into systematic trading logic:
static/strategies/volatility-risk-premium-effect.py: Demonstrates volatility factor construction using adjusted close prices.static/strategies/turn-of-the-month-in-equity-indexes.py: Shows calendar-based signal generation requiring clean, aligned price data.static/strategies/currency-momentum-factor.py: Implements macro-level momentum using multi-currency data—ideal for AkShare integration.static/strategies/asset-class-momentum-rotational-system.py: Builds multi-asset rotation strategies requiring unified price matrices.static/strategies/value-factor-effect-within-countries.py: Merges fundamental data with price series for country-level value factors.
Summary
- yfinance provides free, dividend-adjusted U.S. equity data via
yf.download(), returning pandas DataFrames compatible with the repository’s factor pipelines. - AkShare supplies comprehensive Chinese market data through
ak.stock_zh_a_hist(), enabling analysis of A-shares and macro indicators. - Both libraries follow a standard workflow: import, fetch, clean (datetime index + forward fill), and integrate.
- Strategy files like
static/strategies/volatility-risk-premium-effect.pyserve as reference implementations for these data patterns. - Cross-market analysis requires aligning calendars using
pd.concatwith forward-fill, as shown instatic/strategies/turn-of-the-month-in-equity-indexes.py.
Frequently Asked Questions
What is the difference between yfinance and AkShare in this repository?
yfinance specializes in U.S. exchange data including adjusted closes, splits, and dividends, making it suitable for strategies like the volatility risk premium effect. AkShare focuses on Chinese markets, offering over 2,000 APIs for equities and macro data used in factors such as currency momentum.
How do I align trading calendars when combining U.S. and Chinese data?
Use pd.concat with axis=1 followed by ffill() to forward-fill missing values, creating a common calendar index. This technique mirrors the implementation in static/strategies/turn-of-the-month-in-equity-indexes.py, which handles non-overlapping market holidays between regions.
Can these libraries be used for real-time trading or only backtesting?
Both libraries primarily provide historical end-of-day data optimized for backtesting systematic strategies within the paperswithbacktest/awesome-systematic-trading repository. Real-time trading would require additional data vendors or APIs with live feeds.
Which strategy file shows the cleanest example of integrating external data?
static/strategies/volatility-risk-premium-effect.py provides the clearest reference for U.S. equity data integration, while static/strategies/currency-momentum-factor.py demonstrates how to incorporate AkShare data for multi-region analysis.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →