Skip to content

garthmortensen/timeseries-api

Repository files navigation

Timeseries API

GitHub Docker Hub

CI/CD Codacy Badge Coverage

Overview

  ████████╗██╗███╗   ███╗███████╗███████╗███████╗██████╗ ██╗███████╗███████╗
  ╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██╔════╝██╔══██╗██║██╔════╝██╔════╝
     ██║   ██║██╔████╔██║█████╗  ███████╗█████╗  ██████╔╝██║█████╗g ███████╗
     ██║   ██║██║╚██╔╝██║██╔══╝  ╚════██║██╔══╝  ██╔══██╗██║██╔══╝m ╚════██║
     ██║   ██║██║ ╚═╝ ██║███████╗███████║███████╗██║  ██║██║███████╗███████║
     ╚═╝   ╚═╝╚═╝     ╚═╝╚══════╝╚══════╝╚══════╝╚═╝  ╚═╝╚═╝╚══════╝╚══════╝
              █████╗ ██████╗ ██╗
             ██╔══██╗██╔══██╗██║
             ███████║██████╔╝██║
             ██╔══██║██╔═══╝ ██║
             ██║  ██║██║     ██║
             ╚═╝  ╚═╝╚═╝     ╚═╝

A production-grade FastAPI pipeline for comprehensive time series analysis with ARIMA/GARCH modeling and advanced spillover analysis.

Implementation hosted at www.spilloverlab.com.

This project provides multiple interfaces for financial and econometric data analysis:

  • CLI interface for command-line usage and batch processing
  • REST API with FastAPI endpoints and comprehensive OpenAPI documentation
  • GraphQL API for flexible queries and selective data fetching
  • MCP Server for direct LLM agent integration and natural language processing

Features

  • REST & GraphQL APIs for time series analysis with comprehensive OpenAPI documentation
  • MCP Server Integration - Expose all endpoints as structured tools for LLM agents
  • Advanced Statistical Modeling - ARIMA and GARCH modeling capabilities with spillover analysis
  • Multi-source Data Support - Generate synthetic data or fetch real market data (Yahoo Finance, Stooq)
  • Comprehensive Data Processing - Scaling, stationarity testing, returns conversion, and missing data handling
  • Production Ready - Docker containerization, comprehensive test suite, and CI/CD pipeline
  • Real-time Analysis - Rolling spillover analysis and volatility forecasting
  • Human-readable Interpretations - Automatic generation of plain English explanations for statistical results

Difficult lessons

  • Too late in the game I created export_data() utility.

  • My logging script broke down at some point and I never restored it to fully functional. I really need a top-grade logging utility.

  • Never ever take the shortcut of using undefined dataframes/nested dicts as inputs and returns. Take the time to expand so that the function signature provides a clear and open API contract for downstream users.

  • I'm at odds with the iterative process in this project. By doing a first iteration across package then api then app, and and looping to 2nd full iteration, i spent the majority of time resolving integration issues. Update the package? Now everything downstream needs integrating, and it's difficult to determine what exactly broke. For this project, i needed to spend 5x more effort on determining data structures, methodology, and the entire garch pipeline before getting to work. I needed way more planning...though scope creep was also to blame.

  • i should've made the api much more modular:

    # services.py
    def make_stationary(df): …
    def fill_missing(df): …
    # …more steps…
    
    # routers/transforms.py
    from fastapi import APIRouter
    from services import make_stationary, fill_missing
    
    router = APIRouter(prefix="/transforms")
    @router.post("/stationary")
    def stationary(data: DataModel):
        return make_stationary(data)
    
    @router.post("/fill-missing")
    def fill_missing_endpoint(data: DataModel):
        return fill_missing(data)
    
    # routers/pipeline.py
    from fastapi import APIRouter, Depends
    from services import make_stationary, fill_missing, … 
    
    router = APIRouter(prefix="/pipeline")
    @router.post("/full")
    def full_pipeline(data: DataModel):
        df1 = make_stationary(data)
        df2 = fill_missing(df1)
        # …chain the rest…
        return df_final
    
    # main.py
    from fastapi import FastAPI
    from routers import transforms, pipeline
    
    app = FastAPI()
    app.include_router(transforms.router)
    app.include_router(pipeline.router)

Integration Overview

