# Best Data Sources for Systematic Trading Research: yfinance vs AkShare vs TuShare

> Explore the best data sources for systematic trading research yfinance AkShare and TuShare. Compare free global equity data Chinese macro data and premium tick data.

- Repository: [Papers With Backtest/awesome-systematic-trading](https://github.com/paperswithbacktest/awesome-systematic-trading)
- Tags: comparison
- Published: 2026-07-31

---

**yfinance delivers free global equity data without authentication, while AkShare provides comprehensive Chinese macro and fundamental data via web scraping, and TuShare offers authenticated API access to high-quality Chinese tick data with stricter rate limits.**

The [awesome-systematic-trading](https://github.com/paperswithbacktest/awesome-systematic-trading) repository catalogs these three libraries in its Data Sources section as the primary Python connectors for quantitative research. Each serves distinct geographic markets and data granularity requirements, making the choice dependent on whether your systematic strategy targets global equities or focuses on Chinese mainland securities.

## Market Coverage and Data Granularity

Understanding the primary jurisdiction of each library determines its fit for your backtesting pipeline.

**yfinance** sources data from Yahoo! Finance, providing daily OHLCV and intraday minute-level bars for global equities, ETFs, options, and futures. It includes corporate actions like dividends and splits, though coverage for non-U.S. fundamentals remains limited. According to the repository's [`README.md`](https://github.com/paperswithbacktest/awesome-systematic-trading/blob/main/README.md) (lines 218‑221), this is the recommended starting point for international strategies.

**AkShare** specializes in Chinese mainland markets, offering daily and tick-level data for stocks, bonds, and futures alongside extensive macro-economic indicators (GDP, CPI, etc.). It scrapes public websites and APIs, delivering richer fundamental data (profit margins, balance sheets) than global alternatives for A-share securities.

**TuShare** focuses exclusively on Chinese equities through a formal JSON API, providing daily, weekly, and monthly bars plus concept-stock mappings and industry classifications. While its macro coverage is narrower than AkShare, it delivers cleaner tick-level historical data when accessed with a valid token.

## Authentication Requirements and Rate Limiting

Your infrastructure setup varies significantly between these sources.

**yfinance** requires no API key, functioning as a thin Python wrapper over `pandas_datareader`. It is rate-limited by Yahoo!'s servers but imposes no hard caps on requests per minute.

**AkShare** operates without authentication for most endpoints, though optional tokens unlock premium services. Its web-scraping architecture means it can slow down when source websites change HTML structures or throttle heavy traffic.

**TuShare** mandates a free API token obtained from [tushare.pro](https://tushare.pro) for all calls. The service enforces approximately 100 requests per minute and occasionally exhibits data gaps during Chinese market holidays, requiring robust error handling in production workflows.

## Implementation: Fetching Unified Price Data

All three libraries return `pandas.DataFrame` objects compatible with the repository's strategy scripts in `static/strategies/*.py`. Below are standardized fetchers that align schemas across providers.

### Global Equities with yfinance

Use `yf.download()` for U.S. and international tickers, selecting adjusted close prices to handle splits and dividends.

```python
import yfinance as yf

def fetch_yfinance(ticker: str, start: str, end: str):
    """Fetch daily OHLCV from Yahoo Finance."""
    df = yf.download(ticker, start=start, end=end, progress=False)
    df = df[['Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume']]
    df.columns = [c.lower().replace(' ', '_') for c in df.columns]
    df['source'] = 'yfinance'
    return df

# Example: Apple Inc.

df_aapl = fetch_yfinance("AAPL", "2022-01-01", "2022-12-31")

```

### Chinese Markets with AkShare

Leverage `ak.stock_zh_a_hist()` for A-share data, specifying `adjust="hfq"` for fully-adjusted historical prices.

```python
import akshare as ak
import pandas as pd

def fetch_akshare(ticker: str, start: str, end: str):
    """Fetch Chinese equity data via AkShare."""
    df = ak.stock_zh_a_hist(
        symbol=ticker, 
        period="daily", 
        start_date=start, 
        end_date=end, 
        adjust="hfq"
    )
    df = df.rename(columns={
        "date": "date",
        "open": "open", 
        "high": "high", 
        "low": "low",
        "close": "close", 
        "volume": "volume"
    })[['date', 'open', 'high', 'low', 'close', 'volume']]
    df['date'] = pd.to_datetime(df['date'])
    df = df.set_index('date')
    df['source'] = 'akshare'
    return df

# Example: Kweichow Moutai (600519.SH)

df_moutai = fetch_akshare("600519", "2022-01-01", "2022-12-31")

```

### Chinese Markets with TuShare

Access TuShare Pro via `pro.daily()`, converting date formats from YYYYMMDD strings to datetime indexes.

```python
import tushare as ts
import os
import pandas as pd

def fetch_tushare(ticker: str, start: str, end: str):
    """Fetch Chinese equity data via TuShare Pro API."""
    token = os.getenv("TUSHARE_TOKEN")
    ts.set_token(token)
    pro = ts.pro_api()
    
    df = pro.daily(
        ts_code=ticker, 
        start_date=start.replace('-', ''), 
        end_date=end.replace('-', '')
    )
    df = df.rename(columns={
        "trade_date": "date", 
        "open": "open", 
        "high": "high",
        "low": "low", 
        "close": "close", 
        "vol": "volume"
    })[['date', 'open', 'high', 'low', 'close', 'volume']]
    df['date'] = pd.to_datetime(df['date'])
    df = df.set_index('date')
    df['source'] = 'tushare'
    return df

# Example: Requires TUSHARE_TOKEN environment variable

df_moutai_ts = fetch_tushare("600519.SH", "2022-01-01", "2022-12-31")

```

### Unified Data Interface

Create a provider-agnostic fetcher to swap sources without modifying strategy logic, as implemented in the repository's example scripts like [`static/strategies/asset-growth-effect.py`](https://github.com/paperswithbacktest/awesome-systematic-trading/blob/main/static/strategies/asset-growth-effect.py).

```python
def fetch_price(ticker, start, end, provider="yfinance"):
    """Unified fetcher supporting multiple data sources."""
    if provider == "yfinance":
        return fetch_yfinance(ticker, start, end)
    if provider == "akshare":
        return fetch_akshare(ticker, start, end)
    if provider == "tushare":
        return fetch_tushare(ticker, start, end)
    raise ValueError(f"Unsupported provider: {provider}")

```

## Integration with Backtesting Workflows

When integrating these sources into the awesome-systematic-trading ecosystem, observe three architectural constraints from the source code analysis.

**Caching Layer**: Implement local caching using `joblib` or `pickle` after initial downloads. While `yfinance` provides built-in caching via its `download` wrapper, `AkShare` and `TuShare` require explicit wrappers to check local storage before issuing HTTP requests, preventing redundant calls during strategy iteration.

**Timezone Alignment**: Combine global equities (yfinance, typically UTC or ET) with Chinese data (AkShare/TuShare, Asia/Shanghai) by normalizing all timestamps to UTC. Explicitly handle divergent holiday calendars when merging datasets for cross-regional arbitrage strategies.

**Error Resilience**: Wrap all fetchers in try-except blocks catching `requests.exceptions` and `urllib.error` exceptions. Strategy scripts should fall back to the most recent cached snapshot when network failures occur, ensuring reproducibility of backtests as recommended in the repository's QuantConnect-style implementations.

## Summary

- **yfinance** serves as the optimal choice for global equity research requiring no authentication, offering daily and intraday OHLCV data through `yf.download()`.
- **AkShare** provides the most comprehensive Chinese fundamental and macro data via web scraping, accessed through `ak.stock_zh_a_hist()` without API keys.
- **TuShare** delivers authenticated, high-quality Chinese tick data via `pro.daily()` when you require cleaner institutional-grade feeds and can manage token-based rate limits.
- All three libraries output `pandas.DataFrame` objects compatible with the repository's strategy scripts in `static/strategies/`, enabling plug-and-play data source substitution.
- Implement caching and timezone normalization when combining yfinance's global coverage with AkShare or TuShare's Chinese market data.

## Frequently Asked Questions

### Which data source is best for backtesting U.S. equity strategies?

**yfinance** is the recommended choice for U.S. strategies because it provides free, unauthenticated access to daily and minute-level OHLCV data, dividends, and splits through Yahoo! Finance. Its `yf.download()` function returns DataFrames that integrate directly with the repository's strategy templates, though you should implement caching to avoid hitting rate limits during extensive backtests.

### Do I need an API token to access Chinese stock data?

Only **TuShare** requires a mandatory API token from tushare.pro; **AkShare** operates without authentication for most endpoints. However, TuShare's token-based system enforces stricter data quality controls and provides approximately 100 requests per minute, whereas AkShare relies on web scraping that may break if source websites update their HTML structure.

### Can I use these data sources for live trading or just research?

These libraries are primarily designed for research and backtesting. While yfinance, AkShare, and TuShare can technically feed live trading systems, they lack the low-latency execution guarantees required for high-frequency strategies. According to the awesome-systematic-trading repository's architecture, use these connectors for strategy development in `static/strategies/*.py`, then migrate to broker-specific APIs (like QuantConnect's live trading interface) for production deployment.

### How do I handle different column schemas when switching between yfinance and Chinese data providers?

Standardize column names immediately after fetching. yfinance returns capitalized column names (`Open`, `High`, `Low`, `Close`, `Adj Close`) while AkShare and TuShare use lowercase or Chinese-specific fields. The unified fetcher pattern shown in the code examples above demonstrates renaming columns to a consistent schema (`open`, `high`, `low`, `close`, `volume`) and adding a `source` column for provenance tracking, ensuring your backtesting logic remains agnostic to the data provider.