Skill: lean-zhouchao/economic-calendar-fetcher-zc (version 1.0.0)

--- name: economic-calendar-fetcher-zc description: Fetch upcoming economic events and data releases using FMP API. Retrieve scheduled central bank decisions, employment reports, inflation data, GDP releases, and other market-moving economic indicators for specified date ranges (default: next 7 days). Output chronological markdown reports with impact assessment. --- # Economic Calendar Fetcher ## Overview Retrieve upcoming economic events and data releases from the Financial Modeling Prep (FMP) Economic Calendar API. This skill fetches scheduled economic indicators including central bank monetary policy decisions, employment reports, inflation data (CPI/PPI), GDP releases, retail sales, manufacturing data, and other market-moving events that impact financial markets. The skill uses a Python script to query the FMP API and generates chronological markdown reports with impact assessment for each scheduled event. **Key Capabilities:** - Fetch economic events for specified date ranges (max 90 days) - Support flexible API key provision (environment variable or user input) - Filter by impact level, country, or event type - Generate structured markdown reports with impact analysis - Default to next 7 days for quick market outlook **Data Source:** - FMP Economic Calendar API: `https://financialmodelingprep.com/api/v3/economic_calendar` - Covers major economies: US, EU, UK, Japan, China, Canada, Australia - Event types: Central bank decisions, employment, inflation, GDP, trade, housing, surveys ## When to Use This Skill Use this skill when the user requests: 1. **Economic Calendar Queries:** - "What economic events are coming up this week?" - "Show me the economic calendar for the next two weeks" - "When is the next FOMC meeting?" - "What major economic data is being released next month?" 2. **Market Event Planning:** - "What should I watch for in the markets this week?" - "Are there any high-impact economic releases coming?" - "When is the next jobs report / CPI release / GDP report?" 3. **Specific Date Range Requests:** - "Get economic events from January 1 to January 31" - "What's on the economic calendar for Q1 2025?" 4. **Country-Specific Queries:** - "Show me US economic data releases next week" - "What ECB events are scheduled?" - "When is Japan releasing their inflation data?" **DO NOT use this skill for:** - Past economic events (use market-news-analyst for historical analysis) - Corporate earnings calendars (this skill excludes earnings) - Real-time market data or live quotes - Technical analysis or chart interpretation ## Workflow Follow these steps to fetch and analyze the economic calendar: ### Step 1: Obtain FMP API Key **Check for API key availability:** 1. First check if FMP_API_KEY environment variable is set 2. If not available, ask user to provide API key via chat 3. If user doesn't have API key, provide instructions: - Visit https://financialmodelingprep.com - Sign up for free account (250 requests/day limit) - Navigate to API dashboard to obtain key **Example user interaction:** ``` User: "Show me economic events for next week" Assistant: "I'll fetch the economic calendar. Do you have an FMP API key? I can use the FMP_API_KEY environment variable, or you can provide your API key now." ``` ### Step 2: Determine Date Range **Set appropriate date range based on user request:** **Default (no specific dates):** Today + 7 days **User specifies period:** Use exact dates (validate format: YYYY-MM-DD) **Maximum range:** 90 days (FMP API limitation) **Examples:** - "Next week" → Today to +7 days - "Next two weeks" → Today to +14 days - "January 2025" → 2025-01-01 to 2025-01-31 - "Q1 2025" → 2025-01-01 to 2025-03-31 **Validate date range:** - Ensure start date ≤ end date - Ensure range ≤ 90 days - Warn if querying past dates ### Step 3: Execute API Fetch Script **Run the get_economic_calendar.py script with appropriate parameters:** **Basic usage (default 7 days):** ```bash python3 /path/to/economic-calendar-fetcher/scripts/get_economic_calendar.py --api-key YOUR_KEY ``` **With specific date range:** ```bash python3 /path/to/economic-calendar-fetcher/scripts/get_economic_calendar.py \ --from 2025-01-01 \ --to 2025-01-31 \ --api-key YOUR_KEY \ --format json ``` **Using environment variable (no --api-key needed):** ```bash export FMP_API_KEY=your_key_here python3 /path/to/economic-calendar-fetcher/scripts/get_economic_calendar.py \ --from 2025-01-01 \ --to 2025-01-07 ``` **Script parameters:** - `--from`: Start date (YYYY-MM-DD) - default: today - `--to`: End date (YYYY-MM-DD) - default: today + 7 days - `--api-key`: FMP API key (optional if FMP_API_KEY env var set) - `--format`: Output format (json or text) - default: json - `--output`: Output file path (optional, default: stdout) **Handle errors:** - Invalid API key → Ask user to verify key - Rate limit exceeded (429) → Suggest waiting or upgrading FMP tier - Network errors → Retry with exponential backoff - Invalid date format → Provide correct format example ### Step 4: Parse and Filter Events **Process the JSON response from the script:** 1. **Parse event data:** Extract all events from API response 2. **Apply user filters if specified:** - Impact level: "High", "Medium", "Low" - Country: "US", "EU", "JP", "CN", etc. - Event type: FOMC, CPI, Employment, GDP, etc. - Currency: USD, EUR, JPY, etc. **Filter examples:** - "Show only high-impact events" → Filter impact == "High" - "US events only" → Filter country == "US" - "Central bank decisions" → Search event name for "Rate", "Policy", "FOMC", "ECB", "BOJ" **Event data structure:** ```json { "date": "2025-01-15 14:30:00", "country": "US", "event": "Consumer Price Index (CPI) YoY", "currency": "USD", "previous": 2.6, "estimate": 2.7, "actual": null, "change": null, "impact": "High", "changePercentage": null } ``` ### Step 5: Assess Market Impact **Evaluate the market significance of each event:** **Impact Level Classification (from FMP):** - **High Impact:** Major market-moving events - FOMC rate decisions, ECB/BOJ policy meetings - Non-Farm Payrolls (NFP), CPI, GDP - Market typically shows 0.5-2%+ intraday volatility - **Medium Impact:** Significant but less volatile - Retail Sales, Industrial Production - PMI surveys, Consumer Confidence - Housing data, Durable Goods Orders - **Low Impact:** Minor indicators - Weekly jobless claims (unless extreme) - Regional manufacturing surveys - Minor auction results **Additional Context Factors:** 1. **Current Market Sensitivity:** - High inflation environment → CPI/PPI elevated importance - Recession fears → Employment data more critical - Rate cut speculation → Central bank meetings crucial 2. **Surprise Potential:** - Compare estimate vs. previous reading - Large expected changes = higher attention - Consensus uncertainty = higher impact potential 3. **Event Clustering:** - Multiple related events same day = amplified impact - Example: CPI + Retail Sales + Fed speech = Very High impact day 4. **Forward Significance:** - Does this event influence upcoming central bank decisions? - Is this a preliminary or final reading? - Will this data be revised? ### Step 6: Generate Output Report **Create structured markdown report with the following sections:** **Report Header:** ```markdown # Economic Calendar **Period:** [Start Date] to [End Date] **Report Generated:** [Timestamp] **Total Events:** [Count] **High Impact Events:** [Count] ``` **Event Listing (Chronological):** For each event, provide: ```markdown ## [Date] - [Day of Week] ### [Event Name] ([Impact Level]) - **Country:** [Country Code] ([Currency]) - **Time:** [HH:MM UTC] - **Previous:** [Value] - **Estimate:** [Consensus Forecast] - **Impact Assessment:** [Your analysis] **Market Implications:** [2-3 sentences on why this matters, what markets watch for, typical reaction patterns] --- ``` **Example Event Entry:** ```markdown ## 2025-01-15 - Wednesday ### Consumer Price Index (CPI) YoY (High Impact) - **Country:** US (USD) - **Time:** 14:30 UTC (8:30 AM ET) - **Previous:** 2.6% - **Estimate:** 2.7% - **Impact Assessment:** Very High - Core inflation metric for Fed policy decisions **Market Implications:** CPI reading above estimate (>2.7%) likely strengthens hawkish Fed expectations, potentially pressuring equities and supporting USD. Reading at or below 2.7% could reinforce disinflation narrative and support risk assets. Options market pricing 1.2% S&P 500 move on release day. --- ``` **Summary Section:** Add analytical summary at the end: ```markdown ## Key Takeaways **Highest Impact Days:** - [Date]: [Events] - [Combined impact rationale] - [Date]: [Events] - [Combined impact rationale] **Central Bank Activity:** - [Summary of any scheduled Fed/ECB/BOJ meetings or speeches] **Major Data Releases:** - Employment: [NFP, Unemployment Rate dates] - Inflation: [CPI, PPI dates] - Growth: [GDP, Retail Sales dates] **Market Positioning Considerations:** [2-3 bullets on how traders might position around these events] **Risk Events:** [Highlight any particularly high-uncertainty or surprise-potential events] ``` **Filtering Notes:** If user requested specific filters, note at top: ```markdown **Filters Applied:** - Impact Level: High only - Country: US - Events shown: [X] of [Y] total events in date range ``` **Output Format:** - Primary: Markdown file saved to disk - Filename format: `economic_calendar_[START]_to_[END].md` - Also display summary to user in chat ## Output Format Specifications **File naming convention:** ``` economic_calendar_2025-01-01_to_2025-01-31.md economic_calendar_2025-01-15_to_2025-01-21.md (weekly) economic_calendar_high_impact_2025-01.md (with filters) ``` **Markdown structure requirements:** 1. **Chronological ordering:** Events sorted by date and time (earliest first) 2. **Impact level indicators:** Use (High Impact), (Medium Impact), (Low Impact) labels 3. **Time zone clarity:** Always specify UTC and provide ET/PT conversions for US events 4. **Data completeness:** Include all available fields (previous, estimate, actual if past) 5. **Null handling:** Display "N/A" or "No estimate" for null values 6. **Impact assessment:** Every high/medium impact event must have market implications analysis **Table format option (for dense listings):** ```markdown | Date/Time (UTC) | Event | Country | Impact | Previous | Estimate | Assessment | |-----------------|-------|---------|--------|----------|----------|------------| | 01-15 14:30 | CPI YoY | US | High | 2.6% | 2.7% | Core inflation metric | ``` **Language:** All reports in English ## Resources **Python Script:** - `scripts/get_economic_calendar.py`: Main API fetch script with CLI interface **Reference Documentation:** - `references/fmp_api_documentation.md`: Complete FMP Economic Calendar API reference - Authentication and API key management - Request parameters and date formats - Response field definitions - Rate limits and error handling - Best practices for caching and efficiency **API Details:** - Endpoint: `https://financialmodelingprep.com/api/v3/economic_calendar` - Authentication: API key required (free tier: 250 requests/day) - Max date range: 90 days per request - Response format: JSON array of event objects - Rate limits: 5 requests/second (free tier) **Event Coverage:** - Major economies: US, EU, UK, Japan, China, Canada, Australia, Switzerland - Event categories: Monetary policy, Employment, Inflation, GDP, Trade, Housing, Surveys - Update frequency: Real-time (events added/updated as scheduled) - Historical data: Available for past events with actual values **Usage Tips:** 1. Cache results to minimize API calls (events rarely change once scheduled) 2. Query 7-30 day ranges for optimal request efficiency 3. Don't query >6 months in future (sparse data, speculative dates) 4. Refresh cache daily for upcoming week to catch time changes 5. Use smaller ranges (1-7 days) for real-time event monitoring **Error Handling:** - API key errors: Clear user guidance for obtaining free key - Rate limits: Exponential backoff retry logic - Network failures: Graceful degradation with cached data if available - Invalid dates: Validation with helpful error messages

