# lidb 使用场景和示例

## 典型使用场景

### 1. 量化研究工作流

在量化研究中，研究人员需要从原始数据出发，经过一系列数据处理和特征工程，最终生成用于模型训练的因子数据。lidb提供了一套完整的数据管理解决方案，支持从数据获取到特征生成的全流程。

```mermaid
graph TD
    A[原始数据] --> B[数据清洗和预处理]
    B --> C[基础因子计算]
    C --> D[复合因子生成]
    D --> E[因子组合和筛选]
    E --> F[模型训练和回测]
    F --> G[策略生成]
```

### 2. 实时交易策略

对于需要实时交易的策略，lidb支持实时数据更新和低延迟查询，能够满足高频交易的需求。

```mermaid
graph TD
    A[实时行情] --> B[数据入库]
    B --> C[实时因子计算]
    C --> D[信号生成]
    D --> E[交易执行]
    E --> F[风险监控]
```

### 3. 历史数据分析

在进行历史数据分析时，lidb的惰性计算和并行处理特性能够显著提高数据处理效率，支持大规模历史数据的快速分析。

### 4. 数据管道构建

lidb可以作为数据管道的核心组件，连接不同的数据源和数据目的地，实现数据的自动化处理和流转。

## 代码示例

### 数据集定义和依赖

```python
from lidb import Dataset, DataLoader

# 定义基础数据集
def get_price_data():
    # 从数据库获取价格数据
    return sql("SELECT * FROM stock_prices")

price_ds = Dataset(fn=get_price_data, tb="prices", partitions=["date"])

# 定义因子数据集，依赖价格数据
def calculate_ma5(depend):
    return depend.select(
        pl.col("close").rolling_mean(5).alias("ma5")
    )

ma5_ds = Dataset(
    price_ds,
    fn=calculate_ma5,
    tb="factors/ma5",
    partitions=["date"]
)

# 使用DataLoader批量加载
loader = DataLoader("my_strategy")
loader.get(
    ds_list=[ma5_ds],
    beg_date="2023-01-01",
    end_date="2023-01-31",
    times=["09:30:00"]
)
```

### 表管理（全量/增量）

```python
from lidb import Table, TableMode

# 全量更新模式：每天覆盖更新
# 适用于盘后计算的指标

def get_daily_indicator():
    # 计算每日指标
    return sql("SELECT asset, date, indicator FROM daily_indicators")


daily_table = Table(
    fn=get_daily_indicator,
    tb="indicators/daily",
    update_time="15:00:00",  # 盘后更新
    mode=TableMode.F  # 全量更新
)

# 增量更新模式：每次新增数据
# 适用于实时交易数据

def get_trading_records():
    # 获取最新交易记录
    return sql("SELECT * FROM trading_records WHERE date = CURRENT_DATE")

trading_table = Table(
    fn=get_trading_records,
    tb="trading/records",
    update_time="",  # 实时更新
    mode=TableMode.I  # 增量更新
)

# 更新数据
daily_table.update()
trading_table.update()

# 获取数据
data = daily_table.get_value("2023-01-01")
```

### 复杂表达式计算

```python
from lidb import from_polars
import polars as pl

# 创建QDF对象
qdf = from_polars(
    pl.DataFrame({
        "date": ["2023-01-01", "2023-01-02"],
        "time": ["09:30:00", "09:30:00"],
        "asset": ["A", "B"],
        "close": [100, 101],
        "volume": [1000, 1100]
    }),
    index=("date", "time", "asset")
)

# 使用复杂表达式计算
result = qdf.sql(
    "ts_mean(close, 5) as ma5",
    "ts_std(close, 5) as std5",
    "cs_rank(volume) as volume_rank",
    "d_mean(close, 10) as ma10d",
    "itd_zscore(close, 20) as zscore_20",
)
```

### 数据库操作

```python
# SQL查询
result = sql("SELECT * FROM prices WHERE date = '2023-01-01'")

# 数据存储
put(result, "processed/prices", partitions=["date"])

# 检查数据是否存在
if has("processed/prices"):
    print("Data exists")

# 惰性扫描
lf = scan("prices").filter(pl.col("date") == "2023-01-01")

# 从MySQL读取
data = read_mysql("SELECT * FROM stock_data LIMIT 100", db_conf="DATABASES.mysql")

# 写入MySQL
write_mysql(data, "remote_table", db_conf="DATABASES.mysql", if_table_exists="append")
```

### 配置管理

```python
from lidb import get_settings

# 获取配置
settings = get_settings()

# 访问配置值
mysql_config = settings.DATABASES.mysql
polars_threads = settings.POLARS.max_threads

# 配置文件示例 (~/.config/lidb/settings.toml)
# [GLOBAL]
# path="/path/to/db"
# 
# [POLARS]
# max_threads=32
```

## 最佳实践

### 性能优化技巧

1. **使用惰性计算**：对于复杂的数据处理流程，优先使用`scan()`和`LazyFrame`，只在最后需要结果时才调用`collect()`

```python
# 推荐：惰性计算
lf = scan("data").filter(pl.col("date") > "2023-01-01").select("close")
data = lf.collect()

# 不推荐：立即计算
df = sql("SELECT close FROM data WHERE date > '2023-01-01'")
```

2. **合理使用并行处理**：在加载多个数据集时，使用`DataLoader`的并行加载功能

```python
loader = DataLoader("strategy")
loader.get(
    ds_list=[ds1, ds2, ds3],
    n_jobs=10,  # 并发数量
    backend="loky"  # 并发后端
)
```

3. **分区存储**：对于大规模数据，使用分区存储提高查询效率

```python
# 按日期和资产分区存储
put(df, "factors", partitions=["date", "asset"])
```

### 错误处理模式

```python
from lidb import Dataset
import logging

# 定义带错误处理的数据集
def safe_data_fetch():
    try:
        return sql("SELECT * FROM risky_table")
    except Exception as e:
        logging.warning(f"Failed to fetch data: {e}")
        return pl.DataFrame()  # 返回空DataFrame

safe_ds = Dataset(
    fn=safe_data_fetch,
    tb="safe_data",
    partitions=["date"]
)
```

### 配置管理建议

1. 将敏感配置（如数据库密码）放在`~/.config/lidb/settings.toml`中，不要硬编码在代码中
2. 使用环境变量覆盖配置，便于在不同环境中部署
3. 为不同环境（开发、测试、生产）使用不同的配置文件

### 代码组织方式

```python
# 推荐的代码组织结构
project/
├── data_sources/
│   ├── stock.py
│   ├── futures.py
│   └── options.py
├── factors/
│   ├── technical.py
│   ├── fundamental.py
│   └── alternative.py
├── strategies/
│   ├── mean_reversion.py
│   └── momentum.py
└── config/
    └── settings.py
```

通过合理的代码组织，可以提高代码的可维护性和可重用性。