Metadata-Version: 2.4
Name: lixinger-python
Version: 0.3.0
Summary: Python SDK for Lixinger Financial Data API
Project-URL: Homepage, https://www.lixinger.com
Project-URL: Documentation, https://www.lixinger.com/open/api/doc
Author-email: JianGuo <aliezted@gmail.com>
License: MIT
License-File: LICENSE
Keywords: api,finance,financial-data,lixinger,sdk,stock
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: httpx[socks]>=0.28.1
Requires-Dist: numpy>=2.4.1
Requires-Dist: pandas<3,>=2.0.0
Requires-Dist: pandera>=0.28.1
Requires-Dist: python-dotenv>=1.2.1
Description-Content-Type: text/markdown

This is the python SDK of lixinger API. Lixinger is a website of financial data.

## ✨ Features

- ⚡ **Fully Async/Await** - Non-blocking I/O for better performance
- 🤖 **AI Agent Ready** - Perfect for LangChain, LlamaIndex function calls
- 📊 **Pandas DataFrame** - All responses return pandas DataFrame
- 🔒 **Type Safe** - Full type hints and mypy support
- 🔄 **Auto Retry** - Automatic retry with exponential backoff
- 🚦 **Rate Limiting** - Built-in rate limiter (1000 req/min)
- 🌐 **Proxy Support** - SOCKS proxy support
- 📓 **Jupyter Ready** - Native top-level await support

## Installation

### From PyPI (Recommended)

```bash
# Using pip
pip install lixinger-python

# Using uv (faster)
uv add lixinger-python
```

### From Source (Development)

```bash
# Clone the repository
git clone https://github.com/your-username/lixinger-python.git
cd lixinger-python

# Install dependencies
uv sync
```

## Configuration

**REQUIRED**: The SDK requires the API key to be set in a `.env` file. The API key cannot be passed as a parameter.

```bash
# Copy the example file
cp .env.example .env

# Edit .env and add your API key
# LIXINGER_API_KEY=your_actual_api_key_here
```

Get your API key from: https://www.lixinger.com/open/api

## Usage

### Basic Usage (Async/Await)

```python
import asyncio
from lixinger import AsyncLixingerClient

async def main():
    # The API key is ALWAYS loaded from .env file
    # You cannot pass it as a parameter - this is intentional for security
    async with AsyncLixingerClient() as client:
        # Fetch company information
        df = await client.company.company.get_company(stock_codes=["600036"])
        print(df)

        # Fetch company profile
        df_profile = await client.company.profile.get_profile(stock_codes=["600036"])
        print(df_profile)

if __name__ == "__main__":
    asyncio.run(main())
```

### Advanced: Concurrent Requests

Query multiple stocks in parallel using `asyncio.gather()`:

```python
import asyncio
from lixinger import AsyncLixingerClient

async def main():
    async with AsyncLixingerClient() as client:
        # Fetch multiple stocks concurrently
        tasks = [
            client.company.company.get_company(stock_codes=["600036"]),
            client.company.company.get_company(stock_codes=["000001"]),
            client.company.company.get_company(stock_codes=["000002"]),
        ]
        results = await asyncio.gather(*tasks)

        for df in results:
            print(df)

asyncio.run(main())
```

### Jupyter Notebook Usage

Jupyter notebooks support async/await natively at the top level:

```python
# In a Jupyter cell, you can use await directly (no asyncio.run needed)
from lixinger import AsyncLixingerClient

client = AsyncLixingerClient()
df = await client.company.company.get_company(stock_codes=["600036"])
df
```

### Configuration Override

```python
# You can override settings (but NOT the API key)
async with AsyncLixingerClient(
    timeout=60.0,
    proxy="socks5://localhost:1080",
    max_requests_per_minute=500
) as client:
    df = await client.company.company.get_company(stock_codes=["000001"])
```

For more examples, see the `examples/` directory.

## Project Structure

The project follows an endpoint-based file organization:

```
lixinger/
├── api/cn/
│   ├── company/     # /cn/company endpoints (async)
│   ├── index/       # /cn/index endpoints (async)
│   └── fund/        # /cn/fund endpoints (async)
└── models/cn/       # Pydantic models (mirrors API structure)
    ├── company/
    ├── index/
    └── fund/
```

### Available APIs

**Company APIs** (`client.company.*`):
- `get_company()` - Company basic info
- `get_profile()` - Company profile
- `get_fundamental()` - Fundamental data
- `get_candlestick()` - OHLC candlestick data
- `get_equity_change()` - Equity change events
- `get_dividend()` - Dividend information
- `get_announcement()` - Company announcements
- `get_indices()` - Index memberships

