# Edge SDK

Python SDK for accessing Edge's agricultural commodity data API. Get real-time and historical CME futures data, USDA market reports, and more.

## Installation

```bash
pip install edge-sdk
```

## Quick Start

```python
from edge import Edge

# Initialize the client with your API key
edge = Edge(api_key="your-api-key")

# Get CME futures data
corn_data = edge.cme.get_futures_prices(
    symbol="ZCH5",
    start_date="2025-01-01",
    end_date="2025-01-31"
)

print(corn_data.head())
```

## Authentication

**API Key Required**: All API endpoints require a valid API key. Get your API key from the Edge platform.

### Configuration Options

**Option 1: Pass API key directly**
```python
from edge import Edge

edge = Edge(api_key="edge_your_api_key_here")
```

**Option 2: Use environment variables**
```bash
export EDGE_API_KEY="edge_your_api_key_here"
export EDGE_API_BASE_URL="https://edge-api-730192956959.us-east4.run.app"  # optional
```

```python
from edge import Edge

edge = Edge()  # Automatically uses EDGE_API_KEY from environment
```

**Option 3: Use .env file**
```bash
# .env file
EDGE_API_KEY=edge_your_api_key_here
EDGE_API_BASE_URL=https://edge-api-730192956959.us-east4.run.app
```

```python
from edge import Edge

edge = Edge()  # Automatically loads from .env
```

## API Reference

### Core Client Methods

#### `health_check()`
Check API health status.

```python
status = edge.health_check()
print(status)  # {'status': 'healthy', 'timestamp': '...'}
```

#### `list_sources()`
List all available data sources.

```python
sources = edge.list_sources()
print(sources)
```

#### `list_commodities(category=None, is_active=True)`
List available commodities.

```python
# All commodities
all_commodities = edge.list_commodities()

# Filter by category
livestock = edge.list_commodities(category="LIVESTOCK")
```

#### `list_regions(region_type=None, country_code=None)`
List geographic regions.

```python
# All regions
regions = edge.list_regions()

# Filter by type
countries = edge.list_regions(region_type="COUNTRY")

# Filter by country
us_states = edge.list_regions(country_code="US")
```

#### `list_themes()`
List time series themes.

```python
themes = edge.list_themes()
```

#### `search_series(search_term, source_name=None, limit=50)`
Search for time series by keyword.

```python
# Search all sources
results = edge.search_series("corn")

# Search specific source
usda_corn = edge.search_series("corn", source_name="USDA", limit=10)
```

#### `get_series(series_code, source_name="USDA", start_date=None, end_date=None, limit=None)`
Get time series data (convenience method).

```python
data = edge.get_series(
    series_code="SOME_SERIES_CODE",
    source_name="USDA",
    start_date="2024-01-01",
    end_date="2024-12-31"
)
```

### CME Service (`edge.cme`)

Access CME futures and calendar spread data.

#### `list_symbols()`
List all available CME symbols with data.

```python
symbols = edge.cme.list_symbols()
print(symbols)  # ['ZCH5', 'ZCN5', 'ZCZ5', ...]
```

#### `get_futures_prices(symbol, start_date=None, end_date=None, limit=500)`
Get OHLCV data for a specific futures contract.

```python
# Get corn December 2025 futures
corn_data = edge.cme.get_futures_prices(
    symbol="ZCZ5",
    start_date="2025-01-01",
    end_date="2025-01-31"
)

# Returns DataFrame with columns:
# observation_datetime, open, high, low, close, volume,
# open_interest, settlement_price, bid_price, ask_price, etc.
```

#### `get_spread_data(spread_symbol, start_date=None, end_date=None, limit=500)`
Get calendar spread data between two contract months.

```python
# Get Dec 2025 - Mar 2026 corn spread
spread = edge.cme.get_spread_data(
    spread_symbol="ZCZ5-ZCH6",
    start_date="2025-01-01",
    end_date="2025-01-31"
)

# Returns DataFrame with OHLCV for the spread
```

**Supported CME Symbols:**
- **Grains**: ZC (Corn), ZS (Soybeans), ZW (Wheat), ZL (Soybean Oil), ZM (Soybean Meal)
- **Livestock**: LE (Live Cattle), GF (Feeder Cattle), HE (Lean Hogs)
- **Energy**: CL (Crude Oil), NG (Natural Gas), RB (Gasoline), HO (Heating Oil)
- **Metals**: GC (Gold), SI (Silver), HG (Copper)
- **Financials**: ES (S&P 500), NQ (Nasdaq), YM (Dow)

### Time Series Service (`edge.time_series`)

Generic time series data access.

#### `get_data(series_code, source_name, start_date=None, end_date=None, limit=None)`
Get time series data for any source.

```python
data = edge.time_series.get_data(
    series_code="BEEF_CUTOUT_SERIES",
    source_name="USDA",
    start_date="2024-01-01"
)
```

#### `get_metadata(series_code=None, source_name=None, theme_name=None, commodity_code=None, region_code=None, limit=50)`
Get metadata about available time series.