flowchart TB
    %% Styling
    classDef person fill:#7B4B94,color:#fff,stroke:#5D2B6D,stroke-width:1px
    classDef agent fill:#7B4B94,color:#fff,stroke:#5D2B6D,stroke-width:1px
    classDef system fill:#1168BD,color:#fff,stroke:#0B4884,stroke-width:1px
    classDef external fill:#999999,color:#fff,stroke:#6B6B6B,stroke-width:1px
    classDef database fill:#2E7C8F,color:#fff,stroke:#1D4E5E,stroke-width:1px
    classDef publishing fill:#E67E22,color:#fff,stroke:#D35400,stroke-width:1px
    
    %% Actors and Systems
    User((User)):::person
    AIAgent((AI Agent)):::agent
    
    %% Main Systems
    TimeSeriesFrontend["Frontend App"]:::system
    TimeSeriesPipeline["RESTful Pipeline"]:::system
    MCPServer["MCP Server"]:::system
    TimeseriesCompute["Timeseries-Compute 
    Python Package"]:::system
    
    %% Database
    TimeSeriesDB[("Relational database")]:::database
    
    %% External Systems
    ExternalDataSource[(Yahoo Finance / Stooq)]:::external
    
    %% Publishing Platforms
    PublishingPlatforms["
    GitHub
    Docker Hub
    Google Cloud Run
    PyPI
    Read the Docs"]:::publishing
    
    %% Relationships
    User -- "Uses UI" --> TimeSeriesFrontend
    AIAgent -- "Natural language requests" --> MCPServer
    TimeSeriesFrontend -- "Makes API calls to" --> TimeSeriesPipeline
    MCPServer -- "Makes API calls to" --> TimeSeriesPipeline
    TimeSeriesPipeline -- "Inserts results into" --> TimeSeriesDB
    TimeSeriesPipeline -- "imports" --> TimeseriesCompute
    User -- "pip install" --> TimeseriesCompute
    AIAgent -- "pip install" --> TimeseriesCompute
    ExternalDataSource -- "Provides time series data" --> TimeSeriesPipeline
    
    %% Publishing relationships (simplified)
    TimeSeriesFrontend  --> PublishingPlatforms
    TimeSeriesPipeline --> PublishingPlatforms
    TimeseriesCompute --> PublishingPlatforms
Loading

Quick Start

Docker

Pull the Docker image:

docker pull goattheprofessionalmeower/timeseries-api

Run the container:

docker run -d -p 8001:8001 --name timeseries-api-container goattheprofessionalmeower/timeseries-api:latest

Local Setup

  1. Clone the repository:

    git clone https://github.com/garthmortensen/timeseries-api.git
    cd timeseries-api
  2. Create a virtual environment:

    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
  3. Install dependencies:

    pip install -r requirements.txt
  4. Run the FastAPI app:

    python -m fastapi_pipeline
    # or
    make run-local

API Endpoints

Category Endpoint HTTP Verb Description
Data Operations /api/v1/generate_data POST Generate synthetic time series data
/api/v1/fetch_market_data POST Fetch real market data from Yahoo Finance
/api/v1/fetch_stooq_data POST Fetch real market data from Stooq
/api/v1/scale_data POST Scale time series data using various methods
/api/v1/test_stationarity POST Test for stationarity using ADF test
/api/v1/price_to_returns POST Convert price data to log returns
/api/v1/scale_for_garch POST Scale data specifically for GARCH modeling
Statistical Models /api/v1/run_arima POST Run ARIMA model on time series
/api/v1/run_garch POST Run GARCH model on time series
Pipeline /api/v1/run_pipeline POST Execute the complete end-to-end analysis pipeline
Spillover Analysis /api/v1/analyze_spillover POST Analyze spillover effects between time series
/api/v1/rolling_spillover POST Compute rolling window spillover analysis
GraphQL /v1/graphql POST GraphQL endpoint for flexible queries and mutations

API docs:

GraphQL Features

  • Type-safe schema all inputs are automatically validated against predefined types, preventing runtime errors and ensuring data consistency
  • Flexible queries you can specify exactly which data fields to return, reducing bandwidth and improving performance by avoiding over-fetching
  • Single endpoint one URL (/v1/graphql) handles all queries and mutations instead of multiple REST endpoints, simplifying API integration
  • Real-time introspection the API schema is self-documenting and can be explored interactively without separate documentation files

GraphQL Playground

Visit http://localhost:8001/graphql to access the interactive GraphQL playground with:

  • Schema explorer and documentation, so you can browse all available types, queries, and mutations with their descriptions and field definitions
  • Query autocompletion
  • Real-time query validation, meaning syntax errors and type mismatches are immediately highlighted
  • Built-in query history - your previous queries are automatically saved and can be recalled for reuse or modification

Sample GraphQL Queries

Health Check:

query HealthCheck {
  health
}

Complete Pipeline Analysis:

mutation SyntheticPipeline {
  runPipeline(input: {
    sourceActualOrSyntheticData: "synthetic"
    dataStartDate: "2023-01-01"
    dataEndDate: "2023-02-01"
    symbols: ["GME", "BYND"]
    syntheticAnchorPrices: [150.0, 200.0]
    syntheticRandomSeed: 42
    arimaParams: "{\"p\": 1, \"d\": 1, \"q\": 1}"
    garchParams: "{\"p\": 1, \"q\": 1, \"dist\": \"normal\"}"
    spilloverEnabled: false
    spilloverParams: "{}"
  }) {
    originalData { date values }
    returnsData { date values }
    stationarityResults {
      allSymbolsStationarity
      seriesStats
    }
    arimaResults
    garchResults
  }
}

Real Market Data with Spillover Analysis:

mutation MarketDataAnalysis {
  runPipeline(input: {
    sourceActualOrSyntheticData: "actual_stooq"
    dataStartDate: "2023-01-01"
    dataEndDate: "2023-12-31"
    symbols: ["AAPL.US", "MSFT.US", "GOOGL.US"]
    scalingMethod: "standardize"
    arimaParams: "{\"p\": 1, \"d\": 1, \"q\": 1}"
    garchParams: "{\"p\": 1, \"q\": 1, \"dist\": \"t\"}"
    spilloverEnabled: true
    spilloverParams: "{\"method\": \"diebold_yilmaz\", \"forecast_horizon\": 10}"
  }) {
    spilloverResults {
      totalSpilloverIndex
      directionalSpillover
      netSpillover
      interpretation
    }
  }
}

Parameterized Query:

mutation ParameterizedAnalysis(
  $startDate: String = "2023-01-01"
  $symbols: [String!] = ["GME", "BYND"]
  $enableSpillover: Boolean = false
) {
  runPipeline(input: {
    sourceActualOrSyntheticData: "synthetic"
    dataStartDate: $startDate
    dataEndDate: "2023-02-01"
    symbols: $symbols
    syntheticAnchorPrices: [150.0, 200.0]
    arimaParams: "{\"p\": 1, \"d\": 1, \"q\": 1}"
    garchParams: "{\"p\": 1, \"q\": 1, \"dist\": \"normal\"}"
    spilloverEnabled: $enableSpillover
    spilloverParams: "{}"
  }) {
    stationarityResults { allSymbolsStationarity }
    arimaResults
    garchResults
  }
}

Configuration

The application uses YAML configuration file config/config.yml to set:

  • Data generation parameters
  • Data processing strategies
  • Model parameters for ARIMA and GARCH

Development

Project Structure

timeseries-api/.........................
├── cli_pipeline.py                   # Runs the full pipeline from the terminal sans API
├── fastapi_pipeline.py               # Starts the API server with uvicorn
├── mcp_server.py                     # MCP server for LLM agent integration
├── Makefile                          # Automates dev tasks
├── smoketest.sh                      # Quickly verifies endpoints are functional
├── smoketest_results.txt             # Output from latest smoke test run
├── pipeline.md                       # Documents pipeline architecture and steps
├── pyproject.toml                    # Modern Python project configuration
├── requirements.txt                  # Python dependencies
├── uv.lock                           # Lock file for uv package manager
├── save_openapi_json.py              # Utility to export OpenAPI specification
├── docker-compose.yml                # Docker Compose configuration
├── Dockerfile                        # Main Docker container definition
├── Dockerfile.mcp                    # Docker container for MCP server
├── ADR.md                            # Architectural Decision Records
├── config/............................
│   └── config.yml                    # Centralizes all pipeline params
├── api/...............................
│   ├── __init__.py                   # Makes API module importable and adds parent dir to path
│   ├── app.py                        # Initializes FastAPI and registers routes
│   ├── database.py                   # Database models and initialization for PostgreSQL
│   ├── openapi.json                  # Generated OpenAPI specification
│   ├── schema.graphql                # GraphQL schema definition
│   ├── gql/...........................
│   │   ├── __init__.py               # GraphQL package initializer
│   │   ├── resolvers.py              # GraphQL resolver functions
│   │   └── types.py                  # GraphQL type definitions
│   ├── middleware/....................
│   │   ├── __init__.py               # Middleware package initializer
│   │   └── rate_limiting.py          # Rate limiting middleware implementation
│   ├── models/........................
│   │   ├── __init__.py               # Exports all models and makes module importable
│   │   ├── input.py                  # Defines and validates request payload schemas (including spillover)
│   │   └── response.py               # Defines and validates response formats (including spillover)
│   ├── routers/.......................
│   │   ├── __init__.py               # Exports router instances and makes module importable
│   │   ├── data.py                   # Handles data generation and transformation endpoints
│   │   ├── models.py                 # Implements statistical modeling endpoints
│   │   ├── pipeline.py               # Provides end-to-end analysis pipeline endpoint
│   │   └── spillover.py              # Handles spillover analysis endpoints
│   ├── services/......................
│   │   ├── __init__.py               # Exports service functions and makes module importable
│   │   ├── data_service.py           # Implements data processing business logic
│   │   ├── models_service.py         # Implements statistical modeling business logic
│   │   ├── interpretations.py        # Generates human-readable explanations of statistical results
│   │   ├── spillover_service.py      # Implements spillover analysis business logic
│   │   └── market_data_service.py    # Handles external data fetching (Yahoo Finance, Stooq)
│   └── utils/.........................
│       ├── __init__.py               # Exports utility functions and makes module importable
│       └── json_handling.py          # Handles JSON serialization NaN values (MacOS compatibility issue)
├── utilities/.........................
│   ├── chronicler.py                 # Configures standardized logging across the application
│   ├── configurator.py               # Loads and validates YAML configuration
│   ├── export_util.py                # Utility for exporting data at pipeline steps
│   ├── stooq_test.py                 # Test script for Stooq data source
│   ├── yfinance_test.py              # Test script for Yahoo Finance data source
│   ├── yfinance_ratelimit.py         # Rate limiting utilities for Yahoo Finance API
│   └── yfinance_ratelimit_test.py.bak # Backup of rate limiting test script
├── tests/.............................
│   ├── __init__.py                   # Makes tests discoverable
│   ├── test_chronicler.py            # Tests logging functionality
│   ├── test_configurator.py          # Tests configuration loading and validation
│   ├── test_fastapi_pipeline.py      # Tests API endpoints and response formats
│   ├── test_response_models.py       # Validates response model schemas
│   └── test_yfinance_fetch.py        # Tests external market data fetching
├── database/..........................
│   └── migrations/                   # Database migration scripts (when database enabled)
├── logs/..............................
│   └── *.log                         # Application log files with timestamps
├── outputs/...........................
│   └── *                             # Pipeline output files and exported data
├── timeseries_api.egg-info/...........
│   └── *                             # Python package metadata
└── .github/workflows/.................
    └── cicd.yml                      # Automates testing, Docker image deployment, etc

Testing

Run smoke tests (after launching app):

bash smoketest.sh

Run the test suite:

pytest .

Docker

Build the Docker image:

make docker-build

Run with Docker:

make docker-run

For interactive shell:

make docker-run-interactive

CI/CD Pipeline

The project uses GitHub Actions for:

  • Running tests on multiple Python versions and platforms
  • Building and pushing Docker images
  • Code coverage reporting

Additional (C4) Architectural Diagrams

Each level of a C4 diagram provides a different level of zoom. This helps users understand a project at the most-useful granularity.

level 2: Container Diagram

Zooms in one level to show the major building blocks/"containers". Containers are diff tech chunks that work together. The main engine is FastAPI, which reads from a config.yml file. It's all packed in a Docker container for easy deployment, and a CI/CD pipeline automates testing and building.

flowchart TB
    %% Styling
    classDef person fill:#08427B,color:#fff,stroke:#052E56,stroke-width:1px
    classDef container fill:#438DD5,color:#fff,stroke:#2E6295,stroke-width:1px
    classDef external fill:#999999,color:#fff,stroke:#6B6B6B,stroke-width:1px
    classDef system fill:#1168BD,color:#fff,stroke:#0B4884,stroke-width:1px
    
    %% Person
    User((User)):::person
    
    %% System boundary
    subgraph TimeSeriesPipeline["Time Series Pipeline System"]
        FastAPI["FastAPI Application<br>[Python]<br>Provides API endpoints"]:::container
        Dockerized["Docker Container<br>[Linux]<br>Containerized deployment"]:::container
        Config["Configuration<br>[YAML]<br>Configures pipeline params"]:::container
        Database["PostgreSQL Database<br>[Optional/Disabled by default]<br>Can store pipeline results"]:::container
        CIpipeline["CI/CD Pipeline<br>[GitHub Actions]<br>Automates testing"]:::container
    end
    
    %% External Systems
    ExternalDataSource[(External Data Source<br>Yahoo Finance/Stooq API)]:::external
    
    %% Relationships
    User -- "Uses [HTTP/JSON]" --> FastAPI
    FastAPI -- "Reads" --> Config
    FastAPI -- "Can store results in" --> Database
    FastAPI -- "Packaged into" --> Dockerized
    CIpipeline -- "Builds and tests" --> Dockerized
    ExternalDataSource -- "Provides market data [yfinance/stooq]" --> FastAPI
Loading

level 3: Component Diagram

Look inside the FastAPI app to see the key components. We can see various services like the Data Service for handling data, Models Service for statistical analysis, and Interpretation Service for making sense of results.

flowchart TB
    %% Styling
    classDef person fill:#08427B,color:#fff,stroke:#052E56,stroke-width:1px
    classDef component fill:#85BBF0,color:#000,stroke:#5D82A8,stroke-width:1px
    classDef container fill:#438DD5,color:#fff,stroke:#2E6295,stroke-width:1px
    classDef external fill:#999999,color:#fff,stroke:#6B6B6B,stroke-width:1px
    
    %% Person
    User((User)):::person
    
    %% API Container
    subgraph FastAPI["FastAPI Application"]
        APIRouters["API Routers<br>[Python]<br>Manages endpoints"]:::component
        DataService["Data Service<br>[Python]<br>Data transformations"]:::component
        ModelsService["Models Service<br>[Python]<br>Statistical models"]:::component
        SpillloverService["Spillover Service<br>[Python]<br>Spillover analysis & causality"]:::component
        MarketDataService["Market Data Service<br>[Python]<br>Fetches external data"]:::component
        ChroniclerUtil["Chronicler<br>[Python]<br>Handles logging"]:::component
        ConfigUtil["Configurator<br>[Python]<br>Manages config"]:::component
        InterpretationService["Interpretation Service<br>[Python]<br>Interprets results"]:::component
        JsonHandling["JSON Handling<br>[Python]<br>JSON serialization"]:::component
        GraphQLComponents["GraphQL Components<br>[Python]<br>Schema, resolvers, types"]:::component
        Middleware["Rate Limiting Middleware<br>[Python]<br>API rate limiting"]:::component
        DatabaseModels["Database Models<br>[Python]<br>SQLAlchemy models (optional)"]:::component
        
        %% Component relationships
        APIRouters --> DataService
        APIRouters --> ModelsService
        APIRouters --> SpillloverService
        APIRouters --> MarketDataService
        APIRouters --> InterpretationService
        APIRouters --> Middleware
        DataService --> MarketDataService
        DataService --> ChroniclerUtil
        ModelsService --> ChroniclerUtil
        SpillloverService --> ChroniclerUtil
        DataService --> ConfigUtil
        ModelsService --> ConfigUtil
        SpillloverService --> ConfigUtil
        APIRouters --> JsonHandling
        APIRouters --> GraphQLComponents
        APIRouters --> DatabaseModels
        DataService --> InterpretationService
        ModelsService --> InterpretationService
        SpillloverService --> InterpretationService
    end
    
    %% External
    ConfigFile[(Config YAML)]:::external
    ExternalMarketSource[(Yahoo Finance API)]:::external
    
    %% Relationships
    User -- "Makes API requests to" --> APIRouters
    ConfigUtil -- "Reads from" --> ConfigFile
    MarketDataService -- "Fetches data from" --> ExternalMarketSource
Loading

level 4: Code/Class Diagram

Shows the classes involved in handling ARIMA and GARCH statistical models, including input classes that define what data goes in and response classes that define what comes back.

classDiagram
    %% Main Application Classes
    class App {
        +app: FastAPI
        +config: Config
    }
    
    %% Router Classes
    class DataRouter {
        +router: APIRouter
        +generate_data_endpoint(input_data)
        +fetch_market_data_endpoint(input_data)
        +scale_data_endpoint(input_data)
        +test_stationarity_endpoint(input_data)
    }

    class ModelsRouter {
        +router: APIRouter
        +run_arima_endpoint(input_data)
        +run_garch_endpoint(input_data)
    }
    
    class PipelineRouter {
        +router: APIRouter
        +run_pipeline_endpoint(pipeline_input)
    }
    
    class SpilloverRouter {
        +router: APIRouter
        +analyze_spillover_endpoint(input_data)
        +rolling_spillover_endpoint(input_data)
    }
    
    %% Service Classes
    class DataService {
        +generate_data_step(pipeline_input, config)
        +fill_missing_data_step(df, config)
        +scale_data_step(df, config)
        +stationarize_data_step(df, config)
        +test_stationarity_step(df, config)
        +convert_to_returns_step(df, config)
        +scale_for_garch_step(df, config)
    }
    
    class MarketDataService {
        +fetch_market_data(symbols, start_date, end_date, interval)
    }
    
    class ModelsService {
        +run_arima_step(df_stationary, config)
        +run_garch_step(df_stationary, config)
    }
    
    class InterpretationService {
        +interpret_stationarity_test(adf_results, p_value_threshold)
        +interpret_arima_results(model_summary, forecast)
        +interpret_garch_results(model_summary, forecast)
    }
    
    class SpilloverService {
        +analyze_spillover(df, config)
        +rolling_spillover(df, window, config)
        +granger_causality(df, max_lag, config)
        +perform_granger_causality(df, max_lag, config)
        +get_var_results_from_spillover(spillover_results)
    }
    
    %% Utility Classes
    class JsonHandling {
        +round_for_json(obj, decimals)
        +RoundingJSONEncoder
        +RoundingJSONResponse
    }
    
    class Configurator {
        +read_config_from_fs(config_filename)
        +load_configuration(config_file)
    }
    
    class Chronicler {
        +init_chronicler()
        +log_file: str
    }
    
    class GitInfo {
        +run_git_command(command)
        +update_git_info()
        +get_info()
    }
    
    %% Input Models
    class BaseInputModel {
        <<abstract>>
    }
    
    class DataGenerationInput {
        +start_date: str
        +end_date: str
        +anchor_prices: dict
    }
    
    class MarketDataInput {
        +symbols: List[str]
        +start_date: str
        +end_date: str
        +interval: str
    }
    
    class ScalingInput {
        +method: str
        +data: list
    }
    
    class StationarityTestInput {
        +data: list
    }
    
    class ARIMAInput {
        +p: int
        +d: int
        +q: int
        +data: list
    }
    
    class GARCHInput {
        +p: int
        +q: int
        +data: list
        +dist: str
    }
    
    class PipelineInput {
        +source_actual_or_synthetic_data: str
        +data_start_date: str
        +data_end_date: str
        +symbols: List[str]
        +synthetic_anchor_prices: List[float]
        +synthetic_random_seed: int
        +scaling_method: str
        +arima_params: dict
        +garch_params: dict
    }
    
    %% Response Models
    class BaseResponseModel {
        <<abstract>>
    }
    
    class TimeSeriesDataResponse {
        +data: Dict[str, Dict[str, Any]]
    }
    
    class StationarityTestResponse {
        +adf_statistic: float
        +p_value: float
        +critical_values: Dict[str, float]
        +is_stationary: bool
        +interpretation: str
    }
    
    class ARIMAModelResponse {
        +fitted_model: str
        +parameters: Dict[str, float]
        +p_values: Dict[str, float]
        +forecast: List[float]
    }
    
    class GARCHModelResponse {
        +fitted_model: str
        +forecast: List[float]
    }
    
    class PipelineResponse {
        +stationarity_results: StationarityTestResponse
        +arima_summary: str
        +arima_forecast: List[float]
        +garch_summary: str
        +garch_forecast: List[float]
    }
    
    %% Core Statistical Models
    class StatsModels {
        +run_arima(df_stationary, p, d, q, forecast_steps)
        +run_garch(df_stationary, p, q, dist, forecast_steps)
    }
    
    %% Relationships
    App --> DataRouter: includes
    App --> ModelsRouter: includes
    App --> PipelineRouter: includes
    App --> Configurator: uses
    App --> Chronicler: uses
    
    DataRouter --> DataService: uses
    DataRouter --> MarketDataService: uses
    DataRouter --> DataGenerationInput: accepts
    DataRouter --> MarketDataInput: accepts
    DataRouter --> ScalingInput: accepts
    DataRouter --> StationarityTestInput: accepts
    DataRouter --> TimeSeriesDataResponse: returns
    DataRouter --> StationarityTestResponse: returns
    
    DataService --> MarketDataService: uses
    
    ModelsRouter --> ModelsService: uses
    ModelsRouter --> ARIMAInput: accepts
    ModelsRouter --> GARCHInput: accepts
    ModelsRouter --> ARIMAModelResponse: returns
    ModelsRouter --> GARCHModelResponse: returns
    
    PipelineRouter --> DataService: uses
    PipelineRouter --> ModelsService: uses
    PipelineRouter --> PipelineInput: accepts
    PipelineRouter --> PipelineResponse: returns
    
    SpilloverRouter --> SpilloverService: uses
    SpilloverRouter --> DataService: uses
    SpilloverRouter --> PipelineService: uses
    SpilloverRouter --> SpilloverInput: accepts
    SpilloverRouter --> SpilloverResponse: returns
    
    DataService --> InterpretationService: uses
    DataService --> Configurator: uses
    DataService --> Chronicler: uses
    
    ModelsService --> InterpretationService: uses
    ModelsService --> StatsModels: uses
    ModelsService --> Configurator: uses
    ModelsService --> Chronicler: uses
    
    Chronicler --> GitInfo: uses
    
    BaseInputModel <|-- DataGenerationInput: extends
    BaseInputModel <|-- MarketDataInput: extends
    BaseInputModel <|-- ScalingInput: extends
    BaseInputModel <|-- StationarityTestInput: extends
    BaseInputModel <|-- ARIMAInput: extends
    BaseInputModel <|-- GARCHInput: extends
    BaseInputModel <|-- PipelineInput: extends
    
    BaseResponseModel <|-- TimeSeriesDataResponse: extends
    BaseResponseModel <|-- StationarityTestResponse: extends
    BaseResponseModel <|-- ARIMAModelResponse: extends
    BaseResponseModel <|-- GARCHModelResponse: extends
    BaseResponseModel <|-- PipelineResponse: extends
Loading

MCP Server Integration

The Model Context Protocol (MCP) Server enables direct integration with LLM agents and AI assistants. This allows agents to interact with your timeseries API using natural language requests that are automatically translated into API calls.

Features

  • Structured Tool Definitions - All API endpoints are exposed as properly typed tools with comprehensive documentation
  • Type Safety - Full parameter validation and error handling for reliable agent interactions
  • Natural Language Interface - LLM agents can request complex analyses using conversational language
  • Complete Coverage - All REST/GraphQL endpoints are available as MCP tools, including the full pipeline

Starting the MCP Server

  1. Ensure your FastAPI server is running:

    python fastapi_pipeline.py
  2. Start the MCP server in a separate terminal:

    python mcp_server.py
  3. Or specify a custom API URL:

    python mcp_server.py --api-url http://your-api-host:8001

Available MCP Tools

The MCP server exposes all API endpoints as structured tools:

Tool Category Tool Name Description
GraphQL Tools graphql_health_check Check API health using GraphQL
graphql_fetch_market_data Fetch market data via GraphQL with flexible field selection
graphql_test_stationarity Test stationarity using GraphQL endpoint
graphql_run_complete_pipeline Execute complete pipeline with selective data fetching
graphql_run_arima_model Run ARIMA models via GraphQL
graphql_run_garch_model Run GARCH models via GraphQL
graphql_custom_query Execute custom GraphQL queries for advanced use cases
Data Operations generate_synthetic_data Generate synthetic time series data for testing
fetch_market_data Fetch real market data from Yahoo Finance
fetch_stooq_data Fetch real market data from Stooq
scale_data Scale data using standard/minmax/robust methods
test_stationarity Test for stationarity using ADF test
convert_to_returns Convert price data to log returns
scale_for_garch Scale data specifically for GARCH modeling
Stats Models run_arima_model Fit ARIMA models with forecasting
run_garch_model Fit GARCH models for volatility analysis
Spillover Analysis analyze_spillover Analyze spillover effects between series
rolling_spillover Compute rolling window spillover analysis
Complete Pipeline run_complete_pipeline Execute end-to-end analysis workflow

Example Agent Interactions

LLM agents can now perform complex analyses with natural language:

Agent: "Generate synthetic data for AAPL and TSLA from 2023-01-01 to 2023-12-31, then run the complete analysis pipeline with spillover analysis enabled."

MCP Server: Calls generate_synthetic_data() then run_complete_pipeline() automatically with the specified parameters.
Agent: "Fetch real market data for GME and analyze its volatility using GARCH modeling."

MCP Server: Calls fetch_market_data() followed by run_garch_model() and provides comprehensive volatility analysis.
Agent: "Perform spillover analysis between SPY, VIX, and GLD to understand market interconnectedness during the last year."

MCP Server: Calls fetch_market_data() for all symbols, converts to returns, and runs analyze_spillover() with interpretation.

Enhanced Spillover Analysis

The API now features significantly enhanced spillover analysis capabilities with multi-level significance testing and comprehensive interpretations:

Enhanced Spillover Analysis Flow

flowchart TD
    %% Styling
    classDef input fill:#E8F4FD,color:#000,stroke:#1E88E5,stroke-width:2px
    classDef process fill:#FFF3E0,color:#000,stroke:#FF9800,stroke-width:2px
    classDef analysis fill:#F3E5F5,color:#000,stroke:#9C27B0,stroke-width:2px
    classDef output fill:#E8F5E8,color:#000,stroke:#4CAF50,stroke-width:2px
    classDef enhanced fill:#FFEBEE,color:#000,stroke:#F44336,stroke-width:3px
    
    %% Input Data
    TimeSeriesData[("Time Series Data<br/>Returns DataFrame")]:::input
    
    %% Data Preparation
    DataValidation["Data Validation<br/>• Check for missing values<br/>• Ensure sufficient observations<br/>• Validate datetime index"]:::process
    
    NumericSelection["Select Numeric Columns<br/>• Filter non-numeric data<br/>• Prepare for VAR modeling"]:::process
    
    %% VAR Model Setup
    LagSelection["Optimal Lag Selection<br/>• Calculate safe max lag<br/>• Use AIC criterion<br/>• Ensure stability"]:::process
    
    VARFitting["VAR Model Fitting<br/>• Fit VAR(p) model<br/>• Validate model stability<br/>• Extract coefficients"]:::analysis
    
    %% Spillover Analysis
    FEVDCalculation["FEVD Calculation<br/>• Forecast Error Variance Decomposition<br/>• Calculate spillover matrix<br/>• Generate directional spillovers"]:::analysis
    
    SpilloverMetrics["Spillover Metrics<br/>• Total Spillover Index<br/>• Directional Spillovers<br/>• Net Spillovers<br/>• Pairwise Spillovers"]:::analysis
    
    %% Enhanced Granger Causality
    GrangerEnhanced["Enhanced Granger Causality<br/>• Multi-level significance (1%, 5%)<br/>• Optimal lag detection<br/>• Comprehensive p-value analysis<br/>• Robust test statistics"]:::enhanced
    
    %% Results and Interpretations
    SpilloverResults["Spillover Results<br/>• Spillover indices<br/>• FEVD table<br/>• Network effects"]:::output
    
    GrangerResults["Multi-Level Granger Results<br/>• Highly significant (1% level)<br/>• Significant (5% level)<br/>• Optimal lags per relationship<br/>• Minimum p-values"]:::enhanced
    
    InterpretationEngine["Enhanced Interpretation Engine<br/>• Business-relevant explanations<br/>• Market context analysis<br/>• Risk assessment insights<br/>• Trading implications"]:::enhanced
    
    %% Final Output
    ComprehensiveReport["Comprehensive Analysis Report<br/>• Spillover analysis<br/>• Causality relationships<br/>• Human-readable interpretations<br/>• Actionable insights"]:::output
    
    %% Flow connections
    TimeSeriesData --> DataValidation
    DataValidation --> NumericSelection
    NumericSelection --> LagSelection
    LagSelection --> VARFitting
    VARFitting --> FEVDCalculation
    VARFitting --> GrangerEnhanced
    FEVDCalculation --> SpilloverMetrics
    SpilloverMetrics --> SpilloverResults
    GrangerEnhanced --> GrangerResults
    SpilloverResults --> InterpretationEngine
    GrangerResults --> InterpretationEngine
    InterpretationEngine --> ComprehensiveReport
Loading

Multi-Level Granger Causality Testing

The enhanced Granger causality testing provides more robust and actionable results:

flowchart LR
    %% Styling
    classDef input fill:#E3F2FD,color:#000,stroke:#2196F3,stroke-width:2px
    classDef test fill:#FFF8E1,color:#000,stroke:#FFC107,stroke-width:2px
    classDef result fill:#E8F5E8,color:#000,stroke:#4CAF50,stroke-width:2px
    classDef enhanced fill:#FFEBEE,color:#000,stroke:#F44336,stroke-width:3px
    
    subgraph "Market Pair Analysis"
        SeriesPair["Market Pair<br/>X → Y"]:::input
    end
    
    subgraph "Multi-Level Testing"
        Test1pct["1% Significance Test<br/>α = 0.01<br/>High Confidence"]:::enhanced
        Test5pct["5% Significance Test<br/>α = 0.05<br/>Standard Confidence"]:::enhanced
        OptimalLag["Optimal Lag Detection<br/>Best predictive lag<br/>Minimize p-value"]:::enhanced
    end
    
    subgraph "Enhanced Results"
        Result1pct["Highly Significant<br/>Strong predictive power<br/>Robust relationship"]:::result
        Result5pct["Significant<br/>Meaningful relationship<br/>Standard confidence"]:::result
        ResultNone["No Significance<br/>No predictive power<br/>Independent series"]:::result
    end
    
    subgraph "Business Interpretation"
        LeadingIndicator["Leading Indicator<br/>X predicts Y movements<br/>Trading opportunity"]:::enhanced
        MarketEfficiency["Market Efficiency<br/>No predictable patterns<br/>Random walk hypothesis"]:::enhanced
        RiskManagement["Risk Management<br/>Contagion effects<br/>Diversification impact"]:::enhanced
    end
    
    %% Connections
    SeriesPair --> Test1pct
    SeriesPair --> Test5pct
    SeriesPair --> OptimalLag
    
    Test1pct --> Result1pct
    Test5pct --> Result5pct
    Test1pct -.-> ResultNone
    Test5pct -.-> ResultNone
    
    Result1pct --> LeadingIndicator
    Result5pct --> LeadingIndicator
    ResultNone --> MarketEfficiency
    Result1pct --> RiskManagement
    Result5pct --> RiskManagement
Loading

About

FastAPI backend for time series analysis pipeline

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages