Metadata-Version: 2.4
Name: value300
Version: 0.2.0
Summary: Python SDK for querying ETF data from value300.cn
Author: value300
License: MIT
Keywords: etf,finance,data,value300,quant
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.20
Provides-Extra: pandas
Requires-Dist: pandas>=1.5; extra == "pandas"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pandas>=1.5; extra == "dev"

# value300

Python SDK for querying ETF data from [value300.cn](https://value300.cn).

## Install

```bash
pip install value300

# With pandas support:
pip install value300[pandas]
```

## Quick Start

```python
from value300 import Value300

client = Value300()

# 1. Single ETF history (by date range)
data = client.get_history("510300", start_date="2026-01-01", end_date="2026-06-30")

# 2. Single ETF history (by days back from today)
data = client.get_history("510300", days=180)

# 3. All ETFs snapshot for a specific date
snapshot = client.get_snapshot("2026-07-08")

# 4. All ETFs snapshot for latest trading day
snapshot = client.get_snapshot()

# As pandas DataFrame
df = client.get_history("510300", days=180, as_dataframe=True)
df_snapshot = client.get_snapshot(as_dataframe=True)
```

## Caching

- **Snapshot cache**: 500 entries (LRU, keyed by date)
- **History cache**: 2000 records per ETF code (LRU, keyed by trade_date)

```python
# Check cache stats
print(client.cache_stats())

# Clear caches
client.clear_cache()
client.clear_history_cache("510300")  # specific code only
```

## Rate Limiting

Server-side rate limit: **1000 requests/day per IP**.
Exceeding returns `RateLimitError` with `daily_limit`, `used`, and `retry_after` attributes.

```python
from value300 import RateLimitError

try:
    data = client.get_history("510300", days=365)
except RateLimitError as e:
    print(f"Limit: {e.daily_limit}/day, used: {e.used}, retry in {e.retry_after}s")
```

## API Reference

### `Value300(base_url, timeout, max_retries, snapshot_cache_size, history_cache_size)`

| Parameter | Default | Description |
|---|---|---|
| `base_url` | `https://value300.cn` | API base URL |
| `timeout` | `30` | Request timeout (seconds) |
| `max_retries` | `3` | Max retry attempts |
| `snapshot_cache_size` | `500` | Max cached snapshot entries |
| `history_cache_size` | `2000` | Max cached records per ETF code |

### Methods

| Method | Returns | Description |
|---|---|---|
| `get_history(code, start_date, end_date, days, fields, as_dataframe)` | `list[dict]` or `DataFrame` | Single ETF historical data |
| `get_snapshot(date, as_dataframe)` | `list[dict]` or `DataFrame` | All ETFs snapshot for a date |
| `clear_cache()` | `None` | Clear all caches |
| `clear_history_cache(code)` | `None` | Clear history cache |
| `clear_snapshot_cache()` | `None` | Clear snapshot cache |
| `cache_stats()` | `dict` | Cache statistics |

### Record Fields

| Field | Type | Description |
|---|---|---|
| `code` | `str` | ETF code |
| `name` | `str` | ETF name |
| `trade_date` | `str` | Trading date (YYYY-MM-DD) |
| `open` | `float` | Open price |
| `close` | `float` | Close price |
| `high` | `float` | High price |
| `low` | `float` | Low price |
| `pct_chg` | `float` | Price change percentage |
| `volume` | `int` | Trading volume |
| `amount` | `float` | Trading amount |

## License

MIT