**Index APIs** (`client.cn_index.*`):
- `get_index()` - Index basic info
- `get_constituents()` - Index constituents
- `get_candlestick()` - Index OHLC data
- `get_fundamental()` - Index fundamentals
- `get_tracking_fund()` - Tracking funds
- And more...

**Fund APIs** (`client.cn_fund.*`):
- `get_fund()` - Fund basic info
- `get_profile()` - Fund profile
- `get_candlestick()` - Fund NAV data
- `get_shareholdings()` - Fund holdings
- And more...

**Import Examples:**

```python
# Client API (recommended)
from lixinger import AsyncLixingerClient

async with AsyncLixingerClient() as client:
    df = await client.company.company.get_company(stock_codes=["000001"])

# Functional API (also async)
from lixinger import get_company, get_index

df = await get_company(stock_codes=["000001"])

# Models (if needed for type hints)
from lixinger.models.cn.company import Company
from lixinger.models.cn.index import Index
```

See `AGENTS.md` for detailed file organization rules.

## Documentation

- 📚 **完整文档**: 运行 `uv run mkdocs serve` 启动本地文档站点
- 📖 **API 参考**: 查看 `docs/api/` 目录或 [API_SUMMARY.md](API_SUMMARY.md)
- 🚀 **快速开始**: 查看 [docs/getting-started/quickstart.md](docs/getting-started/quickstart.md)

### 文档特性

本项目使用 **MkDocs + Material 主题** 自动生成文档，特性包括：

- ✨ 从 Python docstrings 自动生成 API 文档
- 🎨 美观的 Material Design 界面
- 🔍 全文搜索功能（支持中英文）
- 🌓 深色/浅色主题切换
- 📱 响应式设计，支持移动端

### 生成和预览文档

```bash
# 安装文档依赖
uv sync --dev

# 启动本地文档服务器（支持热重载）
uv run mkdocs serve
# 访问 http://127.0.0.1:8000

# 构建静态站点
uv run mkdocs build

# 部署到 GitHub Pages
uv run mkdocs gh-deploy
```

详细说明请查看 [DOCS.md](DOCS.md)。

## API Notes

**Architecture:**
- 🔄 **Fully Async** - All API methods use `async def` and must be awaited
- ⚡ **Non-blocking** - Perfect for concurrent requests and AI agents
- 📦 **httpx.AsyncClient** - Modern async HTTP client

**API Requirements:**
- **Content-Type**: `application/json` in request headers
- **Accept-Encoding**: Must include `gzip` (can also include deflate, br, *)
- **Rate Limit**: Maximum 1000 requests per minute
- **Status Code 429**: Too Many Requests (rate limit exceeded)
- **Retry Mechanism**: Built-in automatic retry for network issues
- **Authentication**: API key sent via `token` in POST body (loaded from `.env`)

**Response Format:**
All Lixinger API responses follow this format:
```json
{
  "code": 1,           // 1 = success, other = error
  "message": "success",
  "data": [...]        // Actual data (unwrapped by SDK)
}
```

The SDK automatically validates the response and returns only the `data` field.

## Why Async?

**Perfect for:**
- 🤖 **AI Agents** - LangChain, LlamaIndex function calls
- 🌐 **Web Apps** - FastAPI, Sanic, Quart backends
- 📊 **Data Pipelines** - Concurrent batch processing
- 📓 **Jupyter** - Interactive analysis with await

**Benefits:**
- ⚡ Concurrent requests - Query multiple stocks in parallel
- 🚫 Non-blocking - Doesn't block your event loop
- 📈 Better performance - Especially for bulk operations
- 🎯 Modern Python - Follows async/await best practices

## Development

```bash
# Run linter
uv run ruff check . --fix

# Run formatter
uv run ruff format .

# Run type checker
uv run mypy lixinger/

# Run tests (unit tests only, fast)
uv run pytest -m "not integration"

# Run all tests including integration (requires API key)
uv run pytest
```

See [CLAUDE.md](CLAUDE.md) for development guidelines.

## Contributing

Contributions are welcome! Please see [AGENTS.md](AGENTS.md) for detailed implementation guidelines, especially:
- How to add new APIs (all must be async)
- File organization rules
- Testing requirements
- Documentation standards

## License

[Your License Here]

## Links

- 📚 API Documentation: https://www.lixinger.com/open/api/doc
- 🌐 Lixinger Website: https://www.lixinger.com
- 📖 Full Documentation: Run `uv run mkdocs serve`
