Skill: aisadocs/marketpulse (version 1.0.2)

--- name: marketpulse description: 'Query real-time and historical financial data for equities—prices, news, financial statements, metrics, analyst estimates, insider and institutional activity, SEC filings, earnings press releases, segmented revenues, stock screening, and macro interest rates. Use when: the user needs market data, stock analysis, watchlists, or portfolio workflows.' author: AIsa version: 1.0.2 license: MIT user-invocable: true primaryEnv: AISA_API_KEY requires: bins: - python3 env: - AISA_API_KEY metadata: aisa: emoji: 📊 requires: bins: - python3 env: - AISA_API_KEY primaryEnv: AISA_API_KEY compatibility: - openclaw - claude-code - hermes openclaw: emoji: 📊 requires: bins: - python3 env: - AISA_API_KEY primaryEnv: AISA_API_KEY --- # MarketPulse 📊 **Complete equity market data for autonomous agents. Powered by AIsa.** One API key. Stocks, financials, filings, and macro data. Everything you need. ## Compatibility Works with any [agentskills.io](https://agentskills.io)-compatible harness, including: - **Claude Code** and **Claude** (Anthropic) - **OpenAI Codex** - **Cursor** - **Gemini CLI** (Google) - **OpenCode**, **Goose**, **OpenClaw**, **Hermes** - and any other harness that implements the [Agent Skills specification](https://agentskills.io/specification) Requires Python 3, a POSIX shell, and `AISA_API_KEY` (get one at [aisa.one](https://aisa.one)). ## 🔥 What Can You Do? ### Investment Research ``` "Full analysis: NVDA price trends, insider trades, analyst estimates, SEC filings" ``` ### Earnings Analysis ``` "Get Tesla earnings press releases, analyst estimates, and price reaction" ``` ### Market Screening ``` "Find stocks with P/E < 15 and revenue growth > 20%" ``` ### Whale Watching ``` "Track insider trades at Apple and correlate with price movements" ``` ### Segment Deep-Dive ``` "Break down Apple's revenue by product segment and geography" ``` ## Quick Start ```bash export AISA_API_KEY="your-key" ``` --- ## 🏦 Traditional Finance ### Stock Prices ```bash # Historical price data (daily) curl "https://api.aisa.one/apis/v1/financial/prices?ticker=AAPL&interval=day&interval_multiplier=1&start_date=2025-01-01&end_date=2025-12-31" \ -H "Authorization: Bearer $AISA_API_KEY" # Weekly price data curl "https://api.aisa.one/apis/v1/financial/prices?ticker=AAPL&interval=week&interval_multiplier=1&start_date=2025-01-01&end_date=2025-12-31" \ -H "Authorization: Bearer $AISA_API_KEY" # Minute-level data (intraday) curl "https://api.aisa.one/apis/v1/financial/prices?ticker=AAPL&interval=minute&interval_multiplier=5&start_date=2025-01-15&end_date=2025-01-15" \ -H "Authorization: Bearer $AISA_API_KEY" ``` **Parameters:** - `ticker`: Stock symbol (required) - `interval`: `second`, `minute`, `day`, `week`, `month`, `year` (required) - `interval_multiplier`: Multiplier for interval, e.g., 5 for 5-minute bars (required) - `start_date`: Start date YYYY-MM-DD (required) - `end_date`: End date YYYY-MM-DD (required) ### Company News ```bash # Get news by ticker curl "https://api.aisa.one/apis/v1/financial/news?ticker=AAPL&limit=10" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Financial Statements ```bash # All financial statements (requires period) curl "https://api.aisa.one/apis/v1/financial/financials?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" # Income statements curl "https://api.aisa.one/apis/v1/financial/financials/income-statements?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" # Balance sheets curl "https://api.aisa.one/apis/v1/financial/financials/balance-sheets?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" # Cash flow statements curl "https://api.aisa.one/apis/v1/financial/financials/cash-flow-statements?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" ``` **Parameters:** - `ticker`: Stock symbol (required) - `period`: `annual`, `quarterly`, or `ttm` (required) ### Segmented Revenues ```bash # Break down revenue by business segment and geography curl "https://api.aisa.one/apis/v1/financial/financials/segmented-revenues?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" ``` **Parameters:** - `ticker`: Stock symbol (required) - `period`: `annual` or `quarterly` (required) ### Financial Metrics ```bash # Real-time financial metrics snapshot curl "https://api.aisa.one/apis/v1/financial/financial-metrics/snapshot?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" # Historical financial metrics (period required) curl "https://api.aisa.one/apis/v1/financial/financial-metrics?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Analyst Estimates ```bash # Earnings per share estimates curl "https://api.aisa.one/apis/v1/financial/analyst-estimates?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Earnings Press Releases ```bash # Get earnings press releases curl "https://api.aisa.one/apis/v1/financial/earnings/press-releases?ticker=NVDA" \ -H "Authorization: Bearer $AISA_API_KEY" ``` **Note:** This endpoint has narrower ticker coverage than other financial endpoints. Passing an unsupported ticker returns `{"error":"Invalid ticker"}`. See [earnings-press-releases-tickers.md](./earnings-press-releases-tickers.md) for the full list of supported tickers (~2,776 as of 2026-04-14). ### Insider Trading ```bash # Get insider trades curl "https://api.aisa.one/apis/v1/financial/insider-trades?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Institutional Ownership ```bash # Get institutional ownership (by ticker OR investor) curl "https://api.aisa.one/apis/v1/financial/institutional-ownership?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### SEC Filings ```bash # Get SEC filings curl "https://api.aisa.one/apis/v1/financial/filings?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" # Get SEC filing items (requires filing type and year) curl "https://api.aisa.one/apis/v1/financial/filings/items?ticker=AAPL&filing_type=10-K&year=2024" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Company Facts ```bash # Get company facts (by ticker or CIK) curl "https://api.aisa.one/apis/v1/financial/company/facts?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Stock Screener ```bash # Screen for stocks matching criteria curl -X POST "https://api.aisa.one/apis/v1/financial/financials/search/screener" \ -H "Authorization: Bearer $AISA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"filters":{"pe_ratio":{"max":15},"revenue_growth":{"min":0.2}}}' ``` ### Search Line Items ```bash # Search specific financial line items across tickers curl -X POST "https://api.aisa.one/apis/v1/financial/financials/search/line-items" \ -H "Authorization: Bearer $AISA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tickers":["AAPL","MSFT"],"line_items":["revenue","net_income"],"period":"annual"}' ``` ### Interest Rates (Macro) ```bash # Current interest rates curl "https://api.aisa.one/apis/v1/financial/macro/interest-rates/snapshot" \ -H "Authorization: Bearer $AISA_API_KEY" # Historical interest rates curl "https://api.aisa.one/apis/v1/financial/macro/interest-rates?bank=fed" \ -H "Authorization: Bearer $AISA_API_KEY" ``` --- ## Python Client ```bash # ==================== Stock Data ==================== # Note: start_date and end_date are REQUIRED for prices python3 scripts/market_client.py stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31 python3 scripts/market_client.py stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31 --interval week python3 scripts/market_client.py stock news --ticker AAPL --count 10 # ==================== Financial Statements ==================== python3 scripts/market_client.py stock statements --ticker AAPL --type all --period annual python3 scripts/market_client.py stock statements --ticker AAPL --type income --period quarterly python3 scripts/market_client.py stock statements --ticker AAPL --type balance --period annual python3 scripts/market_client.py stock statements --ticker AAPL --type cash --period ttm # ==================== Segmented Revenues ==================== python3 scripts/market_client.py stock segments --ticker AAPL --period annual # ==================== Metrics & Analysis ==================== python3 scripts/market_client.py stock metrics --ticker AAPL python3 scripts/market_client.py stock metrics --ticker AAPL --historical --period annual python3 scripts/market_client.py stock analyst --ticker AAPL python3 scripts/market_client.py stock earnings --ticker AAPL # ==================== Insider & Institutional ==================== python3 scripts/market_client.py stock insider --ticker AAPL python3 scripts/market_client.py stock ownership --ticker AAPL # ==================== SEC Filings ==================== python3 scripts/market_client.py stock filings --ticker AAPL python3 scripts/market_client.py stock filings --ticker AAPL --items --filing-type 10-K --year 2024 # ==================== Stock Screener / Line Items ==================== python3 scripts/market_client.py stock screen --pe-max 15 --growth-min 0.2 python3 scripts/market_client.py stock line-items --tickers AAPL,MSFT --items revenue,net_income --period annual # ==================== Interest Rates ==================== python3 scripts/market_client.py stock rates python3 scripts/market_client.py stock rates --historical --bank fed ``` --- ## API Endpoints Reference | Endpoint | Method | Description | |----------|--------|-------------| | `/financial/prices` | GET | Historical stock prices (requires interval params) | | `/financial/news` | GET | Company news by ticker | | `/financial/financials` | GET | All financial statements (requires `period`) | | [REDACTED_SECRET] | GET | Income statements (requires `period`) | | [REDACTED_SECRET] | GET | Balance sheets (requires `period`) | | [REDACTED_SECRET] | GET | Cash flow statements (requires `period`) | | [REDACTED_SECRET] | GET | Revenue by segment/geography (requires `period`) | | [REDACTED_SECRET] | GET | Real-time financial metrics | | `/financial/financial-metrics` | GET | Historical metrics (requires `period`) | | `/financial/analyst-estimates` | GET | EPS estimates | | [REDACTED_SECRET] | GET | Earnings press releases (see [supported tickers](./earnings-press-releases-tickers.md)) | | `/financial/insider-trades` | GET | Insider trades | | [REDACTED_SECRET] | GET | Institutional ownership | | `/financial/filings` | GET | SEC filings | | `/financial/filings/items` | GET | SEC filing items (requires `filing_type`, `year`) | | `/financial/company/facts` | GET | Company facts | | [REDACTED_SECRET] | POST | Stock screener | | [REDACTED_SECRET] | POST | Search specific line items across tickers | | [REDACTED_SECRET] | GET | Current interest rates | | `/financial/macro/interest-rates` | GET | Historical rates | --- ## Pricing | API | Cost | |-----|------| | Stock prices | ~$0.001 | | Company news | ~$0.001 | | Financial statements | ~$0.002 | | Segmented revenues | ~$0.002 | | Analyst estimates | ~$0.002 | | Earnings press releases | ~$0.001 | | SEC filings | ~$0.001 | | Line items / screener | ~$0.002 | | Interest rates | ~$0.0005 | --- ## Get Started 1. Sign up at [aisa.one](https://aisa.one) 2. Get your API key 3. Add credits (pay-as-you-go) 4. Set environment variable: `export AISA_API_KEY="your-key"` ## Full API Reference See [API Reference](https://aisa.one/docs/api-reference/) for complete endpoint documentation.

path: README.md
content: # Marketpulse

Release-ready ClawHub skill package generated from `targetSkills/marketpulse`.

- Skill name: `marketpulse`
- Entry point: `SKILL.md`
- Runtime assets: `scripts/`, `references/`, `assets/` when present

## Notes

- Query real-time and historical financial data for equities—prices, news, financial statements, metrics, analyst estimates, insider and institutional activity, SEC filings, earnings press releases, segmented revenues, stock screening, and macro interest rates. Use when: the user needs market data, stock analysis, watchlists, or portfolio workflows.
- This README is release-specific and replaces source READMEs that were written for other runtimes.
- If the underlying instructions mention OpenClaw, treat that as source-context or compatibility guidance unless the skill is specifically about OpenClaw setup.

## Quick Start

1. Open `SKILL.md` to review invocation guidance and runtime requirements.
2. Set any required environment variables before running bundled scripts.
3. Use repo-relative paths like `python3 scripts/...` when following command examples.


path: scripts/market_client.py
content: #!/usr/bin/env python3
"""
AIsa Market - AIsa API Client
Complete equity market data for autonomous agents.

Usage:
    python market_client.py stock prices --ticker <ticker> --start <date> --end <date> [--interval day|week|month] [--multiplier 1]
    python market_client.py stock news --ticker <ticker> [--count <n>]
    python market_client.py stock statements --ticker <ticker> --type <all|income|balance|cash> --period <annual|quarterly|ttm>
    python market_client.py stock segments --ticker <ticker> --period <annual|quarterly>
    python market_client.py stock metrics --ticker <ticker> [--historical --period <annual|quarterly|ttm>]
    python market_client.py stock analyst --ticker <ticker> [--period <annual|quarterly>]
    python market_client.py stock earnings --ticker <ticker>
    python market_client.py stock insider --ticker <ticker>
    python market_client.py stock ownership --ticker <ticker>
    python market_client.py stock filings --ticker <ticker> [--items --filing-type 10-K --year 2024]
    python market_client.py stock facts --ticker <ticker>
    python market_client.py stock rates [--bank <bank>] [--historical]
    python market_client.py stock screen --pe-max <n> --growth-min <n>
    python market_client.py stock line-items --tickers <AAPL,MSFT> --items <revenue,net_income> --period <annual|quarterly|ttm>
"""

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


