__init__.py
"""
Coinglass Extension - Crypto Derivatives Data Tools
Provides crypto derivatives market data including:
- Funding rates (V2 API)
- Open interest (V2 API)
- Long/Short ratios (V2 API)
- Liquidations (V2/V4 API)
- Futures market data (V4 API)
- Supported coins and exchanges
- Comprehensive market data for all coins
- Pair-specific market metrics
- OHLC price history
Environment Variables Required:
- COINGLASS_API_KEY: Coinglass API key
Usage:
This extension is auto-loaded by the ExtensionLoader.
Tools are available to agents configured with these tools in agents.yaml.
"""
import os
import sys
import logging
from typing import List
try:
from core.tool import ToolRegistry
except Exception:
ToolRegistry = None # Standalone script usage
logger = logging.getLogger(__name__)
# Add local tools directory to path for imports
TOOLS_DIR = os.path.join(os.path.dirname(__file__), 'tools')
if TOOLS_DIR not in sys.path:
sys.path.insert(0, TOOLS_DIR)
def register(api) -> List[str]:
"""
Extension entry point - register all Coinglass tools.
Args:
api: ExtensionApi instance with registry and config
Returns:
List of registered tool names
"""
registered = []
try:
from .coinglass import (
FundingRateTool,
LongShortRatioTool,
GlobalAccountRatioTool,
TopAccountRatioTool,
TopPositionRatioTool,
TakerBuySellExchangesTool,
NetPositionTool,
OpenInterestTool,
LiquidationsTool,
LiquidationAnalysisTool,
CoinLiquidationHistoryTool,
PairLiquidationHistoryTool,
LiquidationCoinListTool,
LiquidationOrdersTool,
HyperliquidWhaleAlertsTool,
HyperliquidWhalePositionsTool,
HyperliquidPositionsByCoinTool,
HyperliquidPositionDistributionTool,
SupportedCoinsTool,
SupportedExchangesTool,
CoinsMarketDataTool,
PairMarketDataTool,
OHLCHistoryTool,
TakerVolumeHistoryTool,
AggregatedTakerVolumeTool,
CumulativeVolumeDeltaTool,
CoinNetflowTool,
WhaleTransferTool,
BTCETFFlowsTool,
BTCETFPremiumDiscountTool,
BTCETFHistoryTool,
BTCETFListTool,
HKBTCETFFlowsTool,
ETHETFFlowsTool,
ETHETFListTool,
SOLETFFlowsTool,
XRPETFFlowsTool,
)
# Register existing V2 tools
api.register_tool(FundingRateTool())
api.register_tool(LongShortRatioTool())
# Register advanced long/short ratio tools
api.register_tool(GlobalAccountRatioTool())
api.register_tool(TopAccountRatioTool())
api.register_tool(TopPositionRatioTool())
api.register_tool(TakerBuySellExchangesTool())
api.register_tool(NetPositionTool())
api.register_tool(OpenInterestTool())
api.register_tool(LiquidationsTool())
api.register_tool(LiquidationAnalysisTool())
# Register advanced liquidation tools
api.register_tool(CoinLiquidationHistoryTool())
api.register_tool(PairLiquidationHistoryTool())
api.register_tool(LiquidationCoinListTool())
api.register_tool(LiquidationOrdersTool())
# Register Hyperliquid tools
api.register_tool(HyperliquidWhaleAlertsTool())
api.register_tool(HyperliquidWhalePositionsTool())
api.register_tool(HyperliquidPositionsByCoinTool())
api.register_tool(HyperliquidPositionDistributionTool())
# Register new V4 futures market tools
api.register_tool(SupportedCoinsTool())
api.register_tool(SupportedExchangesTool())
api.register_tool(CoinsMarketDataTool())
api.register_tool(PairMarketDataTool())
api.register_tool(OHLCHistoryTool())
# Register Volume & Flow tools
api.register_tool(TakerVolumeHistoryTool())
api.register_tool(AggregatedTakerVolumeTool())
api.register_tool(CumulativeVolumeDeltaTool())
api.register_tool(CoinNetflowTool())
# Register Whale Transfer tool
api.register_tool(WhaleTransferTool())
# Register Bitcoin ETF tools
api.register_tool(BTCETFFlowsTool())
api.register_tool(BTCETFPremiumDiscountTool())
api.register_tool(BTCETFHistoryTool())
api.register_tool(BTCETFListTool())
api.register_tool(HKBTCETFFlowsTool())
# Register Ethereum & Other ETF tools
api.register_tool(ETHETFFlowsTool())
api.register_tool(ETHETFListTool())
api.register_tool(SOLETFFlowsTool())
api.register_tool(XRPETFFlowsTool())
registered.extend([
"funding_rate",
"long_short_ratio",
"cg_global_account_ratio",
"cg_top_account_ratio",
"cg_top_position_ratio",
"cg_taker_exchanges",
"cg_net_position",
"cg_open_interest",
"cg_liquidations",
"cg_liquidation_analysis",
"cg_coin_liquidation_history",
"cg_pair_liquidation_history",
"cg_liquidation_coin_list",
"cg_liquidation_orders",
"cg_hyperliquid_whale_alerts",
"cg_hyperliquid_whale_positions",
"cg_hyperliquid_positions_by_coin",
"cg_hyperliquid_position_distribution",
"cg_supported_coins",
"cg_supported_exchanges",
"cg_coins_market_data",
"cg_pair_market_data",
"cg_ohlc_history",
"cg_taker_volume_history",
"cg_aggregated_taker_volume",
"cg_cumulative_volume_delta",
"cg_coin_netflow",
"cg_whale_transfers",
"cg_btc_etf_flows",
"cg_btc_etf_premium_discount",
"cg_btc_etf_history",
"cg_btc_etf_list",
"cg_hk_btc_etf_flows",
"cg_eth_etf_flows",
"cg_eth_etf_list",
"cg_sol_etf_flows",
"cg_xrp_etf_flows",
])
logger.info("Registered Coinglass tools (37 tools)")
except Exception as e:
logger.warning(f"Failed to load Coinglass tools: {e}")
return registered
# Extension metadata
EXTENSION_INFO = {
"name": "coinglass",
"version": "3.0.5",
"description": "Coinglass crypto derivatives data tools - V4 API with advanced long/short ratios, liquidations, Hyperliquid whale tracking, volume & flow analysis, on-chain whale transfers, comprehensive ETF data (Bitcoin, Ethereum, Solana, XRP, Hong Kong), and futures market data (37 tools)",
"tools": [
"funding_rate",
"long_short_ratio",
"cg_global_account_ratio",
"cg_top_account_ratio",
"cg_top_position_ratio",
"cg_taker_exchanges",
"cg_net_position",
"cg_open_interest",
"cg_liquidations",
"cg_liquidation_analysis",
"cg_coin_liquidation_history",
"cg_pair_liquidation_history",
"cg_liquidation_coin_list",
"cg_liquidation_orders",
"cg_hyperliquid_whale_alerts",
"cg_hyperliquid_whale_positions",
"cg_hyperliquid_positions_by_coin",
"cg_hyperliquid_position_distribution",
"cg_supported_coins",
"cg_supported_exchanges",
"cg_coins_market_data",
"cg_pair_market_data",
"cg_ohlc_history",
"cg_taker_volume_history",
"cg_aggregated_taker_volume",
"cg_cumulative_volume_delta",
"cg_coin_netflow",
"cg_whale_transfers",
"cg_btc_etf_flows",
"cg_btc_etf_premium_discount",
"cg_btc_etf_history",
"cg_btc_etf_list",
"cg_hk_btc_etf_flows",
"cg_eth_etf_flows",
"cg_eth_etf_list",
"cg_sol_etf_flows",
"cg_xrp_etf_flows",
],
"env_vars": [
"COINGLASS_API_KEY",
],
}
coinglass.py
"""
Coinglass Tool Wrappers
Wraps tools from /tools/coinglass/ for use in Agent framework.
Provides derivatives data: funding rates, open interest, liquidations, long/short ratios.
"""
import asyncio
import logging
from typing import Optional
from core.tool import BaseTool, ToolContext, ToolResult
logger = logging.getLogger(__name__)
# Import original tools from local tools directory
try:
from .tools.funding_rate import get_funding_rates, get_symbol_funding_rate
from .tools.long_short_ratio import get_long_short_ratio
from .tools.long_short_advanced import (
get_global_account_ratio,
get_top_account_ratio,
get_top_position_ratio,
get_taker_buysell_exchanges,
get_net_position
)
from .tools.open_interest import get_open_interest
from .tools.liquidations import get_liquidations, get_liquidation_aggregated
from .tools.liquidations_advanced import (
get_coin_liquidation_history,
get_pair_liquidation_history,
get_liquidation_coin_list,
get_liquidation_orders
)
from .tools.hyperliquid import (
get_whale_alerts,
get_whale_positions,
get_positions_by_coin,
get_position_distribution
)
from .tools.futures_market import (
get_supported_coins,
get_supported_exchanges,
get_coins_data,
get_pair_data,
get_ohlc_history
)
from .tools.volume_flow import (
get_taker_volume_history,
get_aggregated_taker_volume,
get_cumulative_volume_delta,
get_coin_netflow
)
from .tools.whale_transfer import get_whale_transfers
from .tools._api import CoinglassError
from .tools.bitcoin_etf import (
get_btc_etf_flows,
get_btc_etf_premium_discount,
get_btc_etf_history,
get_btc_etf_list,
get_hk_btc_etf_flows
)
from .tools.other_etfs import (
get_eth_etf_flows,
get_eth_etf_list,
get_sol_etf_flows,
get_xrp_etf_flows
)
COINGLASS_AVAILABLE = True
except ImportError as e:
logger.warning(f"Coinglass tools not available: {e}")
COINGLASS_AVAILABLE = False
class FundingRateTool(BaseTool):
"""
Get perpetual futures funding rates across exchanges.
Funding rates indicate market sentiment:
- Positive rates: Longs pay shorts (bullish bias)
- Negative rates: Shorts pay longs (bearish bias)
- Extreme rates often precede reversals
"""
@property
def name(self) -> str:
return "funding_rate"
@property
def description(self) -> str:
return """Get perpetual futures funding rates across exchanges.
Positive rates = longs pay shorts (bullish sentiment)
Negative rates = shorts pay longs (bearish sentiment)
Extreme funding often signals reversal risk.
Examples:
- Get BTC funding rates: funding_rate(symbol="BTC")
- Get ETH funding on Binance: funding_rate(symbol="ETH", exchange="Binance")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"exchange": {
"type": "string",
"description": "Optional: specific exchange (Binance, OKX, Bybit, etc.)"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
exchange: Optional[str] = None
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
if exchange:
result = await asyncio.to_thread(get_symbol_funding_rate, symbol=symbol, exchange=exchange)
else:
result = await asyncio.to_thread(get_funding_rates, symbol=symbol)
if result is None:
return ToolResult(
success=False,
output=None,
error="No data returned. The API returned an empty result."
)
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class LongShortRatioTool(BaseTool):
"""
Get long/short ratio for a cryptocurrency.
Shows the ratio of long vs short positions across exchanges.
Useful for sentiment analysis.
"""
@property
def name(self) -> str:
return "long_short_ratio"
@property
def description(self) -> str:
return """Get long/short position ratio across exchanges.
Ratio > 1: More longs than shorts
Ratio < 1: More shorts than longs
Extreme ratios often signal crowded trades.
Examples:
- Get BTC L/S ratio: long_short_ratio(symbol="BTC")
- Get ETH L/S ratio with timeframe: long_short_ratio(symbol="ETH", interval="h4")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"interval": {
"type": "string",
"description": "Time interval: h1, h4, h12, h24",
"default": "h4"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
interval: str = "h4"
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_long_short_ratio, symbol=symbol, time_type=interval)
if result is None:
return ToolResult(
success=False,
output=None,
error="No data returned. The API returned an empty result."
)
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Advanced Long/Short Ratio Tools ====================
class GlobalAccountRatioTool(BaseTool):
"""Get global long/short account ratio history."""
@property
def name(self) -> str:
return "cg_global_account_ratio"
@property
def description(self) -> str:
return """Get global long/short account ratio history for a trading pair.
Shows the percentage of accounts holding long vs short positions over time.
Examples:
- Get BTC global ratio: cg_global_account_ratio(symbol="BTC", exchange="Binance")
- Get ETH with 4h interval: cg_global_account_ratio(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_global_account_ratio, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class TopAccountRatioTool(BaseTool):
"""Get top traders long/short account ratio."""
@property
def name(self) -> str:
return "cg_top_account_ratio"
@property
def description(self) -> str:
return """Get long/short account ratio for top traders only.
Shows what the most successful traders are doing. More reliable than global ratios.
Examples:
- Get BTC top trader ratio: cg_top_account_ratio(symbol="BTC", exchange="Binance")
- Get ETH 4h: cg_top_account_ratio(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_top_account_ratio, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class TopPositionRatioTool(BaseTool):
"""Get top traders long/short position ratio."""
@property
def name(self) -> str:
return "cg_top_position_ratio"
@property
def description(self) -> str:
return """Get long/short position ratio for top traders (by position size, not account count).
Shows the actual $ amount split between longs and shorts for top traders.
Examples:
- Get BTC top position ratio: cg_top_position_ratio(symbol="BTC", exchange="Binance")
- Get ETH 4h: cg_top_position_ratio(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_top_position_ratio, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class TakerBuySellExchangesTool(BaseTool):
"""Get exchanges with taker buy/sell volume data."""
@property
def name(self) -> str:
return "cg_taker_exchanges"
@property
def description(self) -> str:
return """Get list of exchanges with taker buy/sell volume data available.
Shows which exchanges provide taker volume metrics and their current ratios.
Examples:
- Get BTC exchanges (1h): cg_taker_exchanges(symbol="BTC")
- Get ETH exchanges (24h): cg_taker_exchanges(symbol="ETH", range="24h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"range": {"type": "string", "description": "Time range: 1h, 4h, 12h, 24h (default: 1h)", "default": "1h"}
},
"required": ["symbol"]
}
async def execute(self, ctx: ToolContext, symbol: str, range: str = "1h") -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_taker_buysell_exchanges, symbol, range)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class NetPositionTool(BaseTool):
"""Get net position changes (net long/short delta)."""
@property
def name(self) -> str:
return "cg_net_position"
@property
def description(self) -> str:
return """Get historical net position data showing net long/short changes.
Net position = difference between long and short positions opened.
Useful for tracking institutional positioning.
Examples:
- Get BTC net position: cg_net_position(symbol="BTC", exchange="Binance")
- Get ETH 4h: cg_net_position(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_net_position, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Open Interest Tools ====================
class OpenInterestTool(BaseTool):
"""
Get aggregate open interest across exchanges.
"""
@property
def name(self) -> str:
return "cg_open_interest"
@property
def description(self) -> str:
return """Get aggregate open interest across exchanges for a symbol.
Open interest = total outstanding derivative contracts.
Rising OI + rising price = new money entering (bullish)
Rising OI + falling price = new shorts opening (bearish)
Falling OI = positions closing (trend weakening)
Examples:
- Get BTC open interest: cg_open_interest(symbol="BTC")
- Get ETH open interest: cg_open_interest(symbol="ETH")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_open_interest, symbol)
if result is None:
return ToolResult(
success=False,
output=None,
error="No data returned. The API returned an empty result."
)
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Liquidation Tools ====================
class LiquidationsTool(BaseTool):
"""
Get recent liquidation data.
"""
@property
def name(self) -> str:
return "cg_liquidations"
@property
def description(self) -> str:
return """Get recent liquidation data across exchanges.
Liquidations = forced position closures due to insufficient margin.
More long liquidations = bearish pressure (longs being squeezed)
More short liquidations = bullish pressure (shorts being squeezed)
Examples:
- Get BTC liquidations (24h): cg_liquidations(symbol="BTC")
- Get ETH liquidations (4h): cg_liquidations(symbol="ETH", time_type="h4")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"time_type": {
"type": "string",
"description": "Time window: h1, h4, h12, h24",
"default": "h24"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
time_type: str = "h24"
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_liquidations, symbol, time_type)
if result is None:
return ToolResult(
success=False,
output=None,
error="No data returned. The API returned an empty result."
)
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class LiquidationAnalysisTool(BaseTool):
"""
Get liquidation data with sentiment analysis.
"""
@property
def name(self) -> str:
return "cg_liquidation_analysis"
@property
def description(self) -> str:
return """Get liquidation data with market sentiment analysis.
Includes interpretation of liquidation imbalances.
Examples:
- Analyze BTC liquidations: cg_liquidation_analysis(symbol="BTC")
- Analyze ETH (4h): cg_liquidation_analysis(symbol="ETH", time_type="h4")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"time_type": {
"type": "string",
"description": "Time window: h1, h4, h12, h24",
"default": "h24"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
time_type: str = "h24"
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_liquidation_aggregated, symbol, time_type)
if result is None:
return ToolResult(
success=False,
output=None,
error="No data returned. The API returned an empty result."
)
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Advanced Liquidation Tools ====================
class CoinLiquidationHistoryTool(BaseTool):
"""Get aggregated liquidation history for a coin across all exchanges."""
@property
def name(self) -> str:
return "cg_coin_liquidation_history"
@property
def description(self) -> str:
return """Get aggregated liquidation history across all exchanges for a coin.
Shows total long/short liquidations over time, aggregated across all exchanges.
Examples:
- Get BTC liquidation history: cg_coin_liquidation_history(symbol="BTC", interval="1h", limit=100)
- Get ETH 4h intervals: cg_coin_liquidation_history(symbol="ETH", interval="4h", limit=50)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange_list": {"type": "string", "description": "Comma-separated exchange list (e.g. 'Binance,OKX,Bybit')"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in milliseconds"},
"end_time": {"type": "integer", "description": "End timestamp in milliseconds"}
},
"required": ["symbol", "exchange_list"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange_list: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_coin_liquidation_history, symbol, exchange_list, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class PairLiquidationHistoryTool(BaseTool):
"""Get liquidation history for a specific trading pair on an exchange."""
@property
def name(self) -> str:
return "cg_pair_liquidation_history"
@property
def description(self) -> str:
return """Get liquidation history for a specific pair on a specific exchange.
Shows long/short liquidations over time for exchange-specific pairs.
Examples:
- Get BTC/USDT on Binance: cg_pair_liquidation_history(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH/USDT on OKX: cg_pair_liquidation_history(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1h, 4h, 12h, 24h", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_pair_liquidation_history, symbol, exchange, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class LiquidationCoinListTool(BaseTool):
"""Get liquidation data for all coins on a specific exchange."""
@property
def name(self) -> str:
return "cg_liquidation_coin_list"
@property
def description(self) -> str:
return """Get liquidation data for all coins on a specific exchange.
Shows liquidation amounts across multiple timeframes (1h, 4h, 12h, 24h) for all coins on an exchange.
Examples:
- Get all Binance liquidations: cg_liquidation_coin_list(exchange="Binance")
- Get all OKX liquidations: cg_liquidation_coin_list(exchange="OKX")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"}
},
"required": ["exchange"]
}
async def execute(self, ctx: ToolContext, exchange: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_liquidation_coin_list, exchange)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class LiquidationOrdersTool(BaseTool):
"""Get individual liquidation orders (past 7 days)."""
@property
def name(self) -> str:
return "cg_liquidation_orders"
@property
def description(self) -> str:
return """Get individual liquidation orders with price, side, and USD value (past 7 days only).
Shows actual liquidation events. Max 200 records per request.
Examples:
- Get BTC liquidations on Binance (min $10K): cg_liquidation_orders(symbol="BTC", exchange="Binance", min_liquidation_amount="10000")
- Get ETH liquidations on OKX (min $5K): cg_liquidation_orders(symbol="ETH", exchange="OKX", min_liquidation_amount="5000")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"min_liquidation_amount": {"type": "string", "description": "Minimum threshold for liquidation events (USD)"},
"start_time": {"type": "integer", "description": "Start timestamp in milliseconds"},
"end_time": {"type": "integer", "description": "End timestamp in milliseconds"}
},
"required": ["symbol", "exchange", "min_liquidation_amount"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, min_liquidation_amount: str,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_liquidation_orders, symbol, exchange, min_liquidation_amount, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Futures Market Data Tools (V4 API) ====================
class SupportedCoinsTool(BaseTool):
"""Get list of all supported coins for futures trading."""
@property
def name(self) -> str:
return "cg_supported_coins"
@property
def description(self) -> str:
return """Get list of all supported coins for futures trading on Coinglass.
Returns array of coin symbols (BTC, ETH, SOL, XRP, HYPE, DOGE, etc.)
Use this for:
- Market discovery
- Checking if a coin has futures markets
- Finding new trading opportunities
Examples:
- Get all supported coins: cg_supported_coins()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_supported_coins)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class SupportedExchangesTool(BaseTool):
"""Get all supported exchanges with their trading pairs."""
@property
def name(self) -> str:
return "cg_supported_exchanges"
@property
def description(self) -> str:
return """Get all supported exchanges with trading pairs and specs.
Returns dictionary with exchange pairs including leverage limits, funding intervals, tick sizes.
Examples:
- Get all exchanges: cg_supported_exchanges()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_supported_exchanges)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class CoinsMarketDataTool(BaseTool):
"""Get comprehensive market data for ALL coins in one request."""
@property
def name(self) -> str:
return "cg_coins_market_data"
@property
def description(self) -> str:
return """Get market data for ALL coins in ONE request.
Returns: price, funding rates, OI, volume, long/short ratios, liquidations for 100+ coins.
Use this for market screening and bulk analysis. MUCH more efficient than individual calls.
Examples:
- Get all coins data: cg_coins_market_data()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_coins_data)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class PairMarketDataTool(BaseTool):
"""Get detailed market data for a specific trading pair."""
@property
def name(self) -> str:
return "cg_pair_market_data"
@property
def description(self) -> str:
return """Get detailed market data for a specific pair on an exchange.
Returns: price, volume, OI, funding rate, liquidations, long/short volumes.
Examples:
- Get BTC/USDT on Binance: cg_pair_market_data(symbol="BTC", exchange="Binance")
- Get ETH/USDT on OKX: cg_pair_market_data(symbol="ETH", exchange="OKX")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Coin symbol (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, Gate, etc.)"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_pair_data, symbol, exchange)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class OHLCHistoryTool(BaseTool):
"""Get OHLC price history for a trading pair."""
@property
def name(self) -> str:
return "cg_ohlc_history"
@property
def description(self) -> str:
return """Get OHLC candlestick data for price analysis.
Returns array of candles with: timestamp, open, high, low, close.
Examples:
- Get BTC 1h candles: cg_ohlc_history(symbol="BTC", exchange="Binance", interval="h1", limit=100)
- Get ETH daily: cg_ohlc_history(symbol="ETH", exchange="OKX", interval="d1", limit=30)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Coin symbol (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: m1, m5, m15, m30, h1, h4, h12, d1", "default": "h1"},
"limit": {"type": "integer", "description": "Number of candles (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "h1", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_ohlc_history, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Hyperliquid Tools ====================
class HyperliquidWhaleAlertsTool(BaseTool):
"""Get recent whale alerts on Hyperliquid (positions > $1M)."""
@property
def name(self) -> str:
return "cg_hyperliquid_whale_alerts"
@property
def description(self) -> str:
return """Get recent whale alerts on Hyperliquid (positions > $1M).
Returns approximately 200 most recent large position opens/closes.
Examples:
- Get whale alerts: cg_hyperliquid_whale_alerts()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_whale_alerts)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class HyperliquidWhalePositionsTool(BaseTool):
"""Get current whale positions on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_whale_positions"
@property
def description(self) -> str:
return """Get current whale positions on Hyperliquid.
Shows large active positions with entry price, PnL, leverage, and margin data.
Examples:
- Get whale positions: cg_hyperliquid_whale_positions()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_whale_positions)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class HyperliquidPositionsByCoinTool(BaseTool):
"""Get wallet positions organized by coin on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_positions_by_coin"
@property
def description(self) -> str:
return """Get real-time wallet positions for a specific coin on Hyperliquid.
Shows all open positions for the specified cryptocurrency.
Examples:
- Get BTC positions: cg_hyperliquid_positions_by_coin(symbol="BTC")
- Get ETH positions: cg_hyperliquid_positions_by_coin(symbol="ETH")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"}
},
"required": ["symbol"]
}
async def execute(self, ctx: ToolContext, symbol: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_positions_by_coin, symbol)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class HyperliquidPositionDistributionTool(BaseTool):
"""Get wallet position distribution on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_position_distribution"
@property
def description(self) -> str:
return """Get wallet position distribution on Hyperliquid.
Shows distribution by size tiers including address counts, long/short values, sentiment, and P/L distribution.
Examples:
- Get position distribution: cg_hyperliquid_position_distribution()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_position_distribution)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Volume & Flow Tools ====================
class TakerVolumeHistoryTool(BaseTool):
"""Get taker buy/sell volume history for a specific trading pair."""
@property
def name(self) -> str:
return "cg_taker_volume_history"
@property
def description(self) -> str:
return """Get historical taker buy/sell volume data for a specific trading pair.
Taker volume = aggressive market orders (vs passive limit orders).
Higher taker buy volume = bullish pressure.
Higher taker sell volume = bearish pressure.
Examples:
- Get BTC taker volume on Binance: cg_taker_volume_history(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH 4h intervals: cg_taker_volume_history(symbol="ETH", exchange="OKX", interval="4h", limit=50)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_taker_volume_history, symbol, exchange, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class AggregatedTakerVolumeTool(BaseTool):
"""Get aggregated taker buy/sell volume across all exchanges."""
@property
def name(self) -> str:
return "cg_aggregated_taker_volume"
@property
def description(self) -> str:
return """Get aggregated taker buy/sell volume across all exchanges for a coin.
Shows total market pressure across all major exchanges.
More comprehensive than single-exchange data.
Examples:
- Get BTC aggregated volume: cg_aggregated_taker_volume(symbol="BTC", interval="1h")
- Get ETH 4h: cg_aggregated_taker_volume(symbol="ETH", interval="4h", limit=100)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange_list": {"type": "string", "description": "Comma-separated exchange list (e.g. 'Binance,OKX,Bybit')"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange_list"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange_list: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_aggregated_taker_volume, symbol, exchange_list, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class CumulativeVolumeDeltaTool(BaseTool):
"""Get Cumulative Volume Delta (CVD) for trend analysis."""
@property
def name(self) -> str:
return "cg_cumulative_volume_delta"
@property
def description(self) -> str:
return """Get Cumulative Volume Delta (CVD) history for a trading pair.
CVD = Running total of (taker buy volume - taker sell volume).
Rising CVD = accumulation (bullish).
Falling CVD = distribution (bearish).
Divergences between price and CVD signal trend weakness.
Examples:
- Get BTC CVD on Binance: cg_cumulative_volume_delta(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH CVD: cg_cumulative_volume_delta(symbol="ETH", exchange="OKX", interval="4h", limit=100)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_cumulative_volume_delta, symbol, exchange, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class CoinNetflowTool(BaseTool):
"""Get netflow data for all futures coins."""
@property
def name(self) -> str:
return "cg_coin_netflow"
@property
def description(self) -> str:
return """Get coin netflow data for all futures coins.
Netflow = Capital flowing into/out of a coin across exchanges.
Positive netflow = accumulation (bullish signal).
Negative netflow = distribution (bearish signal).
Use for identifying which coins are seeing the strongest capital inflows.
Examples:
- Get all coin netflows: cg_coin_netflow()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_coin_netflow)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Whale Transfer Tools ====================
class WhaleTransferTool(BaseTool):
"""Get large on-chain transfers (minimum $10M) across major blockchains."""
@property
def name(self) -> str:
return "cg_whale_transfers"
@property
def description(self) -> str:
return """Get large on-chain whale transfers (minimum $10M) within the past 6 months.
Covers major blockchains: Bitcoin, Ethereum, Tron, Ripple, Dogecoin, Litecoin, Polygon, Algorand, Bitcoin Cash, Solana.
Shows transaction hash, asset, amount, exchanges involved, and transfer direction.
Useful for tracking institutional movements and market impact events.
Transfer types:
- 1 = Inflow (to exchange)
- 2 = Outflow (from exchange)
- 3 = Internal (between exchange wallets)
Examples:
- Get recent whale transfers: cg_whale_transfers()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_whale_transfers)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Bitcoin ETF Tools ====================
class BTCETFFlowsTool(BaseTool):
"""Get Bitcoin ETF flow history (inflows/outflows)."""
@property
def name(self) -> str:
return "cg_btc_etf_flows"
@property
def description(self) -> str:
return """Get Bitcoin ETF flow history including daily net inflows and outflows.
Shows institutional money movement into/out of Bitcoin through ETFs.
Large inflows = institutional accumulation (bullish).
Large outflows = institutional distribution (bearish).
Examples:
- Get BTC ETF flows: cg_btc_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class BTCETFPremiumDiscountTool(BaseTool):
"""Get Bitcoin ETF premium/discount rates."""
@property
def name(self) -> str:
return "cg_btc_etf_premium_discount"
@property
def description(self) -> str:
return """Get Bitcoin ETF premium/discount rates.
Shows how ETF market prices compare to their net asset value (NAV).
Premium (positive) = trading above NAV (high demand).
Discount (negative) = trading below NAV (low demand).
Examples:
- Get BTC ETF premium/discount: cg_btc_etf_premium_discount()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_premium_discount)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class BTCETFHistoryTool(BaseTool):
"""Get comprehensive Bitcoin ETF history."""
@property
def name(self) -> str:
return "cg_btc_etf_history"
@property
def description(self) -> str:
return """Get comprehensive Bitcoin ETF history.
Includes market price, NAV, premium/discount %, shares outstanding, and net assets.
Examples:
- Get IBIT history: cg_btc_etf_history(ticker="IBIT")
- Get FBTC history: cg_btc_etf_history(ticker="FBTC")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"ticker": {"type": "string", "description": "ETF ticker symbol (e.g. IBIT, FBTC, GBTC)"}
},
"required": ["ticker"]
}
async def execute(self, ctx: ToolContext, ticker: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_history, ticker)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class BTCETFListTool(BaseTool):
"""Get list of Bitcoin ETFs."""
@property
def name(self) -> str:
return "cg_btc_etf_list"
@property
def description(self) -> str:
return """Get list of Bitcoin ETFs with key status information.
Returns ticker symbols, names, inception dates, and other ETF metadata.
Examples:
- Get BTC ETF list: cg_btc_etf_list()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_list)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class HKBTCETFFlowsTool(BaseTool):
"""Get Hong Kong Bitcoin ETF flow history."""
@property
def name(self) -> str:
return "cg_hk_btc_etf_flows"
@property
def description(self) -> str:
return """Get Hong Kong Bitcoin ETF flow history.
Shows ETF flow activity for Bitcoin ETFs in the Hong Kong market.
Useful for tracking Asian institutional demand.
Examples:
- Get HK BTC ETF flows: cg_hk_btc_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_hk_btc_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
# ==================== Ethereum & Other ETF Tools ====================
class ETHETFFlowsTool(BaseTool):
"""Get Ethereum ETF flow history."""
@property
def name(self) -> str:
return "cg_eth_etf_flows"
@property
def description(self) -> str:
return """Get Ethereum ETF flow history including daily net inflows and outflows.
Shows institutional money movement into/out of Ethereum through ETFs.
Examples:
- Get ETH ETF flows: cg_eth_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_eth_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class ETHETFListTool(BaseTool):
"""Get list of Ethereum ETFs."""
@property
def name(self) -> str:
return "cg_eth_etf_list"
@property
def description(self) -> str:
return """Get list of Ethereum ETFs with key status information.
Examples:
- Get ETH ETF list: cg_eth_etf_list()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_eth_etf_list)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class SOLETFFlowsTool(BaseTool):
"""Get Solana ETF flow history."""
@property
def name(self) -> str:
return "cg_sol_etf_flows"
@property
def description(self) -> str:
return """Get Solana ETF flow history including daily net inflows and outflows.
Examples:
- Get SOL ETF flows: cg_sol_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_sol_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
class XRPETFFlowsTool(BaseTool):
"""Get XRP ETF flow history."""
@property
def name(self) -> str:
return "cg_xrp_etf_flows"
@property
def description(self) -> str:
return """Get XRP ETF flow history including daily net inflows and outflows.
Examples:
- Get XRP ETF flows: cg_xrp_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_xrp_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="No data returned. The API returned an empty result.")
return ToolResult(success=True, output=result)
except CoinglassError as e:
msg = f"Coinglass: {e}"
if e.suggestion:
msg += f" ({e.suggestion})"
return ToolResult(
success=False, output=None, error=msg)
except Exception as e:
return ToolResult(
success=False, output=None,
error=f"Coinglass: {type(e).__name__}: {e}")
coinglass.py.backup2
"""
Coinglass Tool Wrappers
Wraps tools from /tools/coinglass/ for use in Agent framework.
Provides derivatives data: funding rates, open interest, liquidations, long/short ratios.
"""
import asyncio
import logging
from typing import Any, Dict, Optional
from core.tool import BaseTool, ToolContext, ToolResult
logger = logging.getLogger(__name__)
# Import original tools from local tools directory
try:
from .tools.funding_rate import get_funding_rates, get_symbol_funding_rate
from .tools.long_short_ratio import get_long_short_ratio
from .tools.long_short_advanced import (
get_global_account_ratio,
get_top_account_ratio,
get_top_position_ratio,
get_taker_buysell_exchanges,
get_net_position
)
from .tools.open_interest import get_open_interest, get_open_interest_history
from .tools.liquidations import get_liquidations, get_liquidation_aggregated
from .tools.liquidations_advanced import (
get_coin_liquidation_history,
get_pair_liquidation_history,
get_liquidation_coin_list,
get_liquidation_orders,
get_liquidation_heatmap
)
from .tools.hyperliquid import (
get_whale_alerts,
get_whale_positions,
get_positions_by_coin,
get_user_positions,
get_position_distribution
)
from .tools.futures_market import (
get_supported_coins,
get_supported_exchanges,
get_coins_data,
get_pair_data,
get_ohlc_history
)
from .tools.volume_flow import (
get_taker_volume_history,
get_aggregated_taker_volume,
get_cumulative_volume_delta,
get_coin_netflow,
get_volume_ohlc_history
)
from .tools.whale_transfer import get_whale_transfers
from .tools.bitcoin_etf import (
get_btc_etf_flows,
get_btc_etf_net_assets,
get_btc_etf_premium_discount,
get_btc_etf_history,
get_btc_etf_list,
get_hk_btc_etf_flows
)
from .tools.other_etfs import (
get_eth_etf_flows,
get_eth_etf_list,
get_sol_etf_flows,
get_xrp_etf_flows
)
COINGLASS_AVAILABLE = True
except ImportError as e:
logger.warning(f"Coinglass tools not available: {e}")
COINGLASS_AVAILABLE = False
class FundingRateTool(BaseTool):
"""
Get perpetual futures funding rates across exchanges.
Funding rates indicate market sentiment:
- Positive rates: Longs pay shorts (bullish bias)
- Negative rates: Shorts pay longs (bearish bias)
- Extreme rates often precede reversals
"""
@property
def name(self) -> str:
return "funding_rate"
@property
def description(self) -> str:
return """Get perpetual futures funding rates across exchanges.
Positive rates = longs pay shorts (bullish sentiment)
Negative rates = shorts pay longs (bearish sentiment)
Extreme funding often signals reversal risk.
Examples:
- Get BTC funding rates: funding_rate(symbol="BTC")
- Get ETH funding on Binance: funding_rate(symbol="ETH", exchange="Binance")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"exchange": {
"type": "string",
"description": "Optional: specific exchange (Binance, OKX, Bybit, etc.)"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
exchange: Optional[str] = None
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available. Check if /tools/coinglass exists."
)
try:
if exchange:
result = await asyncio.to_thread(get_symbol_funding_rate, symbol=symbol, exchange=exchange)
else:
result = await asyncio.to_thread(get_funding_rates, symbol=symbol)
if result is None:
return ToolResult(
success=False,
output=None,
error="Failed to fetch funding rates. Check COINGLASS_API_KEY."
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class LongShortRatioTool(BaseTool):
"""
Get long/short ratio for a cryptocurrency.
Shows the ratio of long vs short positions across exchanges.
Useful for sentiment analysis.
"""
@property
def name(self) -> str:
return "long_short_ratio"
@property
def description(self) -> str:
return """Get long/short position ratio across exchanges.
Ratio > 1: More longs than shorts
Ratio < 1: More shorts than longs
Extreme ratios often signal crowded trades.
Examples:
- Get BTC L/S ratio: long_short_ratio(symbol="BTC")
- Get ETH L/S ratio with timeframe: long_short_ratio(symbol="ETH", interval="h4")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"interval": {
"type": "string",
"description": "Time interval: h1, h4, h12, h24",
"default": "h4"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
interval: str = "h4"
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_long_short_ratio, symbol=symbol, time_type=interval)
if result is None:
return ToolResult(
success=False,
output=None,
error="Failed to fetch long/short ratio. Check COINGLASS_API_KEY."
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Advanced Long/Short Ratio Tools ====================
class GlobalAccountRatioTool(BaseTool):
"""Get global long/short account ratio history."""
@property
def name(self) -> str:
return "cg_global_account_ratio"
@property
def description(self) -> str:
return """Get global long/short account ratio history for a trading pair.
Shows the percentage of accounts holding long vs short positions over time.
Examples:
- Get BTC global ratio: cg_global_account_ratio(symbol="BTC", exchange="Binance")
- Get ETH with 4h interval: cg_global_account_ratio(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_global_account_ratio, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch global account ratio. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class TopAccountRatioTool(BaseTool):
"""Get top traders long/short account ratio."""
@property
def name(self) -> str:
return "cg_top_account_ratio"
@property
def description(self) -> str:
return """Get long/short account ratio for top traders only.
Shows what the most successful traders are doing. More reliable than global ratios.
Examples:
- Get BTC top trader ratio: cg_top_account_ratio(symbol="BTC", exchange="Binance")
- Get ETH 4h: cg_top_account_ratio(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_top_account_ratio, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch top account ratio. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class TopPositionRatioTool(BaseTool):
"""Get top traders long/short position ratio."""
@property
def name(self) -> str:
return "cg_top_position_ratio"
@property
def description(self) -> str:
return """Get long/short position ratio for top traders (by position size, not account count).
Shows the actual $ amount split between longs and shorts for top traders.
Examples:
- Get BTC top position ratio: cg_top_position_ratio(symbol="BTC", exchange="Binance")
- Get ETH 4h: cg_top_position_ratio(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_top_position_ratio, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch top position ratio. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class TakerBuySellExchangesTool(BaseTool):
"""Get exchanges with taker buy/sell volume data."""
@property
def name(self) -> str:
return "cg_taker_exchanges"
@property
def description(self) -> str:
return """Get list of exchanges with taker buy/sell volume data available.
Shows which exchanges provide taker volume metrics and their current ratios.
Examples:
- Get BTC exchanges (1h): cg_taker_exchanges(symbol="BTC")
- Get ETH exchanges (24h): cg_taker_exchanges(symbol="ETH", range="24h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"range": {"type": "string", "description": "Time range: 1h, 4h, 12h, 24h (default: 1h)", "default": "1h"}
},
"required": ["symbol"]
}
async def execute(self, ctx: ToolContext, symbol: str, range: str = "1h") -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_taker_buysell_exchanges, symbol, range)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch taker exchanges. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class NetPositionTool(BaseTool):
"""Get net position changes (net long/short delta)."""
@property
def name(self) -> str:
return "cg_net_position"
@property
def description(self) -> str:
return """Get historical net position data showing net long/short changes.
Net position = difference between long and short positions opened.
Useful for tracking institutional positioning.
Examples:
- Get BTC net position: cg_net_position(symbol="BTC", exchange="Binance")
- Get ETH 4h: cg_net_position(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_net_position, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch net position. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Open Interest Tools ====================
class OpenInterestTool(BaseTool):
"""
Get aggregate open interest across exchanges.
"""
@property
def name(self) -> str:
return "cg_open_interest"
@property
def description(self) -> str:
return """Get aggregate open interest across exchanges for a symbol.
Open interest = total outstanding derivative contracts.
Rising OI + rising price = new money entering (bullish)
Rising OI + falling price = new shorts opening (bearish)
Falling OI = positions closing (trend weakening)
Examples:
- Get BTC open interest: cg_open_interest(symbol="BTC")
- Get ETH open interest: cg_open_interest(symbol="ETH")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_open_interest, symbol)
if result is None:
return ToolResult(
success=False,
output=None,
error="Failed to fetch open interest. Check COINGLASS_API_KEY."
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Liquidation Tools ====================
class LiquidationsTool(BaseTool):
"""
Get recent liquidation data.
"""
@property
def name(self) -> str:
return "cg_liquidations"
@property
def description(self) -> str:
return """Get recent liquidation data across exchanges.
Liquidations = forced position closures due to insufficient margin.
More long liquidations = bearish pressure (longs being squeezed)
More short liquidations = bullish pressure (shorts being squeezed)
Examples:
- Get BTC liquidations (24h): cg_liquidations(symbol="BTC")
- Get ETH liquidations (4h): cg_liquidations(symbol="ETH", time_type="h4")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"time_type": {
"type": "string",
"description": "Time window: h1, h4, h12, h24",
"default": "h24"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
time_type: str = "h24"
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_liquidations, symbol, time_type)
if result is None:
return ToolResult(
success=False,
output=None,
error="Failed to fetch liquidations. Check COINGLASS_API_KEY."
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class LiquidationAnalysisTool(BaseTool):
"""
Get liquidation data with sentiment analysis.
"""
@property
def name(self) -> str:
return "cg_liquidation_analysis"
@property
def description(self) -> str:
return """Get liquidation data with market sentiment analysis.
Includes interpretation of liquidation imbalances.
Examples:
- Analyze BTC liquidations: cg_liquidation_analysis(symbol="BTC")
- Analyze ETH (4h): cg_liquidation_analysis(symbol="ETH", time_type="h4")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"time_type": {
"type": "string",
"description": "Time window: h1, h4, h12, h24",
"default": "h24"
}
},
"required": ["symbol"]
}
async def execute(
self,
ctx: ToolContext,
symbol: str,
time_type: str = "h24"
) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(
success=False,
output=None,
error="Coinglass tools not available."
)
try:
result = await asyncio.to_thread(get_liquidation_aggregated, symbol, time_type)
if result is None:
return ToolResult(
success=False,
output=None,
error="Failed to fetch liquidation analysis. Check COINGLASS_API_KEY."
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Advanced Liquidation Tools ====================
class CoinLiquidationHistoryTool(BaseTool):
"""Get aggregated liquidation history for a coin across all exchanges."""
@property
def name(self) -> str:
return "cg_coin_liquidation_history"
@property
def description(self) -> str:
return """Get aggregated liquidation history across all exchanges for a coin.
Shows total long/short liquidations over time, aggregated across all exchanges.
Examples:
- Get BTC liquidation history: cg_coin_liquidation_history(symbol="BTC", interval="1h", limit=100)
- Get ETH 4h intervals: cg_coin_liquidation_history(symbol="ETH", interval="4h", limit=50)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange_list": {"type": "string", "description": "Comma-separated exchange list (e.g. 'Binance,OKX,Bybit')"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in milliseconds"},
"end_time": {"type": "integer", "description": "End timestamp in milliseconds"}
},
"required": ["symbol", "exchange_list"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange_list: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_coin_liquidation_history, symbol, exchange_list, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch coin liquidation history. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class PairLiquidationHistoryTool(BaseTool):
"""Get liquidation history for a specific trading pair on an exchange."""
@property
def name(self) -> str:
return "cg_pair_liquidation_history"
@property
def description(self) -> str:
return """Get liquidation history for a specific pair on a specific exchange.
Shows long/short liquidations over time for exchange-specific pairs.
Examples:
- Get BTC/USDT on Binance: cg_pair_liquidation_history(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH/USDT on OKX: cg_pair_liquidation_history(symbol="ETH", exchange="OKX", interval="4h")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1h, 4h, 12h, 24h", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_pair_liquidation_history, symbol, exchange, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch pair liquidation history. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class LiquidationCoinListTool(BaseTool):
"""Get liquidation data for all coins on a specific exchange."""
@property
def name(self) -> str:
return "cg_liquidation_coin_list"
@property
def description(self) -> str:
return """Get liquidation data for all coins on a specific exchange.
Shows liquidation amounts across multiple timeframes (1h, 4h, 12h, 24h) for all coins on an exchange.
Examples:
- Get all Binance liquidations: cg_liquidation_coin_list(exchange="Binance")
- Get all OKX liquidations: cg_liquidation_coin_list(exchange="OKX")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"}
},
"required": ["exchange"]
}
async def execute(self, ctx: ToolContext, exchange: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_liquidation_coin_list, exchange)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch liquidation coin list. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class LiquidationOrdersTool(BaseTool):
"""Get individual liquidation orders (past 7 days)."""
@property
def name(self) -> str:
return "cg_liquidation_orders"
@property
def description(self) -> str:
return """Get individual liquidation orders with price, side, and USD value (past 7 days only).
Shows actual liquidation events. Max 200 records per request.
Examples:
- Get BTC liquidations on Binance (min $10K): cg_liquidation_orders(symbol="BTC", exchange="Binance", min_liquidation_amount="10000")
- Get ETH liquidations on OKX (min $5K): cg_liquidation_orders(symbol="ETH", exchange="OKX", min_liquidation_amount="5000")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"min_liquidation_amount": {"type": "string", "description": "Minimum threshold for liquidation events (USD)"},
"start_time": {"type": "integer", "description": "Start timestamp in milliseconds"},
"end_time": {"type": "integer", "description": "End timestamp in milliseconds"}
},
"required": ["symbol", "exchange", "min_liquidation_amount"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, min_liquidation_amount: str,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_liquidation_orders, symbol, exchange, min_liquidation_amount, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch liquidation orders. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Futures Market Data Tools (V4 API) ====================
class SupportedCoinsTool(BaseTool):
"""Get list of all supported coins for futures trading."""
@property
def name(self) -> str:
return "cg_supported_coins"
@property
def description(self) -> str:
return """Get list of all supported coins for futures trading on Coinglass.
Returns array of coin symbols (BTC, ETH, SOL, XRP, HYPE, DOGE, etc.)
Use this for:
- Market discovery
- Checking if a coin has futures markets
- Finding new trading opportunities
Examples:
- Get all supported coins: cg_supported_coins()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_supported_coins)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch supported coins. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class SupportedExchangesTool(BaseTool):
"""Get all supported exchanges with their trading pairs."""
@property
def name(self) -> str:
return "cg_supported_exchanges"
@property
def description(self) -> str:
return """Get all supported exchanges with trading pairs and specs.
Returns dictionary with exchange pairs including leverage limits, funding intervals, tick sizes.
Examples:
- Get all exchanges: cg_supported_exchanges()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_supported_exchanges)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch supported exchanges. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class CoinsMarketDataTool(BaseTool):
"""Get comprehensive market data for ALL coins in one request."""
@property
def name(self) -> str:
return "cg_coins_market_data"
@property
def description(self) -> str:
return """Get market data for ALL coins in ONE request.
Returns: price, funding rates, OI, volume, long/short ratios, liquidations for 100+ coins.
Use this for market screening and bulk analysis. MUCH more efficient than individual calls.
Examples:
- Get all coins data: cg_coins_market_data()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_coins_data)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch coins market data. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class PairMarketDataTool(BaseTool):
"""Get detailed market data for a specific trading pair."""
@property
def name(self) -> str:
return "cg_pair_market_data"
@property
def description(self) -> str:
return """Get detailed market data for a specific pair on an exchange.
Returns: price, volume, OI, funding rate, liquidations, long/short volumes.
Examples:
- Get BTC/USDT on Binance: cg_pair_market_data(symbol="BTC", exchange="Binance")
- Get ETH/USDT on OKX: cg_pair_market_data(symbol="ETH", exchange="OKX")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Coin symbol (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, Gate, etc.)"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_pair_data, symbol, exchange)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch pair market data. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class OHLCHistoryTool(BaseTool):
"""Get OHLC price history for a trading pair."""
@property
def name(self) -> str:
return "cg_ohlc_history"
@property
def description(self) -> str:
return """Get OHLC candlestick data for price analysis.
Returns array of candles with: timestamp, open, high, low, close.
Examples:
- Get BTC 1h candles: cg_ohlc_history(symbol="BTC", exchange="Binance", interval="h1", limit=100)
- Get ETH daily: cg_ohlc_history(symbol="ETH", exchange="OKX", interval="d1", limit=30)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Coin symbol (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: m1, m5, m15, m30, h1, h4, h12, d1", "default": "h1"},
"limit": {"type": "integer", "description": "Number of candles (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "h1", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_ohlc_history, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch OHLC history. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Hyperliquid Tools ====================
class HyperliquidWhaleAlertsTool(BaseTool):
"""Get recent whale alerts on Hyperliquid (positions > $1M)."""
@property
def name(self) -> str:
return "cg_hyperliquid_whale_alerts"
@property
def description(self) -> str:
return """Get recent whale alerts on Hyperliquid (positions > $1M).
Returns approximately 200 most recent large position opens/closes.
Examples:
- Get whale alerts: cg_hyperliquid_whale_alerts()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_whale_alerts)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch whale alerts. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class HyperliquidWhalePositionsTool(BaseTool):
"""Get current whale positions on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_whale_positions"
@property
def description(self) -> str:
return """Get current whale positions on Hyperliquid.
Shows large active positions with entry price, PnL, leverage, and margin data.
Examples:
- Get whale positions: cg_hyperliquid_whale_positions()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_whale_positions)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch whale positions. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class HyperliquidPositionsByCoinTool(BaseTool):
"""Get wallet positions organized by coin on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_positions_by_coin"
@property
def description(self) -> str:
return """Get real-time wallet positions for a specific coin on Hyperliquid.
Shows all open positions for the specified cryptocurrency.
Examples:
- Get BTC positions: cg_hyperliquid_positions_by_coin(symbol="BTC")
- Get ETH positions: cg_hyperliquid_positions_by_coin(symbol="ETH")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"}
},
"required": ["symbol"]
}
async def execute(self, ctx: ToolContext, symbol: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_positions_by_coin, symbol)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch positions by coin. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class HyperliquidUserPositionsTool(BaseTool):
"""Get positions for a specific user address on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_user_positions"
@property
def description(self) -> str:
return """Get positions for a specific user address on Hyperliquid.
Shows margin summaries, withdrawable balance, and open positions for the specified wallet.
Examples:
- Get user positions: cg_hyperliquid_user_positions(user_address="0x...")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_address": {"type": "string", "description": "Wallet address to query"}
},
"required": ["user_address"]
}
async def execute(self, ctx: ToolContext, user_address: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_user_positions, user_address)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch user positions. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class HyperliquidPositionDistributionTool(BaseTool):
"""Get wallet position distribution on Hyperliquid."""
@property
def name(self) -> str:
return "cg_hyperliquid_position_distribution"
@property
def description(self) -> str:
return """Get wallet position distribution on Hyperliquid.
Shows distribution by size tiers including address counts, long/short values, sentiment, and P/L distribution.
Examples:
- Get position distribution: cg_hyperliquid_position_distribution()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_position_distribution)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch position distribution. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Volume & Flow Tools ====================
class TakerVolumeHistoryTool(BaseTool):
"""Get taker buy/sell volume history for a specific trading pair."""
@property
def name(self) -> str:
return "cg_taker_volume_history"
@property
def description(self) -> str:
return """Get historical taker buy/sell volume data for a specific trading pair.
Taker volume = aggressive market orders (vs passive limit orders).
Higher taker buy volume = bullish pressure.
Higher taker sell volume = bearish pressure.
Examples:
- Get BTC taker volume on Binance: cg_taker_volume_history(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH 4h intervals: cg_taker_volume_history(symbol="ETH", exchange="OKX", interval="4h", limit=50)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_taker_volume_history, symbol, exchange, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch taker volume history. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class AggregatedTakerVolumeTool(BaseTool):
"""Get aggregated taker buy/sell volume across all exchanges."""
@property
def name(self) -> str:
return "cg_aggregated_taker_volume"
@property
def description(self) -> str:
return """Get aggregated taker buy/sell volume across all exchanges for a coin.
Shows total market pressure across all major exchanges.
More comprehensive than single-exchange data.
Examples:
- Get BTC aggregated volume: cg_aggregated_taker_volume(symbol="BTC", interval="1h")
- Get ETH 4h: cg_aggregated_taker_volume(symbol="ETH", interval="4h", limit=100)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange_list": {"type": "string", "description": "Comma-separated exchange list (e.g. 'Binance,OKX,Bybit')"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange_list"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange_list: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_aggregated_taker_volume, symbol, exchange_list, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch aggregated taker volume. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class CumulativeVolumeDeltaTool(BaseTool):
"""Get Cumulative Volume Delta (CVD) for trend analysis."""
@property
def name(self) -> str:
return "cg_cumulative_volume_delta"
@property
def description(self) -> str:
return """Get Cumulative Volume Delta (CVD) history for a trading pair.
CVD = Running total of (taker buy volume - taker sell volume).
Rising CVD = accumulation (bullish).
Falling CVD = distribution (bearish).
Divergences between price and CVD signal trend weakness.
Examples:
- Get BTC CVD on Binance: cg_cumulative_volume_delta(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH CVD: cg_cumulative_volume_delta(symbol="ETH", exchange="OKX", interval="4h", limit=100)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1m, 3m, 5m, 15m, 30m, 1h, 4h, 6h, 8h, 12h, 1d, 1w", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 1000, max: 4500)", "default": 1000},
"start_time": {"type": "integer", "description": "Start timestamp in seconds"},
"end_time": {"type": "integer", "description": "End timestamp in seconds"}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 1000,
start_time: Optional[int] = None, end_time: Optional[int] = None) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_cumulative_volume_delta, symbol, exchange, interval, limit, start_time, end_time)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch CVD. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class CoinNetflowTool(BaseTool):
"""Get netflow data for all futures coins."""
@property
def name(self) -> str:
return "cg_coin_netflow"
@property
def description(self) -> str:
return """Get coin netflow data for all futures coins.
Netflow = Capital flowing into/out of a coin across exchanges.
Positive netflow = accumulation (bullish signal).
Negative netflow = distribution (bearish signal).
Use for identifying which coins are seeing the strongest capital inflows.
Examples:
- Get all coin netflows: cg_coin_netflow()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_coin_netflow)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch coin netflow. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class VolumeOHLCTool(BaseTool):
"""Get volume OHLC history for a trading pair."""
@property
def name(self) -> str:
return "cg_volume_ohlc"
@property
def description(self) -> str:
return """Get trading volume OHLC (Open, High, Low, Close) history.
Shows volume patterns over time in candlestick format.
Useful for identifying volume spikes and trends.
Examples:
- Get BTC volume OHLC: cg_volume_ohlc(symbol="BTC", exchange="Binance", interval="1h")
- Get ETH daily volume: cg_volume_ohlc(symbol="ETH", exchange="OKX", interval="1d", limit=30)"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Trading coin (BTC, ETH, SOL, etc.)"},
"exchange": {"type": "string", "description": "Exchange name (Binance, OKX, Bybit, etc.)"},
"interval": {"type": "string", "description": "Time interval: 1h, 4h, 12h, 1d", "default": "1h"},
"limit": {"type": "integer", "description": "Number of results (default: 100)", "default": 100}
},
"required": ["symbol", "exchange"]
}
async def execute(self, ctx: ToolContext, symbol: str, exchange: str, interval: str = "1h", limit: int = 100) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_volume_ohlc_history, symbol, exchange, interval, limit)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch volume OHLC. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Whale Transfer Tools ====================
class WhaleTransferTool(BaseTool):
"""Get large on-chain transfers (minimum $10M) across major blockchains."""
@property
def name(self) -> str:
return "cg_whale_transfers"
@property
def description(self) -> str:
return """Get large on-chain whale transfers (minimum $10M) within the past 6 months.
Covers major blockchains: Bitcoin, Ethereum, Tron, Ripple, Dogecoin, Litecoin, Polygon, Algorand, Bitcoin Cash, Solana.
Shows transaction hash, asset, amount, exchanges involved, and transfer direction.
Useful for tracking institutional movements and market impact events.
Transfer types:
- 1 = Inflow (to exchange)
- 2 = Outflow (from exchange)
- 3 = Internal (between exchange wallets)
Examples:
- Get recent whale transfers: cg_whale_transfers()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_whale_transfers)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch whale transfers. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Bitcoin ETF Tools ====================
class BTCETFFlowsTool(BaseTool):
"""Get Bitcoin ETF flow history (inflows/outflows)."""
@property
def name(self) -> str:
return "cg_btc_etf_flows"
@property
def description(self) -> str:
return """Get Bitcoin ETF flow history including daily net inflows and outflows.
Shows institutional money movement into/out of Bitcoin through ETFs.
Large inflows = institutional accumulation (bullish).
Large outflows = institutional distribution (bearish).
Examples:
- Get BTC ETF flows: cg_btc_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch BTC ETF flows. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class BTCETFNetAssetsTool(BaseTool):
"""Get Bitcoin ETF net assets history."""
@property
def name(self) -> str:
return "cg_btc_etf_net_assets"
@property
def description(self) -> str:
return """Get Bitcoin ETF net assets history.
Shows total value held in Bitcoin ETFs over time and daily changes.
Rising net assets = growing institutional adoption.
Examples:
- Get BTC ETF net assets: cg_btc_etf_net_assets()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_net_assets)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch BTC ETF net assets. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class BTCETFPremiumDiscountTool(BaseTool):
"""Get Bitcoin ETF premium/discount rates."""
@property
def name(self) -> str:
return "cg_btc_etf_premium_discount"
@property
def description(self) -> str:
return """Get Bitcoin ETF premium/discount rates.
Shows how ETF market prices compare to their net asset value (NAV).
Premium (positive) = trading above NAV (high demand).
Discount (negative) = trading below NAV (low demand).
Examples:
- Get BTC ETF premium/discount: cg_btc_etf_premium_discount()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_premium_discount)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch BTC ETF premium/discount. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class BTCETFHistoryTool(BaseTool):
"""Get comprehensive Bitcoin ETF history."""
@property
def name(self) -> str:
return "cg_btc_etf_history"
@property
def description(self) -> str:
return """Get comprehensive Bitcoin ETF history.
Includes market price, NAV, premium/discount %, shares outstanding, and net assets.
Examples:
- Get IBIT history: cg_btc_etf_history(ticker="IBIT")
- Get FBTC history: cg_btc_etf_history(ticker="FBTC")"""
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"ticker": {"type": "string", "description": "ETF ticker symbol (e.g. IBIT, FBTC, GBTC)"}
},
"required": ["ticker"]
}
async def execute(self, ctx: ToolContext, ticker: str) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_history, ticker)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch BTC ETF history. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class BTCETFListTool(BaseTool):
"""Get list of Bitcoin ETFs."""
@property
def name(self) -> str:
return "cg_btc_etf_list"
@property
def description(self) -> str:
return """Get list of Bitcoin ETFs with key status information.
Returns ticker symbols, names, inception dates, and other ETF metadata.
Examples:
- Get BTC ETF list: cg_btc_etf_list()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_btc_etf_list)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch BTC ETF list. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class HKBTCETFFlowsTool(BaseTool):
"""Get Hong Kong Bitcoin ETF flow history."""
@property
def name(self) -> str:
return "cg_hk_btc_etf_flows"
@property
def description(self) -> str:
return """Get Hong Kong Bitcoin ETF flow history.
Shows ETF flow activity for Bitcoin ETFs in the Hong Kong market.
Useful for tracking Asian institutional demand.
Examples:
- Get HK BTC ETF flows: cg_hk_btc_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_hk_btc_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch HK BTC ETF flows. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Ethereum & Other ETF Tools ====================
class ETHETFFlowsTool(BaseTool):
"""Get Ethereum ETF flow history."""
@property
def name(self) -> str:
return "cg_eth_etf_flows"
@property
def description(self) -> str:
return """Get Ethereum ETF flow history including daily net inflows and outflows.
Shows institutional money movement into/out of Ethereum through ETFs.
Examples:
- Get ETH ETF flows: cg_eth_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_eth_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch ETH ETF flows. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class ETHETFListTool(BaseTool):
"""Get list of Ethereum ETFs."""
@property
def name(self) -> str:
return "cg_eth_etf_list"
@property
def description(self) -> str:
return """Get list of Ethereum ETFs with key status information.
Examples:
- Get ETH ETF list: cg_eth_etf_list()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_eth_etf_list)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch ETH ETF list. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class SOLETFFlowsTool(BaseTool):
"""Get Solana ETF flow history."""
@property
def name(self) -> str:
return "cg_sol_etf_flows"
@property
def description(self) -> str:
return """Get Solana ETF flow history including daily net inflows and outflows.
Examples:
- Get SOL ETF flows: cg_sol_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_sol_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch SOL ETF flows. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class XRPETFFlowsTool(BaseTool):
"""Get XRP ETF flow history."""
@property
def name(self) -> str:
return "cg_xrp_etf_flows"
@property
def description(self) -> str:
return """Get XRP ETF flow history including daily net inflows and outflows.
Examples:
- Get XRP ETF flows: cg_xrp_etf_flows()"""
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}, "required": []}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not COINGLASS_AVAILABLE:
return ToolResult(success=False, output=None, error="Coinglass tools not available.")
try:
result = await asyncio.to_thread(get_xrp_etf_flows)
if result is None:
return ToolResult(success=False, output=None, error="Failed to fetch XRP ETF flows. Check COINGLASS_API_KEY.")
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
exports.py
"""
Coinglass skill exports — script-mode skill.
Usage from a bash block:
python3 - <<'EOF'
import sys
sys.path.insert(0, "/data/workspace/skills/coinglass")
from exports import funding_rate, cg_open_interest
print(funding_rate(symbol="BTC"))
EOF
"""
import os, sys
# Add skill root to sys.path so `tools` works as a package
# (tools/*.py uses relative imports like `from ._api import cg_request`).
_SKILL_ROOT = os.path.dirname(os.path.abspath(__file__))
if _SKILL_ROOT not in sys.path:
sys.path.insert(0, _SKILL_ROOT)
# --- Funding Rate ---
from tools.funding_rate import get_symbol_funding_rate as funding_rate
# --- Long/Short ---
from tools.long_short_ratio import get_long_short_ratio as long_short_ratio
from tools.long_short_advanced import get_global_account_ratio as cg_global_account_ratio
from tools.long_short_advanced import get_top_account_ratio as cg_top_account_ratio
from tools.long_short_advanced import get_top_position_ratio as cg_top_position_ratio
from tools.long_short_advanced import get_taker_buysell_exchanges as cg_taker_exchanges
from tools.long_short_advanced import get_net_position as cg_net_position
# --- Open Interest ---
from tools.open_interest import get_open_interest as cg_open_interest
# --- Liquidations ---
from tools.liquidations import get_liquidations as cg_liquidations
from tools.liquidations import get_liquidation_aggregated as cg_liquidation_analysis
from tools.liquidations_advanced import get_coin_liquidation_history as cg_coin_liquidation_history
from tools.liquidations_advanced import get_pair_liquidation_history as cg_pair_liquidation_history
from tools.liquidations_advanced import get_liquidation_coin_list as cg_liquidation_coin_list
from tools.liquidations_advanced import get_liquidation_orders as cg_liquidation_orders
# --- Futures Market ---
from tools.futures_market import get_supported_coins as cg_supported_coins
from tools.futures_market import get_supported_exchanges as cg_supported_exchanges
from tools.futures_market import get_coins_data as cg_coins_market_data
from tools.futures_market import get_pair_data as cg_pair_market_data
from tools.futures_market import get_ohlc_history as cg_ohlc_history
# --- Hyperliquid ---
from tools.hyperliquid import get_whale_alerts as cg_hyperliquid_whale_alerts
from tools.hyperliquid import get_whale_positions as cg_hyperliquid_whale_positions
from tools.hyperliquid import get_positions_by_coin as cg_hyperliquid_positions_by_coin
from tools.hyperliquid import get_position_distribution as cg_hyperliquid_position_distribution
# --- Volume & Flow ---
from tools.volume_flow import get_taker_volume_history as cg_taker_volume_history
from tools.volume_flow import get_aggregated_taker_volume as cg_aggregated_taker_volume
from tools.volume_flow import get_cumulative_volume_delta as cg_cumulative_volume_delta
from tools.volume_flow import get_coin_netflow as cg_coin_netflow
# --- Whale Transfers ---
from tools.whale_transfer import get_whale_transfers as cg_whale_transfers
# --- BTC ETF ---
from tools.bitcoin_etf import get_btc_etf_flows as cg_btc_etf_flows
from tools.bitcoin_etf import get_btc_etf_premium_discount as cg_btc_etf_premium_discount
from tools.bitcoin_etf import get_btc_etf_history as cg_btc_etf_history
from tools.bitcoin_etf import get_btc_etf_list as cg_btc_etf_list
from tools.bitcoin_etf import get_hk_btc_etf_flows as cg_hk_btc_etf_flows
# --- Other ETFs ---
from tools.other_etfs import get_eth_etf_flows as cg_eth_etf_flows
from tools.other_etfs import get_eth_etf_list as cg_eth_etf_list
from tools.other_etfs import get_sol_etf_flows as cg_sol_etf_flows
from tools.other_etfs import get_xrp_etf_flows as cg_xrp_etf_flows
SKILL.md
---
name: coinglass
version: 3.0.4
description: |
Crypto derivatives data: funding rates, open interest, liquidations, long/short ratios.
Use when researching perp markets, tracking Hyperliquid whale positions, or comparing ETF flows (e.g. BTC funding, ETH OI, liquidation heatmap).
delivery: script
metadata:
starchild:
emoji: 📈
skillKey: coinglass
plan: professional
api_version: v4
version: 3.0.3
total_tools: 37
requires:
env:
- COINGLASS_API_KEY
user-invocable: false
disable-model-invocation: false
---
## Liquidation Heatmap(真正的价格区间清算压力)
`cg_liquidation_analysis` 返回全0,不可用。正确做法是直接调 API:
```python
from tools._api import cg_request
# 全市场聚合热力图(推荐,无需指定交易所)
# range 支持: 12h, 24h, 3d, 7d, 30d, 90d, 180d, 1y
data = cg_request("api/futures/liquidation/aggregated-heatmap/model1",
params={"symbol": "BTC", "range": "24h"})
# 返回结构:
# data["y_axis"] → 价格档位列表(从低到高)
# data["liquidation_leverage_data"] → [[y_idx, leverage, usd_value], ...]
# data["price_candlesticks"] → OHLCV K线,最后一根收盘价 = 当前价
# data["update_time"] → 更新时间戳
# 解析方法:
from collections import defaultdict
y_axis = data["y_axis"]
current_price = float(data["price_candlesticks"][-1][4])
price_liq = defaultdict(float)
for y_idx, leverage, usd_val in data["liquidation_leverage_data"]:
if 0 <= y_idx < len(y_axis):
price_liq[y_axis[y_idx]] += usd_val
longs = {p: v for p, v in price_liq.items() if p < current_price} # 多头清算(↓触发)
shorts = {p: v for p, v in price_liq.items() if p > current_price} # 空头清算(↑触发)
```
注意:单交易所版本(`heatmap/model1` 带 exchange 参数)当前会报 400 错误,改用 aggregated 版本。
## Script Usage
Script-mode skill — read this file, then invoke from a `bash` block:
```bash
python3 - <<'EOF'
import sys, json
sys.path.insert(0, "/data/workspace/skills/coinglass")
from exports import funding_rate, cg_open_interest, cg_liquidations
print(funding_rate(symbol="BTC"))
print(cg_open_interest(symbol="BTC"))
EOF
```
Read `exports.py` for the full list of available functions and exact
signatures. Common ones: `funding_rate`, `long_short_ratio`,
`cg_open_interest`, `cg_liquidations`, `cg_liquidation_analysis`,
`cg_global_account_ratio`, `cg_top_account_ratio`, `cg_top_position_ratio`,
`cg_taker_exchanges`, `cg_net_position`, `cg_supported_coins`,
`cg_supported_exchanges`, `cg_coins_market_data`, `cg_pair_market_data`,
`cg_ohlc_history`, `cg_hyperliquid_whale_alerts`,
`cg_hyperliquid_whale_positions`, `cg_taker_volume_history`,
`cg_aggregated_taker_volume`, `cg_cumulative_volume_delta`,
`cg_coin_netflow`, `cg_whale_transfers`, `cg_btc_etf_flows`,
`cg_eth_etf_flows`, `cg_sol_etf_flows`.
# Coinglass
Coinglass provides the most comprehensive crypto derivatives and institutional data available. 37 tools covering futures positioning, whale tracking, volume analysis, liquidations, and ETF flows.
**API Plan**: Professional ($699/month)
**Rate Limit**: 6000 requests/minute
**API Version**: V4 (with V2 backward compatibility)
**Total Tools**: 37 across 8 categories
## Function Reference (full signatures + return shapes)
All functions live in `exports.py`. Most return `Optional[List[Dict]]` or
`Optional[Dict]`. None means the upstream call failed or returned empty —
always check before indexing.
### ⚠️ Field naming convention (READ THIS FIRST)
CoinGlass v4 API uses **camelCase** for almost all data fields, with a few
legacy snake_case exceptions in liquidation endpoints. Don't assume
snake_case — `inspect` the dict before scripting.
- camelCase: `openInterest`, `volUsd`, `longRate`, `shortVolUsd`,
`exchangeName`, `nextFundingTime`, `fundingIntervalHours`,
`oichangePercent`, `h4OIChangePercent`, `avgFundingRateBySymbol`,
`tokenAmount`, `liquidationUsd` (in some endpoints)
- snake_case (legacy, only in `cg_liquidations`): `liquidation_usd`,
`longLiquidation_usd`, `shortLiquidation_usd`
- `rate` fields (funding) are STRINGS with "+" / "-" / "%" — parse with
`float(r.rstrip('%').lstrip('+'))` to compare numerically
- timestamps are millisecond unix epoch (e.g. `1777881600000`)
### Funding & Open Interest
| Function | Signature |
|---|---|
| `funding_rate(symbol, exchange=None)` | dict — keys: `symbol`, `exchange`, `rate` (str), `num_exchanges`, `exchanges_data` (list of {`exchangeName`, `rate`, `nextFundingTime`, `fundingIntervalHours`, `status`}) |
| `cg_open_interest(symbol='BTC', interval='0')` | LIST of dicts (one per exchange) — keys: `symbol`, `openInterest`, `volUsd`, `oichangePercent`, `h4OIChangePercent`, `h24VolChangePercent`, `volChangePercent7d`, `avgFundingRateBySymbol`, `exchangeName`, `exchangeLogo` |
### Long/Short Ratios
| Function | Signature |
|---|---|
| `long_short_ratio(symbol='BTC', interval='h4')` | LIST — top item is aggregated; `list` field inside has per-exchange breakdown. Keys: `longRate`, `shortRate`, `longVolUsd`, `shortVolUsd`, `totalVolUsd`, `list` |
| `cg_global_account_ratio(symbol='BTC', exchange='Binance', interval='1h')` | list of historical bars |
| `cg_top_account_ratio(symbol='BTC', exchange='Binance', interval='1h')` | list — top trader account-count ratio |
| `cg_top_position_ratio(symbol='BTC', exchange='Binance', interval='1h')` | list — top trader position-size ratio |
| `cg_taker_exchanges(symbol='BTC', range_type='4h')` | list — taker buy/sell across exchanges |
| `cg_net_position(symbol='BTC', exchange='Binance', interval='1h')` | list — net long-short USD over time |
### Liquidations
| Function | Signature |
|---|---|
| `cg_liquidations(symbol='BTC', time_type='h24')` | LIST of dicts (one per exchange + an `'All'` row first). Keys: `exchange`, `liquidation_usd`, `longLiquidation_usd`, `shortLiquidation_usd` (NOTE: snake_case legacy fields) |
| `cg_liquidation_analysis(symbol='BTC', time_type='h24')` | dict — aggregated network-wide stats |
| `cg_coin_liquidation_history(symbol='BTC', interval='h4')` | list — historical liq bars |
| `cg_pair_liquidation_history(symbol='BTC', exchange='Binance', interval='h4')` | list — historical liq for one pair on one exchange |
| `cg_liquidation_coin_list(symbol=None)` | list of all coins with liq summary |
| `cg_liquidation_orders(symbol='BTC', exchange=None)` | list — recent individual liq orders |
### Futures Market Data
| Function | Signature |
|---|---|
| `cg_supported_coins()` | List[str] — symbols supported by CoinGlass |
| `cg_supported_exchanges()` | list of exchange info dicts |
| `cg_coins_market_data(symbol=None)` | list — current snapshot for all coins (or one if symbol given) |
| `cg_pair_market_data(symbol='BTC', exchange=None)` | list — pair-level snapshot |
| `cg_ohlc_history(symbol='BTC', interval='h4', exchange=None)` | list of OHLCV bars |
### Hyperliquid Whale Tracking
| Function | Signature |
|---|---|
| `cg_hyperliquid_whale_alerts()` | list — recent large-position alerts |
| `cg_hyperliquid_whale_positions()` | list — current open whale positions |
| `cg_hyperliquid_positions_by_coin(symbol='BTC')` | list — whales holding a specific coin |
| `cg_hyperliquid_position_distribution(symbol='BTC')` | dict — long/short position-size distribution |
### Volume / Flow
| Function | Signature |
|---|---|
| `cg_taker_volume_history(symbol='BTC', exchange='Binance', interval='1h', limit=1000, start_time=None, end_time=None)` | list — taker buy/sell volume bars |
| `cg_aggregated_taker_volume(symbol='BTC', interval='h4')` | list — aggregated across all exchanges |
| `cg_cumulative_volume_delta(symbol='BTC', exchange='Binance', interval='1h', limit=1000, start_time=None, end_time=None)` | list — CVD bars |
| `cg_coin_netflow(symbol=None)` | list — net inflow/outflow per coin |
| `cg_whale_transfers()` | dict — recent on-chain large transfers |
### ETF Flows
| Function | Signature |
|---|---|
| `cg_btc_etf_flows()` | list — daily flows per US BTC ETF |
| `cg_btc_etf_history(etf_ticker=None)` | list — historical AUM/flows |
| `cg_btc_etf_list()` | list of BTC ETF tickers + AUM |
| `cg_btc_etf_premium_discount()` | list — premium/discount % vs NAV |
| `cg_hk_btc_etf_flows()` | list — Hong Kong BTC ETF flows |
| `cg_eth_etf_flows()` / `cg_eth_etf_list()` / `cg_eth_etf_premium_discount()` / `cg_hk_eth_etf_flows()` | ETH ETF equivalents |
| `cg_sol_etf_flows()` / `cg_sol_etf_list()` | SOL ETF data |
| `cg_xrp_etf_flows()` / `cg_xrp_etf_list()` | XRP ETF data |
### Sample responses (most-used functions)
`funding_rate(symbol="BTC")`:
```json
{
"symbol": "BTC",
"exchange": "average",
"rate": "-0.0016%",
"num_exchanges": 21,
"exchanges_data": [
{"exchangeName": "Binance", "rate": "+0.0050%",
"nextFundingTime": 1777881600000, "fundingIntervalHours": 8, "status": 1}
]
}
```
`cg_liquidations(symbol="BTC", time_type="h24")`:
```json
[
{"exchange": "All", "liquidation_usd": 170497688.16,
"longLiquidation_usd": 8179073.80, "shortLiquidation_usd": 162318614.36},
{"exchange": "Bybit", "liquidation_usd": 40454694.98, ...}
]
```
`cg_open_interest(symbol="BTC")`:
```json
[
{"symbol": "BTC", "openInterest": 61395303653.62, "volUsd": 56349328748.42,
"oichangePercent": 7.17, "h4OIChangePercent": 5.33,
"avgFundingRateBySymbol": -0.001874, "exchangeName": "Binance"}
]
```
`long_short_ratio(symbol="BTC", interval="h4")`:
```json
[{
"symbol": "BTC", "longRate": 53.65, "shortRate": 46.35,
"longVolUsd": 12558668895.91, "shortVolUsd": 10848776476.99,
"totalVolUsd": 23407445372.91,
"list": [
{"exchangeName": "Binance", "longRate": 55.75, "shortRate": 44.25, ...}
]
}]
```
## Tool Selection Guide
### Decision Tree
**Step 1: Is this about LIQUIDATIONS?**
```
Liquidation query?
├─ YES → How many coins?
│ ├─ ALL coins / ranking / 排行 / 汇总
│ │ └─ → cg_liquidation_coin_list ✅ (most liquidation queries land here)
│ ├─ ONE coin, need history over time
│ │ └─ → cg_coin_liquidation_history
│ ├─ ONE coin, specific orders (price/side/USD)
│ │ └─ → cg_liquidation_orders
│ └─ ONE coin, just a quick total + sentiment label
│ └─ → cg_liquidation_analysis (rarely needed; only if explicitly "simple summary")
```
**Step 2: Is this about LONG/SHORT RATIO?**
```
Long/short query?
├─ Historical time-series, trend over time, 多空比变化
│ └─ → cg_global_account_ratio (ALL accounts)
│ or cg_top_account_ratio (top traders only)
│ or cg_top_position_ratio (by position size)
└─ Current snapshot only (no history needed)
└─ → long_short_ratio
```
**Step 3: Is this about OPEN INTEREST?**
```
OI query?
└─ → cg_open_interest (always — do NOT use cg_coins_market_data for OI)
```
**Step 4: Is this a MARKET OVERVIEW / SENTIMENT query?**
```
Sentiment / 市场情绪 / pre-trade check?
└─ Use: funding_rate + long_short_ratio + cg_open_interest
DO NOT use cg_coins_market_data as a substitute for any of the above
```
---
### Keyword → Tool Lookup
| Keyword / Pattern | Correct Tool | ❌ Do NOT use |
|---|---|---|
| 爆仓排行 / 今日爆仓 / all coins liquidation | `cg_liquidation_coin_list` | `cg_liquidations` |
| 24h爆仓汇总 / liquidation summary | `cg_liquidation_coin_list` | `cg_liquidation_analysis` |
| 全网账户多空比 / account L/S ratio | `cg_global_account_ratio` | `long_short_ratio` |
| 头部交易者多空 / top trader ratio | `cg_top_account_ratio` | `long_short_ratio` |
| 未平仓合约 / open interest | `cg_open_interest` | `cg_coins_market_data` |
| 市场情绪多空分析 | `funding_rate` + `long_short_ratio` + `cg_open_interest` | `cg_coins_market_data` |
| BTC做多检查 / pre-trade checklist | `funding_rate` + `cg_global_account_ratio` + `cg_liquidation_coin_list` | — |
---
### Common Mistakes
**Mistake 1 (most common — 8x failure): Using `cg_liquidations` when you need `cg_liquidation_coin_list`**
- `cg_liquidations` → one coin, one timeframe, basic total only
- `cg_liquidation_coin_list(exchange)` → ALL coins, multi-timeframe (1h/4h/12h/24h), per-exchange breakdown
- **Rule:** If the question asks for a ranking, overview, or doesn't specify a single coin → use `cg_liquidation_coin_list`
**Mistake 2 (5x failure): Using `cg_liquidation_analysis` for liquidation rankings**
- `cg_liquidation_analysis` adds a sentiment label to a single-coin total — it is NOT a ranking tool
- **Rule:** "今日爆仓排行" / "各币种爆仓" → always `cg_liquidation_coin_list`
**Mistake 3 (3x failure): Using `long_short_ratio` for historical L/S analysis**
- `long_short_ratio` is a current snapshot (no time-series)
- `cg_global_account_ratio` returns history — use it when the user wants trends or comparison over time
- **Rule:** If the question compares 全网 (global) vs 头部 (top traders) → call BOTH `cg_global_account_ratio` AND `cg_top_account_ratio`
**Mistake 4 (2x failure): Using `cg_coins_market_data` for open interest**
- `cg_coins_market_data` is a bulk snapshot of many coins — not a replacement for dedicated OI or L/S tools
- **Rule:** OI question → `cg_open_interest`. L/S question → `long_short_ratio` or `cg_global_account_ratio`. Never route either to `cg_coins_market_data`.
## Rules
### Tool Call Guidance
**❌ FORBIDDEN TOOLS — NEVER USE:**
- `bash` — Do NOT write scripts to process/format data. Use natural language.
- `write_file` / `read_file` / `edit_file` — Do NOT save intermediate data. Answer directly.
- `learning_log` — ONLY for genuine skill bugs or persistent API errors. NOT for empty responses.
- `echo` — Do NOT use for debugging or output.
**✅ CORRECT PATTERN:**
- Tool returns data → Summarize in natural language → Done
- Tool returns empty/null → Report "no data available" → Done
- Need calculation (%, change, ratio) → Do mental math in reply
**Match tool count to question scope:**
- 单一指标问题("BTC 资金费率"、"ETH 多空比")→ 1 个工具,直接返回
- 多维度分析("做多是否合适"、"衍生品体检")→ 3-5 个工具,综合分析
- 对比问题("ETH vs SOL")→ 每个币种调相同工具,并列对比
- **避免重复调用同一工具。** 除非用户明确要求不同币种/交易所的对比。
### Learning Log Usage (CRITICAL)
**`learning_log` is FORBIDDEN for:**
- ❌ Empty API responses — just report "no data available"
- ❌ Tool returning None/null — handle gracefully
- ❌ Uncertainty about tool selection — check decision tree first
- ❌ Normal tool errors — retry once, then report failure
**`learning_log` is ONLY for:**
- ✅ Genuine bugs in skill code (wrong data format returned)
- ✅ Persistent API rate limit errors after 2+ retries
- ✅ Missing tools that should exist per skill definition
### ETF Tool Selection
| Query | Primary Tool | Secondary Tool |
|-------|--------------|----------------|
| BTC ETF 资金流入/流出 | `cg_btc_etf_flows()` | `cg_btc_etf_history()` for detailed history |
| ETH ETF 资金流入/流出 | `cg_eth_etf_flows()` | — |
| SOL/XRP ETF flows | `cg_sol_etf_flows()` / `cg_xrp_etf_flows()` | — |
| HK ETF flows | `cg_hk_btc_etf_flows()` / `cg_hk_eth_etf_flows()` | — |
| ETF 列表/代码 | `cg_btc_etf_list()` / `cg_eth_etf_list()` | — |
| ETF 溢价/折价 | `cg_btc_etf_premium_discount()` | — |
**ETF 对比问题 workflow:**
```
# BTC vs ETH ETF 对比
btc = cg_btc_etf_flows()
eth = cg_eth_etf_flows()
# Compare the latest day's net flows, summarize in 2-3 sentences
```
## Quick Routing (use this first)
| Query type | Tool |
|---|---|
| 爆仓/liquidation summary (24h, by coin) | `cg_liquidation_coin_list` |
| Individual liquidation orders | `cg_liquidation_orders` |
| Liquidation history for a coin | `cg_coin_liquidation_history` |
| Funding rate | `funding_rate` |
| Long/short ratio (global) | `cg_global_account_ratio` |
| Open interest | `cg_open_interest` |
| Whale activity on Hyperliquid | `cg_hyperliquid_whale_alerts` |
| ETF flows (BTC) | `cg_btc_etf_flows` |
## When to Use Coinglass
Use Coinglass for:
- **Derivatives positioning** - What are leveraged traders doing?
- **Whale tracking** - Track large positions on Hyperliquid DEX
- **Funding rates** - Cost of holding perpetual futures
- **Open interest** - Total notional value of open positions
- **Long/Short ratios** - Sentiment among leveraged traders (global, top accounts, top positions)
- **Liquidations** - Forced position closures with heatmaps and individual orders
- **Volume analysis** - Taker volume, CVD, netflow patterns
- **ETF flows** - Institutional adoption (Bitcoin, Ethereum, Solana, XRP, Hong Kong)
- **Whale transfers** - Large on-chain movements (>$10M)
- **Futures market data** - Supported coins, exchanges, pairs, and OHLC price history
## Tool Categories
### 1. Basic Derivatives Analytics (7 tools)
Core derivatives data for market analysis:
- `funding_rate(symbol, exchange?)` - Current funding rates
- `long_short_ratio(symbol, exchange?, interval?)` - Basic L/S ratios
- `cg_open_interest(symbol)` - Current OI across exchanges
- `cg_liquidations(symbol, time?)` - Recent liquidations
- `cg_liquidation_analysis(symbol)` - Liquidation heatmap analysis
- `cg_supported_coins()` - All supported coins
- `cg_supported_exchanges()` - All exchanges with pairs
### 2. Advanced Long/Short Ratios (6 tools)
Deep positioning analysis with multiple metrics:
- `cg_global_account_ratio(symbol, interval?)` - Global account-based L/S ratio
- `cg_top_account_ratio(symbol, exchange, interval?)` - Top trader accounts ratio
- `cg_top_position_ratio(symbol, exchange, interval?)` - Top positions by size
- `cg_taker_exchanges(symbol)` - Taker buy/sell by exchange
- `cg_net_position(symbol, exchange)` - Net long/short positions
- `cg_net_position_v2(symbol)` - Enhanced net position data
**Use cases**:
- Smart money tracking (top accounts vs retail)
- Exchange-specific sentiment
- Position size distribution analysis
### 3. Advanced Liquidations (4 tools)
Granular liquidation tracking for cascade prediction:
- `cg_coin_liquidation_history(symbol, interval?, limit?, start_time?, end_time?)` - Aggregated across all exchanges
- `cg_pair_liquidation_history(symbol, exchange, interval?, limit?, start_time?, end_time?)` - Exchange-specific pair
- `cg_liquidation_coin_list(exchange)` - All coins on an exchange
- `cg_liquidation_orders(symbol, exchange, min_liquidation_amount, start_time?, end_time?)` - Individual orders (past 7 days, max 200)
**Use cases**:
- Identifying liquidation clusters
- Tracking liquidation patterns over time
- Finding large liquidation events
### 4. Hyperliquid Whale Tracking (4 tools)
Track large traders on Hyperliquid DEX (~200 recent alerts):
- `cg_hyperliquid_whale_alerts()` - Recent large position opens/closes (>$1M)
- `cg_hyperliquid_whale_positions()` - Current whale positions with PnL
- `cg_hyperliquid_positions_by_coin()` - All positions grouped by coin
- `cg_hyperliquid_position_distribution()` - Distribution by size with sentiment
**Use cases**:
- Following smart money on Hyperliquid
- Detecting large position changes
- Tracking whale PnL and sentiment
### 5. Futures Market Data (5 tools)
Market overview and price data:
- `cg_coins_market_data()` - ALL coins data in one call (100+ coins)
- `cg_pair_market_data(symbol, exchange)` - Specific pair metrics
- `cg_ohlc_history(symbol, exchange, interval, limit?)` - OHLC candlesticks
- `cg_taker_volume_history(symbol, exchange, interval, limit?, start_time?, end_time?)` - Pair-specific taker volume
- `cg_aggregated_taker_volume(symbol, interval, limit?, start_time?, end_time?)` - Aggregated across exchanges
**Use cases**:
- Market screening (scan all coins at once)
- Price action analysis
- Volume pattern recognition
### 6. Volume & Flow Analysis (4 tools)
Order flow and capital movement tracking:
- `cg_cumulative_volume_delta(symbol, exchange, interval, limit?, start_time?, end_time?)` - CVD = Running total of (buy - sell)
- `cg_coin_netflow()` - Capital flowing into/out of coins
- `cg_whale_transfers()` - Large on-chain transfers (>$10M, past 6 months)
**Use cases**:
- Order flow divergence detection
- Smart money tracking
- Institutional movement monitoring
### 7. Bitcoin ETF Data (5 tools)
Track institutional Bitcoin adoption:
- `cg_btc_etf_flows()` - Daily net inflows/outflows
- `cg_btc_etf_premium_discount()` - ETF price vs NAV
- `cg_btc_etf_history()` - Comprehensive history (price, NAV, premium%, shares, assets)
- `cg_btc_etf_list()` - List of Bitcoin ETFs
- `cg_hk_btc_etf_flows()` - Hong Kong Bitcoin ETF flows
**Use cases**:
- Institutional demand tracking
- Premium/discount arbitrage
- Regional flow comparison (US vs Hong Kong)
### 8. Other ETF Data (8 tools)
Ethereum, Solana, XRP, and Hong Kong ETFs:
- `cg_eth_etf_flows()` - Ethereum ETF flows
- `cg_eth_etf_list()` - Ethereum ETF list
- `cg_eth_etf_premium_discount()` - ETH ETF premium/discount
- `cg_sol_etf_flows()` - Solana ETF flows
- `cg_sol_etf_list()` - Solana ETF list
- `cg_xrp_etf_flows()` - XRP ETF flows
- `cg_xrp_etf_list()` - XRP ETF list
- `cg_hk_eth_etf_flows()` - Hong Kong Ethereum ETF flows
**Use cases**:
- Multi-asset institutional tracking
- Comparative flow analysis
- Regional preference analysis
## Common Workflows
### Quick Market Scan
```
# Get everything in 3 calls
all_coins = cg_coins_market_data() # 100+ coins with full metrics
btc_liquidations = cg_liquidations("BTC")
whale_alerts = cg_hyperliquid_whale_alerts()
```
### Deep Position Analysis
```
# BTC positioning across metrics
cg_global_account_ratio("BTC") # Retail sentiment
cg_top_account_ratio("BTC", "Binance") # Smart money
cg_net_position_v2("BTC") # Net positioning
cg_liquidation_heatmap("BTC", "Binance") # Cascade levels
```
### ETF Flow Monitoring
```
# Institutional demand
btc_flows = cg_btc_etf_flows()
eth_flows = cg_eth_etf_flows()
sol_flows = cg_sol_etf_flows()
```
### Whale Tracking
```
# Follow the whales
hyperliquid_whales = cg_hyperliquid_whale_alerts()
whale_positions = cg_hyperliquid_whale_positions()
onchain_whales = cg_whale_transfers() # >$10M on-chain
```
### Volume Analysis
```
# Order flow
cvd = cg_cumulative_volume_delta("BTC", "Binance", "1h", 100)
netflow = cg_coin_netflow() # All coins
taker_vol = cg_aggregated_taker_volume("BTC", "1h", 100)
```
## Interpretation Guides
### Funding Rates
| Rate (8h) | Read |
|------------|------|
| > +0.05% | Extreme greed — crowded long, squeeze risk |
| +0.01% to +0.05% | Bullish bias, normal |
| -0.005% to +0.01% | Neutral |
| -0.05% to -0.005% | Bearish bias, normal |
| < -0.05% | Extreme fear — crowded short, bounce risk |
Extreme funding often precedes reversals. The crowd is usually wrong at extremes.
### Open Interest + Price Matrix
| OI | Price | Read |
|----|-------|------|
| Up | Up | New longs entering — bullish conviction |
| Up | Down | New shorts entering — bearish conviction |
| Down | Up | Short covering — weaker rally, less conviction |
| Down | Down | Long liquidation — weaker selloff, capitulation |
### Long/Short Ratio
| Ratio | Read |
|-------|------|
| > 1.5 | Crowded long — contrarian bearish |
| 1.1–1.5 | Moderately bullish |
| 0.9–1.1 | Balanced |
| 0.7–0.9 | Moderately bearish |
| < 0.7 | Crowded short — contrarian bullish |
### CVD (Cumulative Volume Delta)
| Pattern | Read |
|---------|------|
| CVD rising, price rising | Strong buy pressure, healthy uptrend |
| CVD falling, price rising | Weak rally, distribution |
| CVD rising, price falling | Accumulation, potential bottom |
| CVD falling, price falling | Strong sell pressure, healthy downtrend |
### ETF Flows
| Flow | Read |
|------|------|
| Large inflows | Institutional buying, bullish |
| Consistent inflows | Sustained demand |
| Large outflows | Institutional selling, bearish |
| Premium to NAV | High demand, bullish sentiment |
| Discount to NAV | Weak demand, bearish sentiment |
## Analysis Patterns
**Multi-metric confirmation**: Combine tools across categories for high-confidence signals:
- Funding + L/S ratio + liquidations = positioning extremes
- CVD + taker volume + whale alerts = smart money direction
- ETF flows + whale transfers + open interest = institutional conviction
**Smart money vs retail**: Compare metrics to identify divergence:
- `cg_top_account_ratio` (smart money) vs `cg_global_account_ratio` (retail)
- Hyperliquid whale positions vs overall long/short ratios
**Cascade prediction**: Use liquidation tools to predict volatility:
- `cg_coin_liquidation_history` shows liquidation patterns over time
- `cg_liquidation_orders` reveals recent forced closures
- Large liquidation events = cascade risk zones
**Flow divergence**: Track capital movements:
- `cg_coin_netflow` shows where money is flowing
- `cg_whale_transfers` reveals large movements
- ETF flows show institutional demand
## Performance Optimization
### Batch vs Individual Calls
**✅ OPTIMAL**: Use batch endpoints
```
# One call gets 100+ coins
all_coins = cg_coins_market_data()
# One call gets all whale alerts
whales = cg_hyperliquid_whale_alerts()
# One call gets all ETF flows
btc_etf = cg_btc_etf_flows()
```
**❌ INEFFICIENT**: Multiple individual calls
```
# Don't do this - wastes API quota
btc = cg_pair_market_data("BTC", "Binance")
eth = cg_pair_market_data("ETH", "Binance")
sol = cg_pair_market_data("SOL", "Binance")
```
### Query Parameters
Most history endpoints support:
- `interval`: Time granularity (1h, 4h, 12h, 24h, etc.)
- `limit`: Number of records (default varies, max 1000)
- `start_time`: Unix timestamp (milliseconds)
- `end_time`: Unix timestamp (milliseconds)
Example:
```
cg_coin_liquidation_history(
symbol="BTC",
interval="1h",
limit=100,
start_time=1704067200000, # 2024-01-01
end_time=1704153600000 # 2024-01-02
)
```
## Supported Exchanges
Major exchanges with futures data:
- **Tier 1**: Binance, OKX, Bybit, Gate, KuCoin, MEXC
- **Traditional**: CME (Bitcoin and Ethereum futures), Coinbase
- **DEX**: Hyperliquid, dYdX, ApeX
- **Others**: Bitfinex, Kraken, HTX, BingX, Crypto.com, CoinEx, Bitget
Use `cg_supported_exchanges()` for complete list with pair details.
## Important Notes
- **API Key**: Requires COINGLASS_API_KEY environment variable
- **Symbols**: Use standard symbols (BTC, ETH, SOL, etc.) - check with `cg_supported_coins()`
- **Exchanges**: Check `cg_supported_exchanges()` for full list with pairs
- **Update Frequency**:
- Market data: ≤ 1 minute
- Funding rates: Every 8 hours (or 1 hour for some exchanges)
- OHLC: Real-time to 1 minute depending on interval
- ETF data: Daily (after market close)
- Whale transfers: Real-time (within minutes)
- **API Versions**:
- V4 endpoints use `CG-API-KEY` header (most tools)
- V2 endpoints use `coinglassSecret` header (some legacy tools)
- Both work with the same COINGLASS_API_KEY environment variable
- **Rate Limits**: Professional plan allows 6000 requests/minute
- **Historical Data Limits**:
- Liquidation orders: Past 7 days, max 200 records
- Whale transfers: Past 6 months, minimum $10M
- Hyperliquid alerts: ~200 most recent large positions
- Other endpoints: Typically months to years of history
## Data Quality Notes
- **Hyperliquid**: Data is exchange-specific, doesn't include other DEXs
- **Whale Transfers**: Covers Bitcoin, Ethereum, Tron, Ripple, Dogecoin, Litecoin, Polygon, Algorand, Bitcoin Cash, Solana
- **ETF Data**: US ETFs updated after market close (4 PM ET), Hong Kong ETFs updated after Hong Kong market close
- **Liquidation Orders**: Limited to 200 most recent, use heatmap for broader view
- **CVD**: Cumulative metric - resets are not automatic, track changes not absolute values
## Version History
- **v3.0.0** (2025-03): Added 36 new tools
- Advanced liquidations (5 tools)
- Hyperliquid whale tracking (5 tools)
- Volume & flow analysis (5 tools)
- Whale transfers (1 tool)
- Bitcoin ETF (6 tools)
- Other ETFs (8 tools)
- Advanced L/S ratios (6 tools)
- **v2.2.0** (2024): V4 API migration with futures market data
- **v1.0.0** (2024): Initial release with basic derivatives data
tools/__init__.py
"""
Coinglass Tools Module
Provides access to Coinglass cryptocurrency derivatives data including
funding rates and long/short account ratios across major exchanges.
Usage:
from tools.coinglass import get_funding_rates, get_long_short_ratio
# Get BTC funding rates
rates = get_funding_rates("BTC")
# Get BTC long/short ratio
ratio = get_long_short_ratio("BTC", "h1")
Environment Variables Required:
- COINGLASS_API_KEY: Your Coinglass API key
"""
from .funding_rate import (
get_funding_rates,
get_symbol_funding_rate,
get_funding_rate_by_exchange,
analyze_funding_opportunity
)
from .long_short_ratio import (
get_long_short_ratio,
get_exchange_ratio,
get_sentiment,
compare_exchanges
)
__all__ = [
# Funding Rate functions
"get_funding_rates",
"get_symbol_funding_rate",
"get_funding_rate_by_exchange",
"analyze_funding_opportunity",
# Long/Short Ratio functions
"get_long_short_ratio",
"get_exchange_ratio",
"get_sentiment",
"compare_exchanges"
]
tools/_api.py
"""
Shared Coinglass API helper — eliminates return-None error pattern.
Every tools/*.py file repeated the same boilerplate:
1. _get_api_key() → return None if missing
2. proxied_get(url, headers, timeout) → return None on any error
3. check response code → return None if not "0"
This module centralizes that into one `cg_request()` function that:
- Raises typed exceptions instead of returning None
- Provides actionable error messages for each failure mode
- Distinguishes API key errors, rate limits, server errors, parse errors
"""
import os
import json
import requests
try:
from core.http_client import proxied_get
except ImportError:
# Fallback for testing outside platform — use plain requests
def proxied_get(url, params=None, headers=None, timeout=30,
**kwargs):
return requests.get(
url, params=params, headers=headers, timeout=timeout,
**kwargs
)
# ── Coinglass-specific exceptions ───────────────────────────
class CoinglassError(Exception):
"""Base exception for all Coinglass API errors."""
def __init__(self, message, code="UNKNOWN", suggestion=""):
self.code = code
self.suggestion = suggestion
super().__init__(message)
class CoinglassAPIKeyError(CoinglassError):
"""API key missing or invalid."""
pass
class CoinglassRateLimitError(CoinglassError):
"""Rate limited by Coinglass."""
pass
class CoinglassServerError(CoinglassError):
"""Coinglass server returned 5xx."""
pass
# ── API configuration ──────────────────────────────────────
BASE_URL_V2 = "https://open-api.coinglass.com/public/v2"
BASE_URL_V4 = "https://open-api-v4.coinglass.com"
HEADER_KEY_V2 = "coinglassSecret"
HEADER_KEY_V4 = "CG-API-KEY"
def _get_api_key():
"""Get API key from environment."""
return os.getenv("COINGLASS_API_KEY")
def _suggestion_for_status(status):
"""Map HTTP status to actionable suggestion."""
suggestions = {
401: "API key invalid or expired. Check COINGLASS_API_KEY.",
403: "Access denied. This endpoint may require a paid plan.",
404: "Endpoint not found. The API version may have changed.",
429: "Rate limited. Wait 60 seconds before retrying.",
500: "Coinglass server error. Retry in 1-2 minutes.",
502: "Coinglass gateway error. Retry in 1-2 minutes.",
503: "Coinglass service unavailable. Retry in 1-2 minutes.",
}
return suggestions.get(status, f"HTTP {status} error.")
def cg_request(endpoint, params=None, version="v4", timeout=30):
"""
Make a Coinglass API request with structured error handling.
Args:
endpoint: API path (e.g. "api/futures/supported-coins"
or "funding" for v2)
params: Query parameters dict
version: "v2" or "v4" (default "v4")
timeout: Request timeout in seconds
Returns:
Parsed response data (the "data" field from Coinglass response).
Raises:
CoinglassAPIKeyError: API key missing or rejected
CoinglassRateLimitError: 429 rate limit
CoinglassServerError: 5xx server error
CoinglassError: Any other API error
"""
api_key = _get_api_key()
if not api_key:
raise CoinglassAPIKeyError(
"COINGLASS_API_KEY not set in environment",
code="NO_API_KEY",
suggestion="Set COINGLASS_API_KEY in your .env file."
)
if version == "v2":
base_url = BASE_URL_V2
headers = {"accept": "application/json", HEADER_KEY_V2: api_key}
else:
base_url = BASE_URL_V4
headers = {"accept": "application/json", HEADER_KEY_V4: api_key}
url = f"{base_url}/{endpoint}"
try:
response = proxied_get(
url, params=params, headers=headers, timeout=timeout
)
response.raise_for_status()
except requests.exceptions.HTTPError as e:
status = getattr(e.response, "status_code", None)
suggestion = _suggestion_for_status(status)
if status == 401:
raise CoinglassAPIKeyError(
f"HTTP 401 from Coinglass: {e}", code="HTTP_401",
suggestion=suggestion
) from e
if status == 429:
raise CoinglassRateLimitError(
f"Rate limited by Coinglass: {e}", code="HTTP_429",
suggestion=suggestion
) from e
if status and status >= 500:
raise CoinglassServerError(
f"Coinglass server error: {e}", code=f"HTTP_{status}",
suggestion=suggestion
) from e
raise CoinglassError(
f"HTTP {status} from Coinglass: {e}",
code=f"HTTP_{status}", suggestion=suggestion
) from e
except requests.exceptions.ConnectionError as e:
raise CoinglassError(
f"Cannot connect to Coinglass: {e}",
code="CONNECTION_ERROR",
suggestion="Check network. Retry in 30 seconds."
) from e
except requests.exceptions.Timeout as e:
raise CoinglassError(
f"Coinglass request timed out after {timeout}s",
code="TIMEOUT",
suggestion="Retry with a longer timeout or simpler query."
) from e
except requests.exceptions.RequestException as e:
raise CoinglassError(
f"Request failed: {type(e).__name__}: {e}",
code="REQUEST_ERROR",
suggestion="Unexpected network error. Retry."
) from e
# Parse JSON
try:
data = response.json()
except (json.JSONDecodeError, ValueError) as e:
raise CoinglassError(
f"Invalid JSON from Coinglass: {e}",
code="PARSE_ERROR",
suggestion="API may be returning an error page. Try again later."
) from e
# Check Coinglass response code
if isinstance(data, dict):
code = data.get("code")
if code is not None and str(code) != "0":
msg = data.get("msg", "Unknown API error")
raise CoinglassError(
f"Coinglass API error [{code}]: {msg}",
code=f"API_{code}",
suggestion="Check parameters. Some endpoints "
"require specific symbols or exchanges."
)
# Unwrap standard response envelope
if "data" in data:
return data["data"]
return data
tools/bitcoin_etf.py
#!/usr/bin/env python3
"""
Coinglass Bitcoin ETF Module
Provides Bitcoin ETF data including flows, net assets,
premium/discount, history, and Hong Kong ETF data.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
from ._api import cg_request
def get_btc_etf_flows() -> Optional[List[Dict[str, Any]]]:
"""Get Bitcoin ETF flow history (inflows/outflows by fund)."""
return cg_request("api/etf/bitcoin/flow-history")
def get_btc_etf_net_assets() -> Optional[List[Dict[str, Any]]]:
"""Get Bitcoin ETF net assets history."""
return cg_request("api/reference/bitcoin-etf-netassets-history")
def get_btc_etf_premium_discount() -> Optional[List[Dict[str, Any]]]:
"""Get Bitcoin ETF premium/discount rate history."""
return cg_request("api/etf/bitcoin/premium-discount/history")
def get_btc_etf_history(
etf_ticker: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get comprehensive Bitcoin ETF history.
Args:
etf_ticker: Filter by specific ETF ticker (e.g. "GBTC", "IBIT").
"""
params = {}
if etf_ticker:
params["ticker"] = etf_ticker
return cg_request("api/etf/bitcoin/history", params=params or None)
def get_btc_etf_list() -> Optional[List[Dict[str, Any]]]:
"""Get list of all Bitcoin ETFs with details."""
return cg_request("api/etf/bitcoin/list")
def get_hk_btc_etf_flows() -> Optional[List[Dict[str, Any]]]:
"""Get Hong Kong Bitcoin ETF flow history."""
return cg_request("api/hk-etf/bitcoin/flow-history")
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(description="Coinglass BTC ETF Tools")
parser.add_argument("action", choices=[
"flows", "assets", "premium", "history", "list", "hk-flows"
])
parser.add_argument("--ticker", help="ETF ticker filter")
parser.add_argument("--json", "-j", action="store_true")
args = parser.parse_args()
actions = {
"flows": get_btc_etf_flows,
"assets": get_btc_etf_net_assets,
"premium": get_btc_etf_premium_discount,
"history": lambda: get_btc_etf_history(args.ticker),
"list": get_btc_etf_list,
"hk-flows": get_hk_btc_etf_flows,
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/funding_rate.py
#!/usr/bin/env python3
"""
Coinglass Funding Rate Module
Fetch funding rates across major cryptocurrency exchanges including
Binance, OKX, Bybit, KuCoin, MEXC, Bitfinex, Kraken, and more.
Funding rates are fees set by cryptocurrency exchanges to maintain balance
between contract price and underlying asset price in perpetual futures contracts.
Positive rates mean longs pay shorts; negative rates mean shorts pay longs.
Dependencies:
- requests: For HTTP API calls
- python-dotenv: For environment variable management
Environment Variables Required:
- COINGLASS_API_KEY: Your Coinglass API key
Usage Example:
from tools.coinglass.funding_rate import get_funding_rates, get_symbol_funding_rate
# Get all funding rates for BTC
rates = get_funding_rates(symbol="BTC")
# Get funding rate for specific exchange
binance_rate = get_symbol_funding_rate(symbol="BTC", exchange="Binance")
CLI Usage:
python funding_rate.py --symbol BTC
python funding_rate.py --symbol ETH --exchange Binance
python funding_rate.py --all
"""
import os
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
try:
from dotenv import load_dotenv
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../..'))
load_dotenv(os.path.join(project_root, '.env'))
except ImportError:
pass
import requests
from core.http_client import proxied_get
def _fmt_rate(val):
"""Format a funding rate value as a display string with % sign.
Coinglass returns values already in percent (0.01 means 0.01%), so NO multiplication."""
if val is None:
return None
sign = "+" if val >= 0 else ""
return f"{sign}{val:.4f}%"
def _with_rate_unit(obj: dict, field: str):
"""Normalize any funding-rate field to a display-safe percent string."""
if field not in obj or obj.get(field) is None:
return
obj[field] = _fmt_rate(_rate_num(obj, field, 0.0))
def _rate_num(obj: dict, field: str, default: float = 0.0) -> float:
"""Read numeric funding rate safely from number or percent-string values."""
v = obj.get(field)
if isinstance(v, (int, float)):
return float(v)
if isinstance(v, str):
s = v.strip()
if s.endswith('%'):
s = s[:-1]
try:
return float(s)
except ValueError:
return default
return default
# Coinglass Configuration
BASE_URL = "https://open-api.coinglass.com/public/v2"
HEADER_KEY = "coinglassSecret"
# Supported exchanges
EXCHANGES = [
"Binance", "OKX", "Bybit", "KuCoin", "MEXC", "CoinEx",
"Bitfinex", "Kraken", "dYdX", "Gate", "Bitmex"
]
# Common symbols
SYMBOLS = ["BTC", "ETH", "SOL", "BNB", "XRP", "DOGE", "ADA", "AVAX", "LINK", "MATIC"]
def _get_api_key() -> Optional[str]:
"""Get Coinglass API key from environment."""
return os.getenv("COINGLASS_API_KEY")
def get_funding_rates(symbol: Optional[str] = None) -> Optional[Dict[str, Any]]:
"""
Fetch funding rates across all exchanges.
Args:
symbol: Optional symbol filter (BTC, ETH, etc.). If None, returns all.
Returns:
Dictionary with funding rate data:
{
"symbol": "BTC",
"uMarginList": [
{
"exchangeName": "Binance",
"rate": 0.0058, # Funding rate already in % (i.e. 0.0058%)
"nextFundingTime": 1765497600000, # Unix ms
"fundingIntervalHours": 8
},
...
]
}
Returns None if request fails.
Example:
rates = get_funding_rates("BTC")
for exchange in rates["data"]:
if exchange["symbol"] == "BTC":
for rate_info in exchange["uMarginList"]:
print(f"{rate_info['exchangeName']}: {rate_info['rate']:.4f}%")
"""
api_key = _get_api_key()
if not api_key:
print("Error: COINGLASS_API_KEY not found in environment", file=sys.stderr)
return None
url = f"{BASE_URL}/funding"
headers = {
"accept": "application/json",
HEADER_KEY: api_key
}
try:
response = proxied_get(url, headers=headers, timeout=30)
response.raise_for_status()
data = response.json()
if data.get("code") != "0":
print(f"API Error: {data.get('msg', 'Unknown error')}", file=sys.stderr)
return None
# Normalize all funding-rate fields to strings with `%` suffix.
for symbol_entry in data.get("data", []):
for margin_list_key in ("uMarginList", "cMarginList"):
for ex in symbol_entry.get(margin_list_key, []):
_with_rate_unit(ex, "rate")
_with_rate_unit(ex, "predictedRate")
if symbol:
# Filter for specific symbol
filtered = [d for d in data.get("data", []) if d.get("symbol", "").upper() == symbol.upper()]
return {"code": "0", "msg": "success", "data": filtered}
return data
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}", file=sys.stderr)
return None
except json.JSONDecodeError as e:
print(f"Failed to parse response: {e}", file=sys.stderr)
return None
def get_symbol_funding_rate(
symbol: str,
exchange: Optional[str] = None
) -> Optional[Dict[str, Any]]:
"""
Get funding rate for a specific symbol and optionally a specific exchange.
Args:
symbol: Symbol to query (BTC, ETH, etc.)
exchange: Optional exchange name (Binance, OKX, Bybit, etc.)
Returns:
Dictionary with funding rate info:
{
"symbol": "BTC",
"exchange": "Binance", # or "average" if no exchange specified
"rate": "+0.0058%",
"next_funding_time": 1765497600000,
"funding_interval_hours": 8,
"predicted_rate": "+0.0059%" # if available
}
Returns None if not found.
Example:
rate = get_symbol_funding_rate("BTC", "Binance")
if rate:
print(f"BTC funding rate on Binance: {rate['rate']}")
"""
data = get_funding_rates(symbol)
if not data or not data.get("data"):
return None
symbol_data = data["data"][0] if data["data"] else None
if not symbol_data:
return None
if exchange:
# Find specific exchange
for rate_info in symbol_data.get("uMarginList", []):
if rate_info.get("exchangeName", "").lower() == exchange.lower():
rate_num = _rate_num(rate_info, "rate", 0.0)
predicted_num = _rate_num(rate_info, "predictedRate", None) if rate_info.get("predictedRate") is not None else None
return {
"symbol": symbol.upper(),
"exchange": rate_info.get("exchangeName"),
"rate": _fmt_rate(rate_num),
"next_funding_time": rate_info.get("nextFundingTime"),
"funding_interval_hours": rate_info.get("fundingIntervalHours"),
"predicted_rate": _fmt_rate(predicted_num) if predicted_num is not None else None
}
return None
else:
# Return average across all exchanges
rates = [_rate_num(r, "rate", 0.0) for r in symbol_data.get("uMarginList", []) if (r.get("rate") is not None)]
if not rates:
return None
avg_rate = sum(rates) / len(rates)
return {
"symbol": symbol.upper(),
"exchange": "average",
"rate": _fmt_rate(avg_rate),
"num_exchanges": len(rates),
"exchanges_data": symbol_data.get("uMarginList", [])
}
def get_funding_rate_by_exchange(exchange: str) -> Optional[List[Dict[str, Any]]]:
"""
Get funding rates for all symbols on a specific exchange.
Args:
exchange: Exchange name (Binance, OKX, Bybit, etc.)
Returns:
List of funding rate dicts for each symbol on the exchange:
[
{"symbol": "BTC", "rate": "+0.0058%"},
{"symbol": "ETH", "rate": "+0.0042%"},
...
]
Returns None if request fails.
"""
data = get_funding_rates()
if not data or not data.get("data"):
return None
results = []
for symbol_data in data["data"]:
for rate_info in symbol_data.get("uMarginList", []):
if rate_info.get("exchangeName", "").lower() == exchange.lower():
rate_num = _rate_num(rate_info, "rate", 0.0)
predicted_num = _rate_num(rate_info, "predictedRate", None) if rate_info.get("predictedRate") is not None else None
results.append({
"symbol": symbol_data.get("symbol"),
"rate": _fmt_rate(rate_num),
"next_funding_time": rate_info.get("nextFundingTime"),
"funding_interval_hours": rate_info.get("fundingIntervalHours"),
"predicted_rate": _fmt_rate(predicted_num) if predicted_num is not None else None
})
return sorted(results, key=lambda x: abs(_rate_num(x, "rate", 0.0)), reverse=True) if results else None
def analyze_funding_opportunity(symbol: str, threshold: float = 0.01) -> Optional[Dict[str, Any]]:
"""
Analyze funding rate arbitrage opportunities across exchanges.
Args:
symbol: Symbol to analyze (BTC, ETH, etc.)
threshold: Minimum rate difference to flag (default 0.01 = 1%)
Returns:
Dictionary with arbitrage analysis:
{
"symbol": "BTC",
"highest": {"exchange": "CoinEx", "rate": "+0.0200%"},
"lowest": {"exchange": "Kraken", "rate": "-0.0010%"},
"spread": "+0.0210%",
"opportunity": True/False,
"all_rates": [...]
}
"""
data = get_funding_rates(symbol)
if not data or not data.get("data") or not data["data"]:
return None
symbol_data = data["data"][0]
rates_list = symbol_data.get("uMarginList", [])
if not rates_list:
return None
# Extract rates with exchange names
rates = [
{
"exchange": r.get("exchangeName"),
"rate": _fmt_rate(_rate_num(r, "rate", 0.0))
}
for r in rates_list
if (r.get("rate") is not None)
]
if not rates:
return None
sorted_rates = sorted(rates, key=lambda x: _rate_num(x, "rate", 0.0))
lowest = sorted_rates[0]
highest = sorted_rates[-1]
spread = _rate_num(highest, "rate", 0.0) - _rate_num(lowest, "rate", 0.0)
return {
"symbol": symbol.upper(),
"highest": highest,
"lowest": lowest,
"spread": _fmt_rate(spread),
"opportunity": spread >= threshold,
"all_rates": sorted_rates
}
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(description="Fetch Coinglass funding rates")
parser.add_argument("--symbol", "-s", help="Symbol to query (BTC, ETH, etc.)")
parser.add_argument("--exchange", "-e", help="Specific exchange (Binance, OKX, etc.)")
parser.add_argument("--all", "-a", action="store_true", help="Get all funding rates")
parser.add_argument("--analyze", action="store_true", help="Analyze arbitrage opportunities")
parser.add_argument("--by-exchange", help="Get all rates for an exchange")
parser.add_argument("--json", "-j", action="store_true", help="Output as JSON")
args = parser.parse_args()
if args.analyze and args.symbol:
result = analyze_funding_opportunity(args.symbol)
if result:
if args.json:
print(json.dumps(result, indent=2))
else:
print(f"\n{result['symbol']} Funding Rate Analysis")
print("=" * 50)
print(f"Highest: {result['highest']['exchange']}: {result['highest']['rate']}")
print(f"Lowest: {result['lowest']['exchange']}: {result['lowest']['rate']}")
print(f"Spread: {result['spread']}")
print(f"Opportunity: {'YES' if result['opportunity'] else 'NO'}")
else:
print(f"No data found for {args.symbol}")
return
if args.by_exchange:
result = get_funding_rate_by_exchange(args.by_exchange)
if result:
if args.json:
print(json.dumps(result, indent=2))
else:
print(f"\n{args.by_exchange} Funding Rates")
print("=" * 50)
for r in result[:20]: # Top 20
print(f"{r['symbol']:10s} {r['rate']:>10s}")
else:
print(f"No data found for exchange {args.by_exchange}")
return
if args.symbol:
result = get_symbol_funding_rate(args.symbol, args.exchange)
if result:
if args.json:
print(json.dumps(result, indent=2))
else:
print(f"\n{result['symbol']} Funding Rate")
print("=" * 50)
if args.exchange:
print(f"Exchange: {result['exchange']}")
print(f"Rate: {result['rate']}")
if result.get('predicted_rate'):
print(f"Predicted: {result['predicted_rate']}")
else:
print(f"Average Rate: {result['rate']}")
print(f"Exchanges: {result['num_exchanges']}")
else:
print(f"No funding rate found for {args.symbol}" + (f" on {args.exchange}" if args.exchange else ""))
return
if args.all:
result = get_funding_rates()
if result and result.get("data"):
if args.json:
print(json.dumps(result, indent=2))
else:
print("\nAll Funding Rates")
print("=" * 50)
for symbol_data in result["data"][:20]: # First 20 symbols
symbol = symbol_data.get("symbol", "???")
rates = symbol_data.get("uMarginList", [])
if rates:
numeric_rates = [_rate_num(r, "rate", 0.0) for r in rates if (r.get("rate") is not None)]
if numeric_rates:
avg = sum(numeric_rates) / len(numeric_rates)
print(f"{symbol:10s} avg: {_fmt_rate(avg)}")
else:
print("Failed to fetch funding rates")
return
# Default: show help
parser.print_help()
if __name__ == "__main__":
main()
tools/futures_market.py
#!/usr/bin/env python3
"""
Coinglass Futures Market Module
Provides futures market data: supported coins, exchanges, pairs,
coin-level market data, pair-level data, and OHLC price history.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
from ._api import cg_request
def _format_funding_rate(val: Any) -> Any:
"""Format numeric funding-rate values to percent strings."""
if isinstance(val, (int, float)):
sign = "+" if val >= 0 else ""
return f"{sign}{val:.4f}%"
if isinstance(val, str):
s = val.strip()
if s.endswith("%"):
return s
try:
num = float(s)
sign = "+" if num >= 0 else ""
return f"{sign}{num:.4f}%"
except ValueError:
return val
return val
def _normalize_funding_fields(obj: Any) -> Any:
"""Recursively normalize only funding-rate fields; keep all other fields unchanged."""
if isinstance(obj, list):
return [_normalize_funding_fields(x) for x in obj]
if isinstance(obj, dict):
out = {}
for k, v in obj.items():
lk = k.lower()
if "funding" in lk and "rate" in lk:
out[k] = _format_funding_rate(v)
else:
out[k] = _normalize_funding_fields(v)
return out
return obj
def get_supported_coins() -> Optional[List[str]]:
"""Get list of coins supported by Coinglass futures data."""
return cg_request("api/futures/supported-coins")
def get_supported_exchanges() -> Optional[List[Dict[str, Any]]]:
"""Get list of exchanges with supported trading pairs."""
return cg_request("api/futures/supported-exchange-pairs")
def get_supported_pairs(
exchange: str = "Binance"
) -> Optional[List[Dict[str, Any]]]:
"""
Get supported trading pairs for a specific exchange.
Args:
exchange: Exchange name (Binance, OKX, Bybit, etc.)
"""
return cg_request(
"api/futures/supported-exchange-pairs",
params={"exchange": exchange}
)
def get_coins_data(
symbol: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get futures market data aggregated by coin.
Args:
symbol: Optional coin filter (BTC, ETH, etc.)
"""
params = {}
if symbol:
params["symbol"] = symbol
data = cg_request("api/futures/coins-markets", params=params or None)
return _normalize_funding_fields(data)
def get_pair_data(
symbol: str = "BTC",
exchange: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get futures market data by trading pair.
Args:
symbol: Coin symbol (BTC, ETH, etc.)
exchange: Optional exchange filter.
"""
params = {"symbol": symbol}
if exchange:
params["exchange"] = exchange
data = cg_request("api/futures/pairs-markets", params=params)
return _normalize_funding_fields(data)
def get_ohlc_history(
symbol: str = "BTC",
interval: str = "h4",
exchange: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get OHLC price history for a futures pair.
Args:
symbol: Coin symbol.
interval: Time interval (m1, m5, m15, h1, h4, h12, h24).
exchange: Optional exchange filter.
"""
params = {"symbol": symbol, "interval": interval}
if exchange:
params["exchange"] = exchange
return cg_request("api/futures/price/history", params=params)
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Futures Market Tools"
)
parser.add_argument("action", choices=[
"coins", "exchanges", "pairs", "market", "ohlc"
])
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--interval", "-i", default="h4")
args = parser.parse_args()
actions = {
"coins": get_supported_coins,
"exchanges": get_supported_exchanges,
"pairs": lambda: get_supported_pairs(args.exchange or "Binance"),
"market": lambda: get_coins_data(args.symbol),
"ohlc": lambda: get_ohlc_history(
args.symbol, args.interval, args.exchange
),
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/hyperliquid.py
#!/usr/bin/env python3
"""
Coinglass Hyperliquid Module
Provides Hyperliquid-specific data: whale alerts, whale positions,
positions by coin, user positions, and position distribution.
"""
import sys
import json
import argparse
from typing import Dict, Any, List, Optional
from ._api import cg_request
def get_whale_alerts() -> Optional[List[Dict[str, Any]]]:
"""Get Hyperliquid whale position alerts (large position changes)."""
return cg_request("api/hyperliquid/whale-alert")
def get_whale_positions() -> Optional[List[Dict[str, Any]]]:
"""Get current Hyperliquid whale positions."""
return cg_request("api/hyperliquid/whale-position")
def get_positions_by_coin(
symbol: str = "BTC"
) -> Optional[List[Dict[str, Any]]]:
"""
Get Hyperliquid positions aggregated by coin.
Args:
symbol: Coin symbol (BTC, ETH, SOL, etc.)
"""
return cg_request(
"api/hyperliquid/position",
params={"symbol": symbol}
)
def get_user_positions(
address: str = ""
) -> Optional[List[Dict[str, Any]]]:
"""
Get positions for a specific Hyperliquid wallet.
Args:
address: Wallet address to query.
"""
params = {}
if address:
params["address"] = address
return cg_request(
"api/hyperliquid/user-position",
params=params or None
)
def get_position_distribution(
symbol: str = "BTC"
) -> Optional[Dict[str, Any]]:
"""
Get wallet position distribution for a coin on Hyperliquid.
Args:
symbol: Coin symbol (BTC, ETH, SOL, etc.)
"""
return cg_request(
"api/hyperliquid/wallet/position-distribution",
params={"symbol": symbol}
)
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Hyperliquid Tools"
)
parser.add_argument("action", choices=[
"alerts", "whales", "coin", "user", "distribution"
])
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--address", "-a", default="")
args = parser.parse_args()
actions = {
"alerts": get_whale_alerts,
"whales": get_whale_positions,
"coin": lambda: get_positions_by_coin(args.symbol),
"user": lambda: get_user_positions(args.address),
"distribution": lambda: get_position_distribution(args.symbol),
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/liquidations_advanced.py
#!/usr/bin/env python3
"""
Coinglass Liquidations Advanced Module
Provides detailed liquidation data: coin/pair history,
coin list aggregation, liquidation orders, and heatmap data.
"""
import sys
import json
import argparse
from typing import Dict, Any, List, Optional
from ._api import cg_request
def get_coin_liquidation_history(
symbol: str = "BTC",
interval: str = "h4"
) -> Optional[List[Dict[str, Any]]]:
"""
Get aggregated liquidation history for a coin.
Args:
symbol: Coin symbol (BTC, ETH, SOL, etc.)
interval: Time interval (h1, h4, h12, h24).
"""
return cg_request(
"api/futures/liquidation/aggregated-history",
params={"symbol": symbol, "interval": interval}
)
def get_pair_liquidation_history(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "h4"
) -> Optional[List[Dict[str, Any]]]:
"""
Get liquidation history for a specific trading pair.
Args:
symbol: Coin symbol.
exchange: Exchange name.
interval: Time interval (h1, h4, h12, h24).
"""
return cg_request(
"api/futures/liquidation/history",
params={
"symbol": symbol,
"exchange": exchange,
"interval": interval,
}
)
def get_liquidation_coin_list(
symbol: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get liquidation summary aggregated by coin.
Args:
symbol: Optional coin filter.
"""
params = {}
if symbol:
params["symbol"] = symbol
return cg_request(
"api/futures/liquidation/coin-list",
params=params or None
)
def get_liquidation_orders(
symbol: str = "BTC",
exchange: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get recent large liquidation orders.
Args:
symbol: Coin symbol.
exchange: Optional exchange filter.
"""
params = {"symbol": symbol}
if exchange:
params["exchange"] = exchange
return cg_request("api/futures/liquidation/order", params=params)
def get_liquidation_heatmap(
symbol: str = "BTC",
exchange: Optional[str] = None,
range: str = "24h"
) -> Optional[Dict[str, Any]]:
"""
Get liquidation heatmap data (price levels with liquidation density).
Args:
symbol: Coin symbol.
exchange: Exchange name. If omitted, use aggregated heatmap across exchanges.
range: Time range (12h, 24h, 3d, 7d, 30d, 90d, 180d, 1y).
"""
if exchange:
# Pair heatmap requires valid exchange+instrument mapping
return cg_request(
"api/futures/liquidation/heatmap/model1",
params={"symbol": symbol, "exchange": exchange, "range": range}
)
# Aggregated heatmap is more stable for symbol-level liquidation zones
return cg_request(
"api/futures/liquidation/aggregated-heatmap/model1",
params={"symbol": symbol, "range": range}
)
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Liquidation Advanced Tools"
)
parser.add_argument("action", choices=[
"coin-history", "pair-history", "coin-list",
"orders", "heatmap"
])
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--range", "-r", default="24h")
parser.add_argument("--interval", "-i", default="h4")
args = parser.parse_args()
actions = {
"coin-history": lambda: get_coin_liquidation_history(
args.symbol, args.interval
),
"pair-history": lambda: get_pair_liquidation_history(
args.symbol, args.exchange, args.interval
),
"coin-list": lambda: get_liquidation_coin_list(args.symbol),
"orders": lambda: get_liquidation_orders(
args.symbol, args.exchange
),
"heatmap": lambda: get_liquidation_heatmap(
symbol=args.symbol,
exchange=args.exchange,
range=args.range,
),
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/liquidations.py
#!/usr/bin/env python3
"""
Coinglass Liquidations Module
Provides liquidation data across exchanges: individual liquidations
and aggregated (long/short) liquidation summaries.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional
from ._api import cg_request
def get_liquidations(
symbol: str = "BTC",
time_type: str = "h24"
) -> Optional[Dict[str, Any]]:
"""
Get liquidation data across exchanges.
Args:
symbol: Coin symbol (BTC, ETH, SOL, etc.)
time_type: Time window (h1, h4, h12, h24).
Returns:
Dict with liquidation data: long/short amounts, counts.
Raises:
CoinglassError: On API failure.
"""
# Map h-format to API format
range_map = {"h1": "1h", "h4": "4h", "h12": "12h", "h24": "24h"}
v4_range = range_map.get(time_type, time_type)
params = {"symbol": symbol.upper(), "range": v4_range}
return cg_request(
"api/futures/liquidation/exchange-list", params=params
)
def get_liquidation_aggregated(
symbol: str = "BTC",
time_type: str = "h24"
) -> Optional[Dict[str, Any]]:
"""
Get aggregated liquidation summary (total longs vs shorts).
Args:
symbol: Coin symbol.
interval: Time interval.
Returns:
Dict with total long/short liquidations and ratio.
"""
data = get_liquidations(symbol, time_type)
if not data:
return None
# Aggregate across exchanges
entries = data if isinstance(data, list) else [data]
total_long = 0
total_short = 0
for entry in entries:
total_long += entry.get("longLiquidationUsd", 0) or 0
total_short += entry.get("shortLiquidationUsd", 0) or 0
total = total_long + total_short
return {
"symbol": symbol.upper(),
"interval": time_type,
"total_long_usd": total_long,
"total_short_usd": total_short,
"total_usd": total,
"long_ratio": total_long / total if total else 0,
"short_ratio": total_short / total if total else 0,
"dominant": "long" if total_long > total_short else "short",
}
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Liquidation Tools"
)
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--interval", "-i", default="h4")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--aggregated", "-a", action="store_true",
help="Show aggregated summary")
args = parser.parse_args()
try:
if args.aggregated:
result = get_liquidation_aggregated(
args.symbol, args.interval
)
else:
result = get_liquidations(
args.symbol, args.interval
)
if result:
print(json.dumps(result, indent=2))
else:
print("No data found", file=sys.stderr)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/long_short_advanced.py
#!/usr/bin/env python3
"""
Coinglass Long/Short Advanced Module
Provides advanced long/short data: global account ratio,
top trader ratios, taker buy/sell by exchange, net positions.
"""
import sys
import json
import argparse
from typing import Dict, Any, List, Optional
from ._api import cg_request
def _to_pair(symbol: str) -> str:
"""Convert symbol to trading pair (BTC → BTCUSDT)."""
s = symbol.upper()
return s if s.endswith("USDT") else f"{s}USDT"
# Exchange name normalization for consistent API calls
_EXCHANGE_ALIASES = {
"binance": "Binance", "okx": "OKX", "bybit": "Bybit",
"bitget": "Bitget", "gate": "Gate", "bitmex": "Bitmex",
"dydx": "dYdX", "kraken": "Kraken", "coinex": "CoinEx",
}
def _normalize_exchange(name: str) -> str:
"""Normalize exchange name to Coinglass format."""
return _EXCHANGE_ALIASES.get(name.lower(), name)
def get_global_account_ratio(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h"
) -> Optional[List[Dict[str, Any]]]:
"""
Get global long/short account ratio history.
Args:
symbol: Coin symbol.
interval: Time interval (h1, h4, h12, h24).
exchange: Optional exchange filter.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": _normalize_exchange(exchange),
"interval": interval,
}
return cg_request(
"api/futures/global-long-short-account-ratio/history",
params=params
)
def get_top_account_ratio(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h"
) -> Optional[List[Dict[str, Any]]]:
"""
Get top trader long/short account ratio history.
Args:
symbol: Coin symbol.
interval: Time interval.
exchange: Optional exchange filter.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": _normalize_exchange(exchange),
"interval": interval,
}
return cg_request(
"api/futures/top-long-short-account-ratio/history",
params=params
)
def get_top_position_ratio(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h"
) -> Optional[List[Dict[str, Any]]]:
"""
Get top trader long/short position ratio history.
Args:
symbol: Coin symbol.
interval: Time interval.
exchange: Optional exchange filter.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": _normalize_exchange(exchange),
"interval": interval,
}
return cg_request(
"api/futures/top-long-short-position-ratio/history",
params=params
)
def get_taker_buysell_exchanges(
symbol: str = "BTC",
range_type: str = "4h"
) -> Optional[List[Dict[str, Any]]]:
"""
Get taker buy/sell volume by exchange.
Args:
symbol: Coin symbol.
"""
return cg_request(
"api/futures/taker-buy-sell-volume/exchange-list",
params={"symbol": symbol, "range": range_type}
)
def get_net_position(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h"
) -> Optional[List[Dict[str, Any]]]:
"""
Get net position history (v1).
Args:
symbol: Coin symbol.
interval: Time interval.
exchange: Optional exchange filter.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": _normalize_exchange(exchange),
"interval": interval,
}
return cg_request(
"api/futures/net-position/history", params=params
)
def get_net_position_v2(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h"
) -> Optional[List[Dict[str, Any]]]:
"""
Get net position history (v2 — more exchanges).
Args:
symbol: Coin symbol.
interval: Time interval.
exchange: Optional exchange filter.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": _normalize_exchange(exchange),
"interval": interval,
}
return cg_request(
"api/futures/v2/net-position/history", params=params
)
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Long/Short Advanced Tools"
)
parser.add_argument("action", choices=[
"global", "top-account", "top-position",
"taker", "net", "net-v2"
])
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--interval", "-i", default="h4")
args = parser.parse_args()
actions = {
"global": lambda: get_global_account_ratio(
args.symbol, args.exchange or "Binance", args.interval
),
"top-account": lambda: get_top_account_ratio(
args.symbol, args.exchange or "Binance", args.interval
),
"top-position": lambda: get_top_position_ratio(
args.symbol, args.exchange or "Binance", args.interval
),
"taker": lambda: get_taker_buysell_exchanges(args.symbol),
"net": lambda: get_net_position(
args.symbol, args.exchange or "Binance", args.interval
),
"net-v2": lambda: get_net_position_v2(
args.symbol, args.exchange or "Binance", args.interval
),
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/long_short_ratio.py
#!/usr/bin/env python3
"""
Coinglass Long/Short Ratio Module
Provides aggregate long/short position ratio data across exchanges.
Ratio > 1 means more longs; < 1 means more shorts.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
from ._api import cg_request
def get_long_short_ratio(
symbol: str = "BTC",
interval: str = "h4"
) -> Optional[Dict[str, Any]]:
"""
Get long/short ratio data across exchanges.
Args:
symbol: Coin symbol (BTC, ETH, etc.)
interval: Time interval (h1, h4, h12, h24).
Returns:
Dict with exchange-level long/short data.
Raises:
CoinglassError: On API failure.
"""
data = cg_request(
"long_short", params={"symbol": symbol, "time_type": interval},
version="v2"
)
# v2 returns wrapped data — may need to handle both list and dict
return data
def get_exchange_ratio(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "h4"
) -> Optional[Dict[str, Any]]:
"""
Get long/short ratio for a specific exchange.
Args:
symbol: Coin symbol.
exchange: Exchange name.
interval: Time interval.
Returns:
Dict with ratio, longPercent, shortPercent for the exchange.
None if exchange not found in data.
"""
data = get_long_short_ratio(symbol, interval)
if not data:
return None
# Data may be a list of exchange entries
entries = data if isinstance(data, list) else [data]
for entry in entries:
if entry.get("exchangeName", "").lower() == exchange.lower():
long_pct = entry.get("longRate", 0)
short_pct = entry.get("shortRate", 0)
ratio = long_pct / short_pct if short_pct else 0
return {
"symbol": symbol.upper(),
"exchange": entry.get("exchangeName"),
"long_percent": long_pct * 100,
"short_percent": short_pct * 100,
"ratio": ratio,
}
return None
def get_sentiment(
symbol: str = "BTC",
interval: str = "h4"
) -> Optional[Dict[str, Any]]:
"""
Get aggregated market sentiment from long/short ratios.
Args:
symbol: Coin symbol.
interval: Time interval.
Returns:
Dict with avg ratio, sentiment label, and per-exchange breakdown.
"""
data = get_long_short_ratio(symbol, interval)
if not data:
return None
entries = data if isinstance(data, list) else [data]
ratios = []
for entry in entries:
long_r = entry.get("longRate", 0)
short_r = entry.get("shortRate", 0)
if short_r:
ratios.append({
"exchange": entry.get("exchangeName", ""),
"ratio": long_r / short_r,
})
if not ratios:
return None
avg_ratio = sum(r["ratio"] for r in ratios) / len(ratios)
if avg_ratio > 1.2:
sentiment = "Very Bullish"
elif avg_ratio > 1.0:
sentiment = "Bullish"
elif avg_ratio > 0.8:
sentiment = "Bearish"
else:
sentiment = "Very Bearish"
return {
"symbol": symbol.upper(),
"avg_ratio": avg_ratio,
"sentiment": sentiment,
"exchanges": ratios,
}
def compare_exchanges(
symbol: str = "BTC",
interval: str = "h4"
) -> Optional[List[Dict[str, Any]]]:
"""
Compare long/short ratios across all exchanges.
Returns:
Sorted list of exchanges by ratio (most bullish first).
"""
data = get_long_short_ratio(symbol, interval)
if not data:
return None
entries = data if isinstance(data, list) else [data]
results = []
for entry in entries:
long_r = entry.get("longRate", 0)
short_r = entry.get("shortRate", 0)
ratio = long_r / short_r if short_r else 0
results.append({
"exchange": entry.get("exchangeName", ""),
"ratio": round(ratio, 4),
"long_percent": round(long_r * 100, 2),
"short_percent": round(short_r * 100, 2),
})
results.sort(key=lambda x: x["ratio"], reverse=True)
return results if results else None
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Long/Short Ratio Tools"
)
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--interval", "-i", default="h4")
parser.add_argument("--sentiment", action="store_true",
help="Show sentiment analysis")
parser.add_argument("--compare", action="store_true",
help="Compare across exchanges")
args = parser.parse_args()
try:
if args.sentiment:
result = get_sentiment(args.symbol, args.interval)
elif args.compare:
result = compare_exchanges(args.symbol, args.interval)
elif args.exchange:
result = get_exchange_ratio(
args.symbol, args.exchange, args.interval
)
else:
result = get_long_short_ratio(args.symbol, args.interval)
if result:
print(json.dumps(result, indent=2))
else:
print("No data found", file=sys.stderr)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/open_interest.py
#!/usr/bin/env python3
"""
Coinglass Open Interest Module
Fetch aggregate open interest data across major cryptocurrency exchanges.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
from ._api import cg_request
# MCP Tool Schema
MCP_OPEN_INTEREST_SCHEMA = {
"name": "cg_open_interest",
"title": "Coinglass Open Interest",
"description": (
"Get aggregate open interest across exchanges for a symbol."
),
"inputSchema": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Symbol (BTC, ETH, SOL, etc.)"
},
"interval": {
"type": "string",
"description": "Time interval: 0 (all), h1, h4, h12, h24",
"default": "0",
"enum": ["0", "h1", "h4", "h12", "h24"]
}
},
"required": ["symbol"],
"additionalProperties": False
}
}
def get_open_interest(
symbol: str = "BTC",
interval: str = "0"
) -> Optional[Dict[str, Any]]:
"""
Get aggregate open interest across exchanges for a symbol.
Uses v2 API for basic OI data.
Args:
symbol: Coin symbol (BTC, ETH, SOL, etc.)
interval: Time interval (0=all, h1, h4, h12, h24).
Returns:
Dict with open interest data by exchange.
Raises:
CoinglassError: On API failure.
"""
return cg_request(
"open_interest",
params={"symbol": symbol, "interval": interval},
version="v2"
)
def get_open_interest_history(
symbol: str = "BTC",
interval: str = "h4",
exchange: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get open interest history (aggregated across exchanges).
Uses v4 API for historical data.
Args:
symbol: Coin symbol.
interval: Time interval (h1, h4, h12, h24).
exchange: Optional exchange filter.
Returns:
List of historical OI data points.
"""
params = {"symbol": symbol, "interval": interval}
if exchange:
params["exchange"] = exchange
return cg_request(
"api/futures/open-interest/aggregated-history",
params=params
)
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Open Interest Tools"
)
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--interval", "-i", default="h4")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--history", action="store_true",
help="Show OI history")
parser.add_argument("--json", "-j", action="store_true")
args = parser.parse_args()
try:
if args.history:
result = get_open_interest_history(
args.symbol, args.interval, args.exchange
)
else:
result = get_open_interest(args.symbol, args.interval)
if result:
print(json.dumps(result, indent=2))
else:
print("No data found", file=sys.stderr)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/other_etfs.py
#!/usr/bin/env python3
"""
Coinglass ETF Module (Non-Bitcoin)
Provides ETF data for Ethereum, Solana, XRP, and HK listings.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
from ._api import cg_request
def get_eth_etf_flows() -> Optional[List[Dict[str, Any]]]:
"""Get Ethereum ETF flow history (inflows/outflows)."""
return cg_request("api/etf/ethereum/flow-history")
def get_eth_etf_list() -> Optional[List[Dict[str, Any]]]:
"""Get list of all Ethereum ETFs with details."""
return cg_request("api/etf/ethereum/list")
def get_eth_etf_premium_discount() -> Optional[List[Dict[str, Any]]]:
"""Get Ethereum ETF premium/discount history."""
return cg_request("api/etf/ethereum/premium-discount/history")
def get_sol_etf_flows() -> Optional[List[Dict[str, Any]]]:
"""Get Solana ETF flow history."""
return cg_request("api/etf/solana/flow-history")
def get_sol_etf_list() -> Optional[List[Dict[str, Any]]]:
"""Get list of all Solana ETFs."""
return cg_request("api/etf/solana/list")
def get_xrp_etf_flows() -> Optional[List[Dict[str, Any]]]:
"""Get XRP ETF flow history."""
return cg_request("api/etf/xrp/flow-history")
def get_xrp_etf_list() -> Optional[List[Dict[str, Any]]]:
"""Get list of all XRP ETFs."""
return cg_request("api/etf/xrp/list")
def get_hk_eth_etf_flows() -> Optional[List[Dict[str, Any]]]:
"""Get Hong Kong Ethereum ETF flows."""
return cg_request("api/hk-etf/ethereum/flow-history")
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(description="Coinglass ETF Tools")
parser.add_argument("action", choices=[
"eth-flows", "eth-list", "sol-flows", "xrp-flows"
])
parser.add_argument("--json", "-j", action="store_true")
args = parser.parse_args()
actions = {
"eth-flows": get_eth_etf_flows,
"eth-list": get_eth_etf_list,
"sol-flows": get_sol_etf_flows,
"xrp-flows": get_xrp_etf_flows,
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/volume_flow.py
#!/usr/bin/env python3
"""
Coinglass Volume & Flow Module
Provides taker volume history, aggregated taker volume,
cumulative volume delta (CVD), coin netflow, and vol-weighted OHLC.
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional, List
from ._api import cg_request
def _to_pair(symbol: str) -> str:
"""Convert symbol to trading pair (BTC → BTCUSDT)."""
s = symbol.upper()
return s if s.endswith("USDT") else f"{s}USDT"
def get_taker_volume_history(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h",
limit: int = 1000,
start_time: int = None,
end_time: int = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get taker buy/sell volume history for a coin.
Args:
symbol: Coin symbol.
exchange: Exchange name.
interval: Time interval (1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d).
limit: Number of results (default 1000, max 4500).
start_time: Start timestamp in seconds.
end_time: End timestamp in seconds.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": exchange,
"interval": interval,
}
if limit and limit != 1000:
params["limit"] = limit
if start_time:
params["startTime"] = start_time
if end_time:
params["endTime"] = end_time
return cg_request(
"api/futures/v2/taker-buy-sell-volume/history",
params=params
)
def get_aggregated_taker_volume(
symbol: str = "BTC",
interval: str = "h4"
) -> Optional[List[Dict[str, Any]]]:
"""
Get aggregated taker buy/sell volume history across exchanges.
Args:
symbol: Coin symbol.
interval: Time interval.
"""
return cg_request(
"api/futures/aggregated-taker-buy-sell-volume/history",
params={"symbol": _to_pair(symbol), "interval": interval}
)
def get_cumulative_volume_delta(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h",
limit: int = 1000,
start_time: int = None,
end_time: int = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get cumulative volume delta (CVD) history.
CVD tracks net buying vs selling pressure over time.
Rising CVD = accumulation (bullish).
Falling CVD = distribution (bearish).
Args:
symbol: Coin symbol.
exchange: Exchange name.
interval: Time interval (1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d).
limit: Number of results (default 1000, max 4500).
start_time: Start timestamp in seconds.
end_time: End timestamp in seconds.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": exchange,
"interval": interval,
}
if limit and limit != 1000:
params["limit"] = limit
if start_time:
params["startTime"] = start_time
if end_time:
params["endTime"] = end_time
return cg_request(
"api/futures/cvd/history",
params=params
)
def get_coin_netflow(
symbol: Optional[str] = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get exchange netflow data by coin.
Shows net inflow/outflow of coins across exchanges.
Args:
symbol: Optional coin filter.
"""
params = {}
if symbol:
params["symbol"] = symbol
return cg_request("api/futures/netflow-list", params=params or None)
def get_volume_ohlc_history(
symbol: str = "BTC",
exchange: str = "Binance",
interval: str = "1h",
limit: int = 1000,
start_time: int = None,
end_time: int = None
) -> Optional[List[Dict[str, Any]]]:
"""
Get volume-weighted OHLC history.
Args:
symbol: Coin symbol.
exchange: Exchange name.
interval: Time interval (1m, 5m, 15m, 30m, 1h, 4h, 12h, 1d).
limit: Number of results (default 1000, max 4500).
start_time: Start timestamp in seconds.
end_time: End timestamp in seconds.
"""
params = {
"symbol": _to_pair(symbol),
"exchange": exchange,
"interval": interval,
}
if limit and limit != 1000:
params["limit"] = limit
if start_time:
params["startTime"] = start_time
if end_time:
params["endTime"] = end_time
return cg_request(
"api/futures/vol-weight-ohlc-history",
params=params
)
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Volume & Flow Tools"
)
parser.add_argument("action", choices=[
"taker", "aggregated", "cvd", "netflow", "ohlc"
])
parser.add_argument("--symbol", "-s", default="BTC")
parser.add_argument("--exchange", "-e", default=None)
parser.add_argument("--interval", "-i", default="h4")
args = parser.parse_args()
actions = {
"taker": lambda: get_taker_volume_history(
args.symbol, args.exchange or "Binance", args.interval
),
"aggregated": lambda: get_aggregated_taker_volume(
args.symbol, args.interval
),
"cvd": lambda: get_cumulative_volume_delta(
args.symbol, args.exchange or "Binance", args.interval
),
"netflow": lambda: get_coin_netflow(args.symbol),
"ohlc": lambda: get_volume_ohlc_history(
args.symbol, args.exchange or "Binance", args.interval
),
}
try:
result = actions[args.action]()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
tools/whale_transfer.py
#!/usr/bin/env python3
"""
Coinglass Whale Transfer Module
Provides on-chain whale transfer data including:
- Large transfers (minimum $10M) across major blockchains
- Bitcoin, Ethereum, Tron, Ripple, Dogecoin, Litecoin, Polygon,
Algorand, Bitcoin Cash, Solana
- Past 6 months of data
"""
import sys
import json
import argparse
from typing import Dict, Any, Optional
from ._api import cg_request
def get_whale_transfers() -> Optional[Dict[str, Any]]:
"""
Get large on-chain transfers (minimum $10M) across major blockchains.
Returns:
List of whale transfers with transaction hash, asset, amount,
exchange, transfer type (1=inflow, 2=outflow, 3=internal),
addresses, and timestamp.
Raises:
CoinglassError: On API failure with actionable error message.
"""
return cg_request("api/chain/v2/whale-transfer")
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Coinglass Whale Transfer Tool"
)
parser.add_argument("--json", "-j", action="store_true",
help="Output as JSON")
parser.parse_args()
try:
result = get_whale_transfers()
print(json.dumps(result, indent=2))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()