path: _meta.json
content: ownerId: kn7agf701n3afzzbq8ge0wa8k1809wm4
slug: economic-calendar-fetcher
version: 0.1.0
publishedAt: 1769870220982

path: references/fmp_api_documentation.md
content: # FMP Economic Calendar API Documentation

## Overview

The Financial Modeling Prep (FMP) Economic Calendar API provides access to upcoming and historical economic data releases, central bank decisions, and other market-moving events. This API enables traders and investors to stay informed about scheduled economic events that may impact financial markets.

## API Endpoint

```
https://financialmodelingprep.com/api/v3/economic_calendar
```

## Authentication

API access requires a valid FMP API key, which must be included as a query parameter in all requests.

**Parameter:** `apikey`
**Format:** String
**Required:** Yes

### Obtaining an API Key

1. Visit https://financialmodelingprep.com
2. Sign up for an account (free and paid tiers available)
3. Navigate to the API dashboard to view your API key
4. Free tier allows limited requests per day (~250-300 requests)
5. Paid tiers offer higher rate limits and additional features

## Request Parameters

### Required Parameters

| Parameter | Type | Description | Example |
|-----------|------|-------------|---------|
| `from` | date | Start date for calendar period | `2025-01-01` |
| `to` | date | End date for calendar period | `2025-01-31` |
| `apikey` | string | Your FMP API key | `YOUR_API_KEY` |