class MarketClient:
    """AIsa Market - Unified Market Data API Client."""

    BASE_URL = "https://api.aisa.one/apis/v1"

    def __init__(self, [REDACTED_SECRET] = None):
        """Initialize the client with an API key."""
        self.[REDACTED_SECRET] or os.environ.get("AISA_API_KEY")
        if not self.api_key:
            raise ValueError(
                "AISA_API_KEY is required. Set it via environment variable or pass to constructor."
            )

    def _request(
        self,
        method: str,
        endpoint: str,
        params: Optional[Dict[str, Any]] = None,
        data: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """Make an HTTP request to the AIsa API."""
        url = f"{self.BASE_URL}{endpoint}"

        if params:
            query_string = urllib.parse.urlencode(
                {k: v for k, v in params.items() if v is not None}
            )
            url = f"{url}?{query_string}"

        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
            "User-Agent": "AIsa-Market/1.0",
        }

        request_data = None
        if data:
            request_data = json.dumps(data).encode("utf-8")

        if method == "POST" and request_data is None:
            request_data = b"{}"

        req = urllib.request.Request(url, data=request_data, headers=headers, method=method)

        try:
            with urllib.request.urlopen(req, timeout=60) as response:
                return json.loads(response.read().decode("utf-8"))
        except urllib.error.HTTPError as e:
            error_body = e.read().decode("utf-8")
            try:
                return json.loads(error_body)
            except json.JSONDecodeError:
                return {"success": False, "error": {"code": str(e.code), "message": error_body}}
        except urllib.error.URLError as e:
            return {"success": False, "error": {"code": "NETWORK_ERROR", "message": str(e.reason)}}

    # ==================== Stock APIs ====================

    def stock_prices(
        self,
        ticker: str,
        start_date: str,
        end_date: str,
        interval: str = "day",
        interval_multiplier: int = 1,
    ) -> Dict[str, Any]:
        """Get historical stock prices."""
        return self._request("GET", "/financial/prices", params={
            "ticker": ticker,
            "start_date": start_date,
            "end_date": end_date,
            "interval": interval,
            "interval_multiplier": interval_multiplier,
        })

    def company_news(self, ticker: str, limit: int = 10) -> Dict[str, Any]:
        """Get company news by ticker."""
        return self._request("GET", "/financial/news", params={
            "ticker": ticker,
            "limit": limit,
        })

    def statements_all(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get all financial statements."""
        return self._request("GET", "/financial/financials", params={
            "ticker": ticker,
            "period": period,
        })

    def statements_income(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get income statements."""
        return self._request("GET", "/financial/financials/income-statements", params={
            "ticker": ticker,
            "period": period,
        })

    def statements_balance(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get balance sheets."""
        return self._request("GET", "/financial/financials/balance-sheets", params={
            "ticker": ticker,
            "period": period,
        })

    def statements_cash(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get cash flow statements."""
        return self._request("GET", "/financial/financials/cash-flow-statements", params={
            "ticker": ticker,
            "period": period,
        })

    def segmented_revenues(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get segmented revenues by business segment and geography."""
        return self._request("GET", "/financial/financials/segmented-revenues", params={
            "ticker": ticker,
            "period": period,
        })

    def metrics_snapshot(self, ticker: str) -> Dict[str, Any]:
        """Get real-time financial metrics snapshot."""
        return self._request("GET", "/financial/financial-metrics/snapshot", params={"ticker": ticker})

    def metrics_historical(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get historical financial metrics."""
        return self._request("GET", "/financial/financial-metrics", params={
            "ticker": ticker,
            "period": period,
        })

    def analyst_eps(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get earnings per share estimates."""
        return self._request("GET", "/financial/analyst-estimates", params={
            "ticker": ticker,
            "period": period,
        })

    def earnings_press_releases(self, ticker: str) -> Dict[str, Any]:
        """Get earnings press releases for a ticker."""
        return self._request("GET", "/financial/earnings/press-releases", params={"ticker": ticker})

    def insider_trades(self, ticker: str, limit: int = 10) -> Dict[str, Any]:
        """Get insider trades."""
        return self._request("GET", "/financial/insider-trades", params={
            "ticker": ticker,
            "limit": limit,
        })

    def institutional_ownership(self, ticker: str) -> Dict[str, Any]:
        """Get institutional ownership."""
        return self._request("GET", "/financial/institutional-ownership", params={"ticker": ticker})

    def sec_filings(self, ticker: str, filing_type: Optional[str] = None) -> Dict[str, Any]:
        """Get SEC filings."""
        params: Dict[str, Any] = {"ticker": ticker}
        if filing_type:
            params["filing_type"] = filing_type
        return self._request("GET", "/financial/filings", params=params)

    def sec_filing_items(self, ticker: str, filing_type: str, year: int) -> Dict[str, Any]:
        """Get SEC filing items (10-K or 10-Q)."""
        return self._request("GET", "/financial/filings/items", params={
            "ticker": ticker,
            "filing_type": filing_type,
            "year": year,
        })

    def company_facts(self, ticker: str) -> Dict[str, Any]:
        """Get company facts."""
        return self._request("GET", "/financial/company/facts", params={"ticker": ticker})

    def rates_snapshot(self) -> Dict[str, Any]:
        """Get current interest rates snapshot."""
        return self._request("GET", "/financial/macro/interest-rates/snapshot")

    def rates_historical(self, bank: str = "fed") -> Dict[str, Any]:
        """Get historical interest rates."""
        return self._request("GET", "/financial/macro/interest-rates", params={"bank": bank})

    def screen_stocks(self, filters: Dict[str, Any]) -> Dict[str, Any]:
        """Screen for stocks matching criteria."""
        return self._request(
            "POST",
            "/financial/financials/search/screener",
            data={"filters": filters},
        )

    def search_line_items(
        self,
        tickers: List[str],
        line_items: List[str],
        period: str = "annual",
    ) -> Dict[str, Any]:
        """Search specific financial line items across tickers."""
        return self._request(
            "POST",
            "/financial/financials/search/line-items",
            data={
                "tickers": tickers,
                "line_items": line_items,
                "period": period,
            },
        )


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        description="AIsa Market - Complete equity market data",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
    %(prog)s stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31
    %(prog)s stock statements --ticker AAPL --type income --period annual
    %(prog)s stock segments --ticker AAPL --period annual
    %(prog)s stock earnings --ticker AAPL
    %(prog)s stock line-items --tickers AAPL,MSFT --items revenue,net_income --period annual
        """,
    )

    subparsers = parser.add_subparsers(dest="asset_type", help="Asset type")

    # ==================== Stock Commands ====================
    stock_parser = subparsers.add_parser("stock", help="Stock/Finance commands")
    stock_sub = stock_parser.add_subparsers(dest="command", help="Command")

    # prices
    prices = stock_sub.add_parser("prices", help="Get stock prices")
    prices.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    prices.add_argument("--start", "-s", required=True, help="Start date (YYYY-MM-DD)")
    prices.add_argument("--end", "-e", required=True, help="End date (YYYY-MM-DD)")
    prices.add_argument(
        "--interval", "-i", default="day",
        choices=["second", "minute", "day", "week", "month", "year"],
        help="Time interval (default: day)",
    )
    prices.add_argument("--multiplier", "-m", type=int, default=1,
                        help="Interval multiplier (default: 1)")

    # news
    news = stock_sub.add_parser("news", help="Get company news")
    news.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    news.add_argument("--count", "-c", type=int, default=10, help="Number of articles")

    # statements
    statements = stock_sub.add_parser("statements", help="Get financial statements")
    statements.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    statements.add_argument("--type", required=True,
                            choices=["all", "income", "balance", "cash"],
                            help="Statement type")
    statements.add_argument("--period", "-p", default="annual",
                            choices=["annual", "quarterly", "ttm"],
                            help="Reporting period (default: annual)")

    # segments
    segments = stock_sub.add_parser("segments", help="Get segmented revenues")
    segments.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    segments.add_argument("--period", "-p", default="annual",
                          choices=["annual", "quarterly"],
                          help="Reporting period (default: annual)")

    # metrics
    metrics = stock_sub.add_parser("metrics", help="Get financial metrics")
    metrics.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    metrics.add_argument("--historical", action="store_true", help="Get historical data")
    metrics.add_argument("--period", "-p", default="annual",
                         choices=["annual", "quarterly", "ttm"],
                         help="Period for historical metrics (default: annual)")

    # analyst
    analyst = stock_sub.add_parser("analyst", help="Get analyst estimates")
    analyst.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    analyst.add_argument("--period", "-p", choices=["annual", "quarterly"], default="annual")

    # earnings
    earnings = stock_sub.add_parser("earnings", help="Get earnings press releases")
    earnings.add_argument("--ticker", "-t", required=True, help="Stock ticker")

    # insider
    insider = stock_sub.add_parser("insider", help="Get insider trades")
    insider.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    insider.add_argument("--limit", "-l", type=int, default=10, help="Max trades to return")

    # ownership
    ownership = stock_sub.add_parser("ownership", help="Get institutional ownership")
    ownership.add_argument("--ticker", "-t", required=True, help="Stock ticker")

    # filings
    filings = stock_sub.add_parser("filings", help="Get SEC filings")
    filings.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    filings.add_argument("--filing-type", help="Filing type (10-K, 10-Q, 8-K, 4, 144)")
    filings.add_argument("--items", action="store_true",
                         help="Fetch filing items instead of filings list (requires --filing-type and --year)")
    filings.add_argument("--year", type=int, help="Filing year (required with --items)")

    # facts
    facts = stock_sub.add_parser("facts", help="Get company facts")
    facts.add_argument("--ticker", "-t", required=True, help="Stock ticker")

    # rates
    rates = stock_sub.add_parser("rates", help="Get interest rates")
    rates.add_argument("--bank", "-b", default="fed", help="Central bank (e.g., fed)")
    rates.add_argument("--historical", action="store_true", help="Get historical data")

    # screen
    screen = stock_sub.add_parser("screen", help="Stock screener")
    screen.add_argument("--pe-max", type=float, help="Max P/E ratio")
    screen.add_argument("--pe-min", type=float, help="Min P/E ratio")
    screen.add_argument("--growth-min", type=float, help="Min revenue growth")
    screen.add_argument("--growth-max", type=float, help="Max revenue growth")

    # line-items
    line_items = stock_sub.add_parser("line-items", help="Search specific line items across tickers")
    line_items.add_argument("--tickers", required=True,
                            help="Comma-separated tickers (e.g., AAPL,MSFT)")
    line_items.add_argument("--items", required=True,
                            help="Comma-separated line items (e.g., revenue,net_income)")
    line_items.add_argument("--period", "-p", default="annual",
                            choices=["annual", "quarterly", "ttm"],
                            help="Period (default: annual)")

    args = parser.parse_args()

    if not args.asset_type:
        parser.print_help()
        sys.exit(1)

    if not args.command:
        stock_parser.print_help()
        sys.exit(1)

    try:
        client = MarketClient()
    except ValueError as e:
        print(json.dumps({"success": False, "error": {"code": "AUTH_ERROR", "message": str(e)}}))
        sys.exit(1)

    result = None

    if args.asset_type == "stock":
        if args.command == "prices":
            result = client.stock_prices(
                args.ticker, args.start, args.end, args.interval, args.multiplier
            )
        elif args.command == "news":
            result = client.company_news(args.ticker, args.count)
        elif args.command == "statements":
            if args.type == "all":
                result = client.statements_all(args.ticker, args.period)
            elif args.type == "income":
                result = client.statements_income(args.ticker, args.period)
            elif args.type == "balance":
                result = client.statements_balance(args.ticker, args.period)
            elif args.type == "cash":
                result = client.statements_cash(args.ticker, args.period)
        elif args.command == "segments":
            result = client.segmented_revenues(args.ticker, args.period)
        elif args.command == "metrics":
            if args.historical:
                result = client.metrics_historical(args.ticker, args.period)
            else:
                result = client.metrics_snapshot(args.ticker)
        elif args.command == "analyst":
            result = client.analyst_eps(args.ticker, args.period)
        elif args.command == "earnings":
            result = client.earnings_press_releases(args.ticker)
        elif args.command == "insider":
            result = client.insider_trades(args.ticker, args.limit)
        elif args.command == "ownership":
            result = client.institutional_ownership(args.ticker)
        elif args.command == "filings":
            if args.items:
                if not args.filing_type or not args.year:
                    print(json.dumps({
                        "success": False,
                        "error": {"code": "BAD_ARGS",
                                  "message": "--items requires --filing-type and --year"},
                    }))
                    sys.exit(1)
                result = client.sec_filing_items(args.ticker, args.filing_type, args.year)
            else:
                result = client.sec_filings(args.ticker, args.filing_type)
        elif args.command == "facts":
            result = client.company_facts(args.ticker)
        elif args.command == "rates":
            if args.historical:
                result = client.rates_historical(args.bank)
            else:
                result = client.rates_snapshot()
        elif args.command == "screen":
            filters: Dict[str, Any] = {}
            if args.pe_max or args.pe_min:
                filters["pe_ratio"] = {}
                if args.pe_max:
                    filters["pe_ratio"]["max"] = args.pe_max
                if args.pe_min:
                    filters["pe_ratio"]["min"] = args.pe_min
            if args.growth_max or args.growth_min:
                filters["revenue_growth"] = {}
                if args.growth_max:
                    filters["revenue_growth"]["max"] = args.growth_max
                if args.growth_min:
                    filters["revenue_growth"]["min"] = args.growth_min
            result = client.screen_stocks(filters)
        elif args.command == "line-items":
            tickers = [t.strip() for t in args.tickers.split(",") if t.strip()]
            items = [i.strip() for i in args.items.split(",") if i.strip()]
            result = client.search_line_items(tickers, items, args.period)

    if result:
        output = json.dumps(result, indent=2, ensure_ascii=False)
        try:
            print(output)
        except UnicodeEncodeError:
            print(json.dumps(result, indent=2, ensure_ascii=True))
        sys.exit(0 if result.get("success", True) else 1)


if __name__ == "__main__":
    main()


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