Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
37-tool crypto derivatives data suite: funding rates, open interest, liquidations, Hyperliquid whale tracking, and ETF flows.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
tools/long_short_ratio.py
1#!/usr/bin/env python32"""3Coinglass Long/Short Ratio Module45Provides aggregate long/short position ratio data across exchanges.6Ratio > 1 means more longs; < 1 means more shorts.7"""89import sys10import json11import argparse12from typing import Dict, Any, Optional, List1314from ._api import cg_request151617def get_long_short_ratio(18symbol: str = "BTC",19interval: str = "h4"20) -> Optional[Dict[str, Any]]:21"""22Get long/short ratio data across exchanges.2324Args:25symbol: Coin symbol (BTC, ETH, etc.)26interval: Time interval (h1, h4, h12, h24).2728Returns:29Dict with exchange-level long/short data.3031Raises:32CoinglassError: On API failure.33"""34data = cg_request(35"long_short", params={"symbol": symbol, "time_type": interval},36version="v2"37)3839# v2 returns wrapped data — may need to handle both list and dict40return data414243def get_exchange_ratio(44symbol: str = "BTC",45exchange: str = "Binance",46interval: str = "h4"47) -> Optional[Dict[str, Any]]:48"""49Get long/short ratio for a specific exchange.5051Args:52symbol: Coin symbol.53exchange: Exchange name.54interval: Time interval.5556Returns:57Dict with ratio, longPercent, shortPercent for the exchange.58None if exchange not found in data.59"""60data = get_long_short_ratio(symbol, interval)61if not data:62return None6364# Data may be a list of exchange entries65entries = data if isinstance(data, list) else [data]66for entry in entries:67if entry.get("exchangeName", "").lower() == exchange.lower():68long_pct = entry.get("longRate", 0)69short_pct = entry.get("shortRate", 0)70ratio = long_pct / short_pct if short_pct else 071return {72"symbol": symbol.upper(),73"exchange": entry.get("exchangeName"),74"long_percent": long_pct * 100,75"short_percent": short_pct * 100,76"ratio": ratio,77}78return None798081def get_sentiment(82symbol: str = "BTC",83interval: str = "h4"84) -> Optional[Dict[str, Any]]:85"""86Get aggregated market sentiment from long/short ratios.8788Args:89symbol: Coin symbol.90interval: Time interval.9192Returns:93Dict with avg ratio, sentiment label, and per-exchange breakdown.94"""95data = get_long_short_ratio(symbol, interval)96if not data:97return None9899entries = data if isinstance(data, list) else [data]100ratios = []101for entry in entries:102long_r = entry.get("longRate", 0)103short_r = entry.get("shortRate", 0)104if short_r:105ratios.append({106"exchange": entry.get("exchangeName", ""),107"ratio": long_r / short_r,108})109110if not ratios:111return None112113avg_ratio = sum(r["ratio"] for r in ratios) / len(ratios)114if avg_ratio > 1.2:115sentiment = "Very Bullish"116elif avg_ratio > 1.0:117sentiment = "Bullish"118elif avg_ratio > 0.8:119sentiment = "Bearish"120else:121sentiment = "Very Bearish"122123return {124"symbol": symbol.upper(),125"avg_ratio": avg_ratio,126"sentiment": sentiment,127"exchanges": ratios,128}129130131def compare_exchanges(132symbol: str = "BTC",133interval: str = "h4"134) -> Optional[List[Dict[str, Any]]]:135"""136Compare long/short ratios across all exchanges.137138Returns:139Sorted list of exchanges by ratio (most bullish first).140"""141data = get_long_short_ratio(symbol, interval)142if not data:143return None144145entries = data if isinstance(data, list) else [data]146results = []147for entry in entries:148long_r = entry.get("longRate", 0)149short_r = entry.get("shortRate", 0)150ratio = long_r / short_r if short_r else 0151results.append({152"exchange": entry.get("exchangeName", ""),153"ratio": round(ratio, 4),154"long_percent": round(long_r * 100, 2),155"short_percent": round(short_r * 100, 2),156})157158results.sort(key=lambda x: x["ratio"], reverse=True)159return results if results else None160161162def main():163"""CLI entry point."""164parser = argparse.ArgumentParser(165description="Coinglass Long/Short Ratio Tools"166)167parser.add_argument("--symbol", "-s", default="BTC")168parser.add_argument("--exchange", "-e", default=None)169parser.add_argument("--interval", "-i", default="h4")170parser.add_argument("--sentiment", action="store_true",171help="Show sentiment analysis")172parser.add_argument("--compare", action="store_true",173help="Compare across exchanges")174args = parser.parse_args()175176try:177if args.sentiment:178result = get_sentiment(args.symbol, args.interval)179elif args.compare:180result = compare_exchanges(args.symbol, args.interval)181elif args.exchange:182result = get_exchange_ratio(183args.symbol, args.exchange, args.interval184)185else:186result = get_long_short_ratio(args.symbol, args.interval)187188if result:189print(json.dumps(result, indent=2))190else:191print("No data found", file=sys.stderr)192except Exception as e:193print(f"Error: {e}", file=sys.stderr)194sys.exit(1)195196197if __name__ == "__main__":198main()199