### Date Format

- **Format:** `YYYY-MM-DD` (ISO 8601 date format)
- **Example:** `2025-07-20`
- **Maximum Range:** 90 days between `from` and `to` dates
- **Timezone:** All dates are in UTC

### Date Range Limitations

- Minimum range: 1 day
- Maximum range: 90 days
- Past dates: API returns historical events with actual values
- Future dates: API returns scheduled events with estimates (actual values will be null)

## Response Format

The API returns a JSON array of economic event objects.

### Response Structure

```json
[
    {
        "date": "2024-03-01 03:35:00",
        "country": "JP",
        "event": "3-Month Bill Auction",
        "currency": "JPY",
        "previous": -0.112,
        "estimate": null,
        "actual": -0.096,
        "change": 0.016,
        "impact": "Low",
        "changePercentage": 14.286
    }
]
```

### Response Fields

| Field | Type | Description | Nullable |
|-------|------|-------------|----------|
| `date` | string | Event date and time in UTC (format: `YYYY-MM-DD HH:MM:SS`) | No |
| `country` | string | ISO 2-letter country code (e.g., `US`, `JP`, `GB`, `EU`) | No |
| `event` | string | Name/description of the economic event | No |
| `currency` | string | ISO 3-letter currency code (e.g., `USD`, `EUR`, `JPY`) | No |
| `previous` | number | Previous reading/value for this indicator | Yes |
| `estimate` | number | Market consensus estimate/forecast | Yes |
| `actual` | number | Actual released value (null for future events) | Yes |
| `change` | number | Absolute change from previous reading | Yes |
| `impact` | string | Market impact level: `"High"`, `"Medium"`, `"Low"` | No |
| `changePercentage` | number | Percentage change from previous reading | Yes |

