Skill: 0xjordansg-yolo/openclaw-aisa-finance-stock-equity-crypto-market-price-data-yahoo-finance-coinhacko (version 1.0.0)

--- name: MarketPulse description: "Query real-time and historical financial data across equities and crypto—prices, market moves, metrics, and trends for analysis, alerts, and reporting." homepage: https://openclaw.ai metadata: {"openclaw":{"emoji":"📊","requires":{"bins":["curl","python3"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY"}} --- # OpenClaw Market 📊 **Complete market data for autonomous agents. Powered by AIsa.** One API key. Stocks + Crypto + Financials. Everything you need. ## 🔥 What Can You Do? ### Cross-Asset Portfolio ``` "Get BTC, ETH prices alongside AAPL, NVDA stock data for my portfolio" ``` ### Investment Research ``` "Full analysis: NVDA price trends, insider trades, analyst estimates, SEC filings" ``` ### Crypto Tracking ``` "Real-time prices for BTC, ETH, SOL with 30-day historical charts" ``` ### Earnings Analysis ``` "Get Tesla earnings reports, 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" ``` ## 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 curl "https://api.aisa.one/apis/v1/financial/financial_statements/all?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" # Income statements curl "https://api.aisa.one/apis/v1/financial/financial_statements/income?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" # Balance sheets curl "https://api.aisa.one/apis/v1/financial/financial_statements/balance?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" # Cash flow statements curl "https://api.aisa.one/apis/v1/financial/financial_statements/cash?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### 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 curl "https://api.aisa.one/apis/v1/financial/financial-metrics?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Analyst Estimates ```bash # Earnings per share estimates curl "https://api.aisa.one/apis/v1/financial/analyst/eps?ticker=AAPL&period=annual" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### 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 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/sec/filings?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" # Get SEC filing items curl "https://api.aisa.one/apis/v1/financial/sec/items?ticker=AAPL" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Company Facts ```bash # Get company facts by 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/search/stock" \ -H "Authorization: Bearer $AISA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"filters":{"pe_ratio":{"max":15},"revenue_growth":{"min":0.2}}}' ``` ### Interest Rates ```bash # Current interest rates curl "https://api.aisa.one/apis/v1/financial/interest_rates/snapshot" \ -H "Authorization: Bearer $AISA_API_KEY" # Historical interest rates curl "https://api.aisa.one/apis/v1/financial/interest_rates/historical?bank=fed" \ -H "Authorization: Bearer $AISA_API_KEY" ``` --- ## ₿ Cryptocurrency ### Real-Time Price Snapshot ```bash # Get current BTC price (use ticker format: SYMBOL-USD) curl "https://api.aisa.one/apis/v1/financial/crypto/prices/snapshot?ticker=BTC-USD" \ -H "Authorization: Bearer $AISA_API_KEY" # Get current ETH price curl "https://api.aisa.one/apis/v1/financial/crypto/prices/snapshot?ticker=ETH-USD" \ -H "Authorization: Bearer $AISA_API_KEY" # Get current SOL price curl "https://api.aisa.one/apis/v1/financial/crypto/prices/snapshot?ticker=SOL-USD" \ -H "Authorization: Bearer $AISA_API_KEY" # Get TRUMP token price curl "https://api.aisa.one/apis/v1/financial/crypto/prices/snapshot?ticker=TRUMP-USD" \ -H "Authorization: Bearer $AISA_API_KEY" ``` **Note:** Crypto tickers use format `SYMBOL-USD` (e.g., `BTC-USD`, `ETH-USD`). ### Historical Price Data ```bash # Get BTC historical prices (daily) curl "https://api.aisa.one/apis/v1/financial/crypto/prices?ticker=BTC-USD&interval=day&interval_multiplier=1&start_date=2025-01-01&end_date=2025-01-31" \ -H "Authorization: Bearer $AISA_API_KEY" # Get ETH hourly data curl "https://api.aisa.one/apis/v1/financial/crypto/prices?ticker=ETH-USD&interval=minute&interval_multiplier=60&start_date=2025-01-15&end_date=2025-01-16" \ -H "Authorization: Bearer $AISA_API_KEY" ``` ### Supported Cryptocurrencies | Ticker | Name | |--------|------| | BTC-USD | Bitcoin | | ETH-USD | Ethereum | | SOL-USD | Solana | | BNB-USD | Binance Coin | | XRP-USD | Ripple | | DOGE-USD | Dogecoin | | ADA-USD | Cardano | | AVAX-USD | Avalanche | | DOT-USD | Polkadot | | MATIC-USD | Polygon | | LINK-USD | Chainlink | | UNI-USD | Uniswap | | ATOM-USD | Cosmos | | LTC-USD | Litecoin | | TRUMP-USD | Trump Token | | ... | And many more | --- ## Python Client ```bash # ==================== Stock Data ==================== # Note: start_date and end_date are REQUIRED for prices python3 {baseDir}/scripts/market_client.py stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31 python3 {baseDir}/scripts/market_client.py stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31 --interval week python3 {baseDir}/scripts/market_client.py stock news --ticker AAPL --count 10 # ==================== Financial Statements ==================== python3 {baseDir}/scripts/market_client.py stock statements --ticker AAPL --type all python3 {baseDir}/scripts/market_client.py stock statements --ticker AAPL --type income python3 {baseDir}/scripts/market_client.py stock statements --ticker AAPL --type balance python3 {baseDir}/scripts/market_client.py stock statements --ticker AAPL --type cash # ==================== Metrics & Analysis ==================== python3 {baseDir}/scripts/market_client.py stock metrics --ticker AAPL python3 {baseDir}/scripts/market_client.py stock analyst --ticker AAPL # ==================== Insider & Institutional ==================== python3 {baseDir}/scripts/market_client.py stock insider --ticker AAPL python3 {baseDir}/scripts/market_client.py stock ownership --ticker AAPL # ==================== SEC Filings ==================== python3 {baseDir}/scripts/market_client.py stock filings --ticker AAPL # ==================== Stock Screener ==================== python3 {baseDir}/scripts/market_client.py stock screen --pe-max 15 --growth-min 0.2 # ==================== Interest Rates ==================== python3 {baseDir}/scripts/market_client.py stock rates python3 {baseDir}/scripts/market_client.py stock rates --historical # ==================== Crypto Data ==================== # Note: Use ticker format SYMBOL-USD (or just SYMBOL, auto-converted) python3 {baseDir}/scripts/market_client.py crypto snapshot --ticker BTC-USD python3 {baseDir}/scripts/market_client.py crypto snapshot --ticker ETH # Auto-converts to ETH-USD python3 {baseDir}/scripts/market_client.py crypto historical --ticker BTC-USD --start 2025-01-01 --end 2025-01-31 python3 {baseDir}/scripts/market_client.py crypto portfolio --tickers BTC-USD,ETH-USD,SOL-USD ``` --- ## API Endpoints Reference ### Traditional Finance | Endpoint | Method | Description | |----------|--------|-------------| | `/financial/prices` | GET | Historical stock prices (requires interval params) | | `/financial/news` | GET | Company news by ticker | | [REDACTED_SECRET] | GET | All financial statements | | [REDACTED_SECRET] | GET | Income statements | | [REDACTED_SECRET] | GET | Balance sheets | | [REDACTED_SECRET] | GET | Cash flow statements | | [REDACTED_SECRET] | GET | Real-time financial metrics | | `/financial/financial-metrics` | GET | Historical metrics | | `/financial/analyst/eps` | GET | EPS estimates | | `/financial/insider/trades` | GET | Insider trades | | [REDACTED_SECRET] | GET | Institutional ownership | | `/financial/sec/filings` | GET | SEC filings | | `/financial/sec/items` | GET | SEC filing items | | `/financial/company/facts` | GET | Company facts | | `/financial/search/stock` | POST | Stock screener | | [REDACTED_SECRET] | GET | Current interest rates | | [REDACTED_SECRET] | GET | Historical rates | ### Cryptocurrency | Endpoint | Method | Description | |----------|--------|-------------| | [REDACTED_SECRET] | GET | Real-time price snapshot | | `/financial/crypto/prices` | GET | Historical OHLCV data | --- ## Pricing | API | Cost | |-----|------| | Stock prices | ~$0.001 | | Company news | ~$0.001 | | Financial statements | ~$0.002 | | Analyst estimates | ~$0.002 | | SEC filings | ~$0.001 | | Crypto snapshot | ~$0.0005 | | Crypto historical | ~$0.001 | Every response includes `usage.cost` and `usage.credits_remaining`. --- ## 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.mintlify.app/api-reference/introduction) for complete endpoint documentation.

