Quick Start - Farseer

## 1 Installation

Install Farseer using pip or build from source:

### From PyPI (Recommended)

    pip install farseer

### From Source

    # Clone the repository
    git clone https://github.com/ryanbieber/seer
    cd seer

    # For Python 3.13+, set compatibility flag
    export PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1

    # Build and install with maturin
    pip install maturin
    maturin develop --release

### Prerequisites

- Python 3.11 or higher
- CmdStan (automatically installed with cmdstanpy)
- Rust toolchain (only for building from source)

## 2 Your First Forecast

Create a simple forecast in just a few lines of code:

    import polars as pl
    from datetime import datetime
    from farseer import Farseer

    # Create sample data
    df = pl.DataFrame({
        'ds': pl.date_range(
            datetime(2020, 1, 1),
            periods=100,
            interval='1d',
            eager=True
        ),
        'y': range(100)  # Simple linear trend
    })

    # Create and fit model
    m = Farseer()
    m.fit(df)

    # Make future predictions
    future = m.make_future_dataframe(periods=30)
    forecast = m.predict(future)

    # View results
    print(forecast.select(['ds', 'yhat', 'yhat_lower', 'yhat_upper']).tail())

Output:

    shape: (5, 4)
    ┌─────────────────────┬────────────┬─────────────┬─────────────┐
    │ ds                  ┆ yhat       ┆ yhat_lower  ┆ yhat_upper  │
    │ ---                 ┆ ---        ┆ ---         ┆ ---         │
    │ datetime[μs]        ┆ f64        ┆ f64         ┆ f64         │
    ╞═════════════════════╪════════════╪═════════════╪═════════════╡
    │ 2020-04-06 00:00:00 ┆ 126.234    ┆ 123.891     ┆ 128.577     │
    │ 2020-04-07 00:00:00 ┆ 127.234    ┆ 124.891     ┆ 129.577     │
    │ 2020-04-08 00:00:00 ┆ 128.234    ┆ 125.891     ┆ 130.577     │
    │ 2020-04-09 00:00:00 ┆ 129.234    ┆ 126.891     ┆ 131.577     │
    │ 2020-04-10 00:00:00 ┆ 130.234    ┆ 127.891     ┆ 132.577     │
    └─────────────────────┴────────────┴─────────────┴─────────────┘

## 3 Understanding the Model

Farseer's forecast includes several components:

- yhat: The predicted value
- yhat_lower, yhat_upper: Uncertainty intervals (default 80%)
- trend: The overall trend component
- yearly: Yearly seasonal component (if enabled)
- weekly: Weekly seasonal component (if enabled)
- daily: Daily seasonal component (if enabled)

    # View all components
    print(forecast.select([
        'ds', 'yhat', 'trend', 'yearly', 'weekly'
    ]).tail())

## 4 Customizing Your Model

Farseer provides many options to customize your forecast:

### Seasonality Settings

    m = Farseer(
        yearly_seasonality=True,   # Enable yearly patterns
        weekly_seasonality=True,   # Enable weekly patterns
        daily_seasonality=False,   # Disable daily patterns
        seasonality_mode='additive'  # or 'multiplicative'
    )

### Growth Settings

    # Linear growth (default)
    m = Farseer(growth='linear')

    # Logistic growth with capacity
    df['cap'] = 200  # Maximum capacity
    m = Farseer(growth='logistic')
    m.fit(df)

    # Flat (no trend)
    m = Farseer(growth='flat')

### Changepoint Detection

    m = Farseer(
        n_changepoints=25,           # Number of potential changepoints
        changepoint_range=0.8,       # Use first 80% of data
        changepoint_prior_scale=0.05 # Flexibility (higher = more flexible)
    )

### Uncertainty Intervals

    m = Farseer(interval_width=0.95)  # 95% confidence intervals
    m.fit(df)
    forecast = m.predict(future)

## 5 Working with Real Data

Here's a complete example with realistic data including trend and seasonality:

    import polars as pl
    import numpy as np
    from datetime import datetime
    from farseer import Farseer

    # Generate realistic data
    np.random.seed(42)
    n = 365 * 2  # 2 years of daily data
    dates = pl.date_range(datetime(2020, 1, 1), periods=n, interval='1d', eager=True)

    # Create components
    t = np.arange(n)
    trend = t * 0.5 + 100  # Linear growth
    yearly = 10 * np.sin(2 * np.pi * t / 365.25)  # Yearly seasonality
    weekly = 5 * np.sin(2 * np.pi * t / 7)  # Weekly seasonality
    noise = np.random.normal(0, 2, n)

    y = trend + yearly + weekly + noise

    df = pl.DataFrame({'ds': dates, 'y': y})

    # Split into train/test
    train_size = int(n * 0.8)
    train = df[:train_size]
    test = df[train_size:]

    # Fit model
    m = Farseer(
        yearly_seasonality=True,
        weekly_seasonality=True,
        daily_seasonality=False
    )
    m.fit(train)

    # Forecast on test set
    forecast = m.predict(test)

    # Evaluate performance
    from sklearn.metrics import mean_absolute_error, mean_squared_error

    mae = mean_absolute_error(test['y'], forecast['yhat'][:len(test)])
    rmse = np.sqrt(mean_squared_error(test['y'], forecast['yhat'][:len(test)]))

    print(f"Test MAE: {mae:.2f}")
    print(f"Test RMSE: {rmse:.2f}")

## 6 Next Steps

Now that you've got the basics, explore more advanced features:

- Weighted observations - Give more importance to recent data
- Custom regressors - Add additional variables
- Manual changepoints - Specify known trend changes
- Holiday effects - Model special events
- Performance optimization - Maximize speed

### 💡 Pro Tip

Use Polars DataFrames instead of Pandas for 5-10x better performance. Farseer is optimized for Polars but still supports Pandas for backward compatibility.