### Field Details

**`date`:**
- Format: `YYYY-MM-DD HH:MM:SS` in UTC timezone
- Represents the scheduled release time for the economic data
- For future events, this is the expected release time
- Times may be adjusted if releases are delayed

**`country`:**
- ISO 3166-1 alpha-2 country codes
- Special codes:
  - `EU`: European Union (ECB-related events)
  - `G7`: G7 summit/collaborative events
  - International organizations may use special codes

**`event`:**
- Descriptive name of the economic indicator or event
- Examples:
  - `"Non-Farm Payrolls"`
  - `"Consumer Price Index (CPI)"`
  - `"Federal Funds Rate Decision"`
  - `"GDP Growth Rate QoQ"`
  - `"Unemployment Rate"`

**`currency`:**
- ISO 4217 currency codes
- Indicates which currency's economy the event affects
- May differ from country (e.g., EU events affect EUR across multiple countries)

**`previous`:**
- The last reported value for this indicator
- Used as baseline for comparing current release
- May be revised from originally reported value
- `null` if no prior data available (new indicator)

**`estimate`:**
- Market consensus forecast compiled from analyst surveys
- Typically from Bloomberg, Reuters, or other consensus services
- `null` if no consensus exists or for less-watched indicators
- Comparing `actual` to `estimate` shows "surprise" factor

**`actual`:**
- The officially released value when data is published
- `null` for future events (not yet released)
- This is the critical field that moves markets when released
- May be revised in subsequent releases (preliminary → final revisions)

**`change`:**
- Calculated as: `actual - previous` (for past events)
- `null` if either `actual` or `previous` is null
- Sign indicates direction: positive = increase, negative = decrease
- Absolute value, not percentage

**`impact`:**
- Qualitative assessment of market-moving potential
- Three levels:
  - `"High"`: Major market-moving events (NFP, FOMC, CPI)
  - `"Medium"`: Significant but less volatile (Retail Sales, PMI)
  - `"Low"`: Minor indicators, routine data releases