path: README.md
content: # MarketPulse (Stocks + Crypto Data) 📊

Query real-time and historical financial data across equities and crypto—prices, market moves, metrics, and trends for analysis, alerts, and reporting.

## Features

- **Stock Data**: Historical prices, real-time quotes
- **Company News**: Latest news by ticker
- **Financial Statements**: Income, balance sheets, cash flow
- **Analyst Estimates**: EPS forecasts, recommendations
- **Insider Trading**: Track insider transactions
- **SEC Filings**: 10-K, 10-Q, 8-K and more
- **Crypto Data**: Real-time prices, historical OHLCV
- **Stock Screener**: Filter by metrics

## Quick Start

```bash
export AISA_API_KEY="your-key"

# Stock data
python scripts/market_client.py stock prices --ticker AAPL

# Crypto data
python scripts/market_client.py crypto snapshot --symbol BTC
```

## Documentation

See [SKILL.md](SKILL.md) for complete API documentation.


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

Usage:
    # Stock commands
    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>
    python market_client.py stock metrics --ticker <ticker> [--historical]
    python market_client.py stock analyst --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>
    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>
    
    # Crypto commands
    python market_client.py crypto snapshot --ticker <BTC-USD>
    python market_client.py crypto historical --ticker <BTC-USD> --start <date> --end <date> [--interval day]
    python market_client.py crypto portfolio --tickers <BTC-USD,ETH-USD,SOL-USD>
