import os
from typing import Any, Dict, Union
from dotenv import load_dotenv
from pybit.unified_trading import HTTP
from bybit_mcp.models.market_models import (
FundingRateHistoryResponse,
InstrumentsInfoResponse,
InsuranceResponse,
KlineResponse,
LongShortRatioResponse,
OpenInterestResponse,
OrderBookResponse,
RecentTradesResponse,
RiskLimitResponse,
TickerResponse,
)
# Load environment variables from .env file
load_dotenv()
BYBIT_API_KEY = os.getenv("BYBIT_API_KEY")
BYBIT_API_SECRET = os.getenv("BYBIT_API_SECRET")
# Use testnet if BYBIT_TESTNET is set to "true" or "1"
USE_TESTNET = os.getenv("BYBIT_TESTNET", "false").lower() in ("true", "1")
bybit_session = HTTP(
testnet=USE_TESTNET, # Updated to use USE_TESTNET
api_key=BYBIT_API_KEY,
api_secret=BYBIT_API_SECRET,
)
def get_server_time() -> Dict[str, Any]:
"""Get Bybit server time using the Market API."""
return bybit_session.get_server_time()
def get_tickers(
symbol: Union[str, None] = None,
category: str = "linear",
baseCoin: Union[str, None] = None,
limit: int | None = None,
cursor: str | None = None,
) -> TickerResponse:
"""Get market tickers for all or a specific symbol and validate response."""
params = {"category": category}
for key, value in [("symbol", symbol), ("baseCoin", baseCoin), ("limit", str(limit) if limit else None), ("cursor", cursor)]:
if value:
params[key] = value
response = bybit_session.get_tickers(**params)
if isinstance(response, tuple):
response = response[0]
return TickerResponse(**response["result"])
def get_order_book(
symbol: str,
category: str = "linear",
limit: int = 50,
baseCoin: Union[str, None] = None,
cursor: str | None = None,
) -> OrderBookResponse:
"""Get order book (depth) for a symbol and validate response."""
params = {"symbol": symbol, "category": category, "limit": limit}
if baseCoin:
params["baseCoin"] = baseCoin
if cursor:
params["cursor"] = cursor
response = bybit_session.get_orderbook(**params)
if isinstance(response, tuple):
response = response[0]
return OrderBookResponse(**response["result"])
def get_recent_trades(
symbol: str,
category: str = "linear",
baseCoin: Union[str, None] = None,
optionType: Union[str, None] = None,
limit: int = 50,
cursor: str | None = None,
) -> RecentTradesResponse:
"""Get recent trades for a symbol and validate response."""
params = {"symbol": symbol, "category": category, "limit": limit}
if baseCoin:
params["baseCoin"] = baseCoin
if optionType:
params["optionType"] = optionType
if cursor:
params["cursor"] = cursor
response = bybit_session.get_public_trade_history(**params)
if isinstance(response, tuple):
response = response[0]
return RecentTradesResponse(**response["result"])
def get_kline(symbol: str, interval: str, category: str = "linear", limit: int = 200) -> KlineResponse:
"""Get kline (candlestick) data for a symbol and validate response."""
response = bybit_session.get_kline(symbol=symbol, interval=interval, category=category, limit=limit)
if isinstance(response, tuple):
response = response[0]
return KlineResponse(**response["result"])
def get_mark_price_kline(symbol: str, interval: str, category: str = "linear", limit: int = 200) -> KlineResponse:
"""Get mark price kline data for a symbol and validate response."""
response = bybit_session.get_mark_price_kline(symbol=symbol, interval=interval, category=category, limit=limit)
if isinstance(response, tuple):
response = response[0]
return KlineResponse(**response["result"])
def get_index_price_kline(symbol: str, interval: str, category: str = "linear", limit: int = 200) -> KlineResponse:
"""Get index price kline data for a symbol and validate response."""
response = bybit_session.get_index_price_kline(symbol=symbol, interval=interval, category=category, limit=limit)
if isinstance(response, tuple):
response = response[0]
return KlineResponse(**response["result"])
def get_premium_index_price_kline(symbol: str, interval: str, category: str = "linear", limit: int = 200) -> KlineResponse:
"""Get premium index price kline data for a symbol and validate response."""
response = bybit_session.get_premium_index_price_kline(symbol=symbol, interval=interval, category=category, limit=limit)
if isinstance(response, tuple):
response = response[0]
return KlineResponse(**response["result"])
def get_instruments_info(category: str = "linear", symbol: Union[str, None] = None) -> InstrumentsInfoResponse:
"""Get instruments info (list of trading pairs) and validate response."""
params = {"category": category}
if symbol:
params["symbol"] = symbol
response = bybit_session.get_instruments_info(**params)
if isinstance(response, tuple):
response = response[0]
return InstrumentsInfoResponse(**response["result"])
def get_funding_rate_history(symbol: str, category: str = "linear", limit: int = 200) -> FundingRateHistoryResponse:
"""Get funding rate history for a symbol and validate response."""
response = bybit_session.get_funding_rate_history(symbol=symbol, category=category, limit=limit)
if isinstance(response, tuple):
response = response[0]
return FundingRateHistoryResponse(**response["result"])
def get_open_interest(symbol: str, category: str = "linear", interval: str = "5min", limit: int = 200) -> OpenInterestResponse:
"""Get open interest for a symbol and validate response."""
response = bybit_session.get_open_interest(symbol=symbol, category=category, intervalTime=interval, limit=limit)
if isinstance(response, tuple):
response = response[0]
return OpenInterestResponse(**response["result"])
def get_insurance(
category: str = "linear",
baseCoin: Union[str, None] = None,
quoteCoin: Union[str, None] = None,
startTime: Union[str, None] = None,
endTime: Union[str, None] = None,
) -> InsuranceResponse:
"""Get insurance fund history and validate response."""
params = {"category": category}
for key, value in [("baseCoin", baseCoin), ("quoteCoin", quoteCoin), ("startTime", startTime), ("endTime", endTime)]:
if value:
params[key] = value
response = bybit_session.get_insurance(**params)
if isinstance(response, tuple):
response = response[0]
return InsuranceResponse(**response["result"])
def get_risk_limit(symbol: str, category: str = "linear") -> RiskLimitResponse:
"""Get risk limit for a symbol and validate response."""
response = bybit_session.get_risk_limit(symbol=symbol, category=category)
if isinstance(response, tuple):
response = response[0]
return RiskLimitResponse(**response["result"])
def get_long_short_ratio(symbol: str, category: str = "linear", interval: str = "5min", limit: int = 200) -> LongShortRatioResponse:
"""Get long short ratio for a symbol and validate response."""
response = bybit_session.get_long_short_ratio(symbol=symbol, category=category, period=interval, limit=limit)
if isinstance(response, tuple):
response = response[0]
return LongShortRatioResponse(**response["result"])