- Determined by FMP based on historical volatility impact

**`changePercentage`:**
- Calculated as: `((actual - previous) / previous) * 100`
- `null` if either value is null or if `previous` is zero
- Percentage representation of the change
- Useful for comparing relative magnitude across different indicators

## Example Requests

### Fetch Events for Next 7 Days

```bash
curl "https://financialmodelingprep.com/api/v3/economic_calendar?from=2025-01-01&to=2025-01-07&[REDACTED_SECRET]"
```

### Fetch High-Impact Events Only (Post-Processing)

Note: API does not have an `impact` filter parameter, so filtering must be done after retrieval.

```python
import requests

response = requests.get(
    "https://financialmodelingprep.com/api/v3/economic_calendar",
    params={
        "from": "2025-01-01",
        "to": "2025-01-31",
        "apikey": "YOUR_API_KEY"
    }
)

events = response.json()
high_impact_events = [e for e in events if e["impact"] == "High"]
```

### Fetch Events for Specific Country (Post-Processing)

```python
us_events = [e for e in events if e["country"] == "US"]
eu_events = [e for e in events if e["country"] == "EU"]
```

## Rate Limits

Rate limits depend on your FMP subscription tier:

| Tier | Requests/Day | Requests/Second |
|------|--------------|-----------------|
| Free | 250 | 5 |
| Starter | 500 | 10 |
| Professional | 1,000+ | 20+ |

If you exceed rate limits, the API returns HTTP 429 (Too Many Requests).

## Error Handling

### HTTP Status Codes

| Code | Meaning | Description |
|------|---------|-------------|
| 200 | Success | Request successful, data returned |
| 400 | Bad Request | Invalid parameters (malformed dates, missing required params) |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | API key valid but lacks permission (expired subscription) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | FMP server error (retry after delay) |

### Error Response Format

```json
{
    "Error Message": "Invalid API KEY. Please retry or visit our documentation to create one FREE https://financialmodelingprep.com/developer/docs"
}
```

### Common Errors

**Invalid API Key:**
```json
{"Error Message": "Invalid API KEY..."}
```
**Solution:** Verify API key is correct, active subscription

**Date Range Too Large:**
```json
{"Error Message": "Maximum date range is 90 days"}
```
**Solution:** Reduce date range to 90 days or less

**Rate Limit Exceeded:**
- HTTP 429 response
**Solution:** Wait before next request, upgrade subscription tier

## Best Practices

### 1. Respect Rate Limits

Implement exponential backoff for retries:
```python
import time

def fetch_with_retry(url, params, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, params=params)
        if response.status_code == 429:
            wait_time = 2 ** attempt  # Exponential backoff
            time.sleep(wait_time)
            continue
        return response
    raise Exception("Max retries exceeded")
```

### 2. Cache Results