"""

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


class MarketClient:
    """OpenClaw 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": "OpenClaw-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.
        
        Args:
            ticker: Stock symbol (e.g., AAPL)
            start_date: Start date (YYYY-MM-DD) - required
            end_date: End date (YYYY-MM-DD) - required
            interval: second, minute, day, week, month, year (default: day)
            interval_multiplier: Multiplier for interval (default: 1)
        """
        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) -> Dict[str, Any]:
        """Get all financial statements."""
        return self._request("GET", "/financial/financial_statements/all", params={"ticker": ticker})
    
    def statements_income(self, ticker: str) -> Dict[str, Any]:
        """Get income statements."""
        return self._request("GET", "/financial/financial_statements/income", params={"ticker": ticker})
    
    def statements_balance(self, ticker: str) -> Dict[str, Any]:
        """Get balance sheets."""
        return self._request("GET", "/financial/financial_statements/balance", params={"ticker": ticker})
    
    def statements_cash(self, ticker: str) -> Dict[str, Any]:
        """Get cash flow statements."""
        return self._request("GET", "/financial/financial_statements/cash", params={"ticker": ticker})
    
    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) -> Dict[str, Any]:
        """Get historical financial metrics."""
        return self._request("GET", "/financial/financial-metrics", params={"ticker": ticker})
    
    def analyst_eps(self, ticker: str, period: str = "annual") -> Dict[str, Any]:
        """Get earnings per share estimates."""
        return self._request("GET", "/financial/analyst/eps", params={
            "ticker": ticker,
            "period": period
        })
    
    def insider_trades(self, ticker: str) -> Dict[str, Any]:
        """Get insider trades."""
        return self._request("GET", "/financial/insider/trades", params={"ticker": ticker})
    
    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) -> Dict[str, Any]:
        """Get SEC filings."""
        return self._request("GET", "/financial/sec/filings", params={"ticker": ticker})
    
    def sec_items(self, ticker: str) -> Dict[str, Any]:
        """Get SEC filing items."""
        return self._request("GET", "/financial/sec/items", params={"ticker": ticker})
    
    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."""
        return self._request("GET", "/financial/interest_rates/snapshot")
    
    def rates_historical(self, bank: str = "fed") -> Dict[str, Any]:
        """Get historical interest rates."""
        return self._request("GET", "/financial/interest_rates/historical", params={"bank": bank})
    
    def screen_stocks(self, filters: Dict[str, Any]) -> Dict[str, Any]:
        """Screen for stocks matching criteria."""
        return self._request("POST", "/financial/search/stock", data={"filters": filters})
    
    # ==================== Crypto APIs ====================
    
    def crypto_snapshot(self, ticker: str) -> Dict[str, Any]:
        """
        Get real-time price snapshot for a cryptocurrency.
        
        Args:
            ticker: Crypto ticker in format SYMBOL-USD (e.g., BTC-USD, ETH-USD)
        """
        return self._request("GET", "/financial/crypto/prices/snapshot", params={"ticker": ticker})
    
    def crypto_historical(
        self, 
        ticker: str, 
        start_date: str,
        end_date: str,
        interval: str = "day",
        interval_multiplier: int = 1
    ) -> Dict[str, Any]:
        """
        Get historical price data for a cryptocurrency.
        
        Args:
            ticker: Crypto ticker in format SYMBOL-USD (e.g., BTC-USD)
            start_date: Start date (YYYY-MM-DD) - required
            end_date: End date (YYYY-MM-DD) - required
            interval: second, minute, day, week, month, year (default: day)
            interval_multiplier: Multiplier for interval (default: 1)
        """
        return self._request("GET", "/financial/crypto/prices", params={
            "ticker": ticker,
            "start_date": start_date,
            "end_date": end_date,
            "interval": interval,
            "interval_multiplier": interval_multiplier
        })
    
    def crypto_portfolio(self, tickers: List[str]) -> Dict[str, Any]:
        """
        Get prices for multiple cryptocurrencies.
        
        Args:
            tickers: List of crypto tickers in format SYMBOL-USD
        """
        results = {}
        for ticker in tickers:
            results[ticker] = self.crypto_snapshot(ticker)
        return {"portfolio": results}