```python
# Get all USDA series metadata
usda_meta = edge.time_series.get_metadata(source_name="USDA", limit=100)

# Filter by commodity
corn_series = edge.time_series.get_metadata(commodity_code="CORN")
```

#### `search(search_term, source_name=None, limit=50)`
Search time series by description or code.

```python
results = edge.time_series.search("beef prices", limit=20)
```

#### `get_multiple(series_configs, start_date=None, end_date=None, limit=None)`
Get multiple time series in one request.

```python
configs = [
    {"series_code": "ZCH5", "source_name": "CME"},
    {"series_code": "ZCN5", "source_name": "CME"},
]
data = edge.time_series.get_multiple(
    series_configs=configs,
    start_date="2025-01-01"
)
```

## Usage Examples

### Complete Workflow Example

```python
from edge import Edge
import pandas as pd

# Initialize client
edge = Edge(api_key="your-api-key")

# 1. Discover available symbols
symbols = edge.cme.list_symbols()
print(f"Found {len(symbols)} CME symbols")

# 2. Get futures data for corn
corn = edge.cme.get_futures_prices(
    symbol="ZCZ5",
    start_date="2025-01-01",
    end_date="2025-01-31"
)

# 3. Calculate statistics
print(f"Average Close: ${corn['close'].mean():.2f}")
print(f"High: ${corn['high'].max():.2f}")
print(f"Low: ${corn['low'].min():.2f}")

# 4. Get spread data
spread = edge.cme.get_spread_data(
    spread_symbol="ZCZ5-ZCH6",
    start_date="2025-01-01"
)

print(f"Current Spread: ${spread.iloc[-1]['close']:.2f}")

# Close the client
edge.close()
```

### Working with DataFrames

All data is returned as pandas DataFrames for easy analysis:

```python
import matplotlib.pyplot as plt

# Get CME data
data = edge.cme.get_futures_prices("ZCH5", start_date="2025-01-01")

# Plot OHLC
data.plot(x="observation_datetime", y=["open", "high", "low", "close"], figsize=(12, 6))
plt.title("Corn Futures - March 2025")
plt.show()

# Calculate statistics
print(data[["open", "high", "low", "close"]].describe())

# Resample to weekly
weekly = data.set_index("observation_datetime")["close"].resample("W").mean()
```

### Error Handling

```python
from edge import Edge
from edge.exceptions import EdgeAPIError, DataNotFoundError, AuthenticationError

try:
    edge = Edge(api_key="your-api-key")
    data = edge.cme.get_futures_prices("INVALID_SYMBOL")
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
except DataNotFoundError as e:
    print(f"Data not found: {e}")
except EdgeAPIError as e:
    print(f"API error: {e}")
```

### Context Manager

Use the client as a context manager for automatic cleanup:

```python
with Edge(api_key="your-key") as edge:
    data = edge.cme.get_futures_prices("ZCH5")
    print(data.head())
    # Client automatically closes when done
```

### Advanced Configuration

```python
# Custom base URL and timeout
edge = Edge(
    api_key="your-api-key",
    base_url="http://localhost:8000",  # for local development
    timeout=60  # 60 second timeout
)

# Get limited results for performance
data = edge.cme.get_futures_prices(
    symbol="ZCH5",
    limit=100  # Only get 100 most recent records
)
```

## Data Returned

### CME Futures Data

CME futures data includes the following fields:

| Field | Type | Description |
|-------|------|-------------|
| `observation_datetime` | datetime | Timestamp of the observation |
| `open` | float | Opening price |
| `high` | float | High price |
| `low` | float | Low price |
| `close` | float | Closing price |
| `volume` | float | Trading volume |
| `open_interest` | float | Open interest |
| `settlement_price` | float | Settlement price |
| `bid_price` | float | Bid price |
| `ask_price` | float | Ask price |
| `bid_size` | float | Bid size |
| `ask_size` | float | Ask size |

### Time Series Data

Generic time series data includes:

| Field | Type | Description |
|-------|------|-------------|
| `observation_date` | date | Date of observation |
| `value` | float | Primary value |
| `value_high` | float | High value (if applicable) |
| `value_low` | float | Low value (if applicable) |
| `volume` | float | Volume (if applicable) |
| `quality_flag` | string | Data quality indicator |

## Exception Types

The SDK provides specific exception types for better error handling:

- **`EdgeAPIError`**: Base exception for all API errors
- **`AuthenticationError`**: Raised when API key is invalid or missing
- **`DataNotFoundError`**: Raised when requested data is not found (404)

```python
from edge.exceptions import EdgeAPIError, AuthenticationError, DataNotFoundError
```

## Requirements

- Python 3.9+
- pandas>=2.0
- httpx>=0.25
- python-dotenv>=1.0

## Support

For issues or questions:
- Documentation: https://docs.edge-api.com
- Email: support@try-edge.com
- GitHub: https://github.com/edge-monorepo/edge-sdk

## License

MIT License - see LICENSE file for details.