Economic calendar data doesn't change frequently once released:
- Cache past events indefinitely (actual values don't change)
- Cache future events for 1-24 hours (estimates rarely change)
- Refresh cache after event release time passes

### 3. Efficient Date Ranges

- Query 7-30 day ranges to minimize API calls
- Don't query dates more than 3-6 months in future (sparse data)
- Use smaller ranges (1-7 days) for real-time monitoring

### 4. Handle Null Values

Many fields can be `null`, especially for future events:
```python
event_value = event.get("actual") or event.get("estimate") or event.get("previous")
if event_value is None:
    print("No value available for this event")
```

### 5. Time Zone Awareness

All API times are UTC:
```python
from datetime import datetime, timezone

utc_time = datetime.strptime(event["date"], "%Y-%m-%d %H:%M:%S")
utc_time = utc_time.replace(tzinfo=timezone.utc)

# Convert to local timezone
local_time = utc_time.astimezone()
```

## Data Accuracy and Timeliness

### Release Time Accuracy

- Most release times accurate within ±1 minute
- Delayed releases possible (technical issues, holidays)
- Times may shift due to daylight saving time changes

### Data Revisions

Economic data is often revised:
- **Preliminary:** First release (most market impact)
- **Revised:** 1-2 months later
- **Final:** 2-3 months later

The API `previous` field reflects the latest revised value, not necessarily the original preliminary release.

### Coverage

FMP Economic Calendar covers:
- **Major Economies:** US, EU, UK, Japan, China, Canada, Australia
- **Event Types:**
  - Employment data (NFP, unemployment rate)
  - Inflation (CPI, PPI, PCE)
  - Growth (GDP, retail sales, industrial production)
  - Central bank decisions (FOMC, ECB, BOJ, BOE)
  - Surveys (PMI, consumer confidence, sentiment indices)
  - Trade data (trade balance, exports/imports)
  - Housing data (starts, permits, sales)

## Comparison with Other Sources

| Feature | FMP API | Forex Factory | Investing.com |
|---------|---------|---------------|---------------|
| API Access | Yes | No (scraping only) | No (scraping only) |
| Historical Data | Yes | Limited | Yes (web only) |
| Free Tier | Yes (250/day) | N/A | N/A |
| Data Format | JSON | HTML | HTML |
| Reliability | High | Medium (changes) | Medium (changes) |

FMP is a reliable, legitimate API source compared to scraping financial calendar websites (which violates ToS and is fragile).

## Support and Documentation

- **Official Docs:** https://financialmodelingprep.com/developer/docs/economic-calendar-api
- **API Status:** https://status.financialmodelingprep.com
- **Support:** [REDACTED_SECRET]
- **Community:** Active Discord and forum for FMP users


path: scripts/get_economic_calendar.py
content: #!/usr/bin/env python3
"""
Economic Calendar Fetcher using FMP API
Retrieves economic events and data releases for specified date range
"""

import os
import sys
import json
import argparse
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import urllib.request
import urllib.error
import urllib.parse


def get_api_key() -> Optional[str]:
    """
    Get FMP API key from environment variable.

    Returns:
        API key string or None if not found
    """
    [REDACTED_SECRET]'FMP_API_KEY')
    if not [REDACTED_SECRET]"Warning: FMP_API_KEY environment variable not set", file=sys.stderr)
    return api_key


def fetch_economic_calendar(
    from_date: str,
    to_date: str,
    api_key: str
) -> List[Dict]:
    """
    Fetch economic calendar data from FMP API.

    Args:
        from_date: Start date in YYYY-MM-DD format
        to_date: End date in YYYY-MM-DD format
        api_key: FMP API key

    Returns:
        List of economic event dictionaries

    Raises:
        urllib.error.HTTPError: If API request fails
        ValueError: If response is invalid
    """
    base_url = "https://financialmodelingprep.com/api/v3/economic_calendar"

    # Build query parameters
    params = {
        'from': from_date,
        'to': to_date,
        'apikey': api_key
    }

    # Construct URL with parameters
    url = f"{base_url}?{urllib.parse.urlencode(params)}"

    try:
        # Make API request
        with urllib.request.urlopen(url) as response:
            if response.status != 200:
                raise ValueError(f"API returned status code {response.status}")

            data = json.loads(response.read().decode('utf-8'))

            if not isinstance(data, list):
                raise ValueError(f"Unexpected API response format: {type(data)}")

            return data

    except urllib.error.HTTPError as e:
        error_body = e.read().decode('utf-8') if e.fp else 'No error details'
        raise urllib.error.HTTPError(
            e.url, e.code, f"FMP API error: {e.reason}. Details: {error_body}",
            e.hdrs, e.fp
        )
    except urllib.error.URLError as e:
        raise ValueError(f"Network error: {e.reason}")


def validate_date_range(from_date: str, to_date: str) -> None:
    """
    Validate date range is within FMP API limits (max 90 days).

    Args:
        from_date: Start date in YYYY-MM-DD format
        to_date: End date in YYYY-MM-DD format

    Raises:
        ValueError: If date range is invalid or exceeds 90 days
    """
    try:
        start = datetime.strptime(from_date, '%Y-%m-%d')
        end = datetime.strptime(to_date, '%Y-%m-%d')
    except ValueError as e:
        raise ValueError(f"Invalid date format. Use YYYY-MM-DD: {e}")

    if start > end:
        raise ValueError(f"Start date {from_date} is after end date {to_date}")

    delta = (end - start).days
    if delta > 90:
        raise ValueError(f"Date range ({delta} days) exceeds maximum of 90 days")

    # Warn if querying past dates
    today = datetime.now().date()
    if end.date() < today:
        print(f"Warning: End date {to_date} is in the past", file=sys.stderr)