def _normalize_crypto_ticker(symbol: str) -> str:
    """Convert simple symbol to ticker format (BTC -> BTC-USD)."""
    symbol = symbol.upper().strip()
    if not symbol.endswith("-USD"):
        return f"{symbol}-USD"
    return symbol


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        description="OpenClaw Market - Complete market data (Stocks + Crypto)",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
    %(prog)s stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31
    %(prog)s stock prices --ticker AAPL --start 2025-01-01 --end 2025-01-31 --interval week
    %(prog)s stock news --ticker AAPL --count 5
    %(prog)s crypto snapshot --ticker BTC-USD
    %(prog)s crypto snapshot --ticker BTC  # Auto-converts to BTC-USD
    %(prog)s crypto historical --ticker ETH-USD --start 2025-01-01 --end 2025-01-15
        """
    )
    
    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")
    
    # 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")
    
    # 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")
    
    # insider
    insider = stock_sub.add_parser("insider", help="Get insider trades")
    insider.add_argument("--ticker", "-t", required=True, help="Stock ticker")
    
    # 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")
    
    # 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")
    
    # ==================== Crypto Commands ====================
    crypto_parser = subparsers.add_parser("crypto", help="Cryptocurrency commands")
    crypto_sub = crypto_parser.add_subparsers(dest="command", help="Command")
    
    # snapshot
    snapshot = crypto_sub.add_parser("snapshot", help="Get real-time price")
    snapshot.add_argument("--ticker", "-t", required=True, 
                         help="Crypto ticker (e.g., BTC-USD or BTC)")
    
    # historical
    historical = crypto_sub.add_parser("historical", help="Get historical prices")
    historical.add_argument("--ticker", "-t", required=True, 
                           help="Crypto ticker (e.g., BTC-USD or BTC)")
    historical.add_argument("--start", "-s", required=True, help="Start date (YYYY-MM-DD)")
    historical.add_argument("--end", "-e", required=True, help="End date (YYYY-MM-DD)")
    historical.add_argument("--interval", "-i", default="day",
                           choices=["second", "minute", "day", "week", "month", "year"],
                           help="Time interval (default: day)")
    historical.add_argument("--multiplier", "-m", type=int, default=1,
                           help="Interval multiplier (default: 1)")
    
    # portfolio
    portfolio = crypto_sub.add_parser("portfolio", help="Get prices for multiple coins")
    portfolio.add_argument("--tickers", "-t", required=True, 
                          help="Tickers (comma-separated, e.g., BTC-USD,ETH-USD or BTC,ETH)")
    
    args = parser.parse_args()
    
    if not args.asset_type:
        parser.print_help()
        sys.exit(1)
    
    if not args.command:
        if args.asset_type == "stock":
            stock_parser.print_help()
        else:
            crypto_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
    
    # Stock commands
    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)
            elif args.type == "income":
                result = client.statements_income(args.ticker)
            elif args.type == "balance":
                result = client.statements_balance(args.ticker)
            elif args.type == "cash":
                result = client.statements_cash(args.ticker)
        elif args.command == "metrics":
            if args.historical:
                result = client.metrics_historical(args.ticker)
            else:
                result = client.metrics_snapshot(args.ticker)
        elif args.command == "analyst":
            result = client.analyst_eps(args.ticker, args.period)
        elif args.command == "insider":
            result = client.insider_trades(args.ticker)
        elif args.command == "ownership":
            result = client.institutional_ownership(args.ticker)
        elif args.command == "filings":
            result = client.sec_filings(args.ticker)
        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 = {}
            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)
    
    # Crypto commands
    elif args.asset_type == "crypto":
        if args.command == "snapshot":
            ticker = _normalize_crypto_ticker(args.ticker)
            result = client.crypto_snapshot(ticker)
        elif args.command == "historical":
            ticker = _normalize_crypto_ticker(args.ticker)
            result = client.crypto_historical(
                ticker, 
                args.start, 
                args.end,
                args.interval,
                args.multiplier
            )
        elif args.command == "portfolio":
            tickers = [_normalize_crypto_ticker(t.strip()) for t in args.tickers.split(",")]
            result = client.crypto_portfolio(tickers)
    
    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: clean (LOW)