def format_event_output(events: List[Dict], output_format: str = 'json') -> str:
    """
    Format economic events for output.

    Args:
        events: List of event dictionaries from FMP API
        output_format: Output format ('json' or 'text')

    Returns:
        Formatted string
    """
    if output_format == 'json':
        return json.dumps(events, indent=2, ensure_ascii=False)

    elif output_format == 'text':
        lines = []
        lines.append(f"Economic Calendar Events (Total: {len(events)})")
        lines.append("=" * 80)

        for event in events:
            lines.append(f"\nDate: {event.get('date', 'N/A')}")
            lines.append(f"Country: {event.get('country', 'N/A')}")
            lines.append(f"Event: {event.get('event', 'N/A')}")
            lines.append(f"Currency: {event.get('currency', 'N/A')}")
            lines.append(f"Impact: {event.get('impact', 'N/A')}")

            previous = event.get('previous')
            estimate = event.get('estimate')
            actual = event.get('actual')

            if previous is not None:
                lines.append(f"Previous: {previous}")
            if estimate is not None:
                lines.append(f"Estimate: {estimate}")
            if actual is not None:
                lines.append(f"Actual: {actual}")

            change = event.get('change')
            change_pct = event.get('changePercentage')
            if change is not None:
                lines.append(f"Change: {change}")
            if change_pct is not None:
                lines.append(f"Change %: {change_pct}%")

            lines.append("-" * 80)

        return "\n".join(lines)

    else:
        raise ValueError(f"Unknown output format: {output_format}")


def main():
    """Main execution function."""
    parser = argparse.ArgumentParser(
        description='Fetch economic calendar events from FMP API',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Fetch events for next 7 days (default)
  python get_economic_calendar.py

  # Fetch events for specific date range
  python get_economic_calendar.py --from 2025-01-01 --to 2025-01-31

  # Provide API key via argument (overrides environment variable)
  python get_economic_calendar.py --api-key YOUR_KEY_HERE

  # Output as formatted text instead of JSON
  python get_economic_calendar.py --format text

  # Save output to file
  python get_economic_calendar.py --output calendar.json
        """
    )

    # Date range arguments
    today = datetime.now().date()
    default_from = today.strftime('%Y-%m-%d')
    default_to = (today + timedelta(days=7)).strftime('%Y-%m-%d')

    parser.add_argument(
        '--from', dest='from_date',
        default=default_from,
        help=f'Start date in YYYY-MM-DD format (default: {default_from})'
    )
    parser.add_argument(
        '--to', dest='to_date',
        default=default_to,
        help=f'End date in YYYY-MM-DD format (default: {default_to})'
    )

    # API key argument
    parser.add_argument(
        '--api-key', dest='api_key',
        help='FMP API key (overrides FMP_API_KEY environment variable)'
    )

    # Output format
    parser.add_argument(
        '--format', choices=['json', 'text'],
        default='json',
        help='Output format (default: json)'
    )

    # Output file
    parser.add_argument(
        '--output', '-o',
        help='Output file path (default: stdout)'
    )

    # Parse arguments
    args = parser.parse_args()

    # Get API key
    [REDACTED_SECRET] or get_api_key()
    if not [REDACTED_SECRET]"Error: FMP API key is required. Set FMP_API_KEY environment variable or use --api-key",
              file=sys.stderr)
        sys.exit(1)

    try:
        # Validate date range
        validate_date_range(args.from_date, args.to_date)

        # Fetch events
        print(f"Fetching economic calendar from {args.from_date} to {args.to_date}...",
              file=sys.stderr)
        events = fetch_economic_calendar(args.from_date, args.to_date, api_key)

        print(f"Retrieved {len(events)} events", file=sys.stderr)

        # Format output
        output = format_event_output(events, args.format)

        # Write output
        if args.output:
            with open(args.output, 'w', encoding='utf-8') as f:
                f.write(output)
            print(f"Output written to {args.output}", file=sys.stderr)
        else:
            print(output)

        sys.exit(0)

    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == '__main__':
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)