import os import pandas as pd from typing import List, Dict, Any, Optional from binance.client import Client, HistoricalKlinesType from binance.exceptions import BinanceAPIException import datetime import time class BinanceAPI: """Binance API交互类,用于获取市场数据和执行交易""" def __init__(self, api_key: str, api_secret: str, test_mode: bool = True): """ 初始化Binance API客户端 Args: api_key: Binance API密钥 api_secret: Binance API密钥 test_mode: 是否使用测试模式(不执行实际交易) """ self.api_key = api_key self.api_secret = api_secret self.test_mode = test_mode self.client = Client(api_key, api_secret) # 验证API连接 try: self.client.get_account() print("Binance API连接成功") except BinanceAPIException as e: print(f"Binance API连接失败: {e}") def get_all_symbols(self) -> List[str]: """ 获取所有合约交易对 Returns: List[str]: 所有合约交易对列表 """ symbols = self.client.get_exchange_info()['symbols'] result = [] # 选择USDT交易对以及 status 为 TRADING 的交易对 for symbol in symbols: if symbol['quoteAsset'] == 'USDT' and symbol['status'] == 'TRADING': result.append(symbol['symbol']) return result def get_top_longshort_position_ratio(self, symbol: str, period: str = '1h') -> float: """ 获取交易对大户持仓多空比 Args: symbol: 交易对符号,例如 'BTCUSDT' period: 时间间隔,例如 '1h', '1d' Returns: 大户持仓多空比 """ try: response = self.client.futures_top_longshort_position_ratio(symbol=symbol, period=period) return response except BinanceAPIException as e: print(f"获取交易对大户持仓多空比时出错: {e}") return 0 def get_top_longshort_account_ratio(self, symbol: str, period: str = '1h') -> float: """ 获取交易对大户持仓多空比 Args: symbol: 交易对符号,例如 'BTCUSDT' period: 时间间隔,例如 '1h', '1d' Returns: 大户持仓多空比 """ try: response = self.client.futures_top_longshort_account_ratio(symbol=symbol, period=period) return response except BinanceAPIException as e: print(f"获取交易对大户持仓多空比时出错: {e}") return 0 def get_historical_klines(self, symbol: str, interval: str, start_str: Optional[str] = None, end_str: Optional[str] = None, limit: int = 200) -> pd.DataFrame: """ 获取历史K线数据 Args: symbol: 交易对符号,例如 'BTCUSDT' interval: K线间隔,例如 '1h', '1d' start_str: 开始时间,例如 '1 day ago UTC' end_str: 结束时间,例如 'now UTC' Returns: 包含历史数据的DataFrame """ try: klines = self.client.get_historical_klines( symbol=symbol, interval=interval, start_str=start_str, end_str=end_str, limit=limit, klines_type=HistoricalKlinesType.FUTURES ) print(f"Binance获取数据: {klines}") # 转换为DataFrame df = pd.DataFrame(klines, columns=[ 'timestamp', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'quote_asset_volume', 'number_of_trades', 'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume', 'ignore' ]) df['format_timestamp'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True).map(lambda x: x.tz_convert('Asia/Shanghai')) df['format_close_time'] = pd.to_datetime(df['close_time'], unit='ms', utc=True).map(lambda x: x.tz_convert('Asia/Shanghai')) for col in ['open', 'high', 'low', 'close', 'volume', 'quote_asset_volume', 'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume']: df[col] = df[col].astype(float) # 数据倒序 df = df.iloc[::-1] return df except BinanceAPIException as e: print(f"获取历史K线数据时出错: {e}") return pd.DataFrame() def get_recent_trades(self, symbol: str, limit: int = 500) -> pd.DataFrame: """ 获取最近的交易 Args: symbol: 交易对符号,例如 'BTCUSDT' limit: 返回的交易数量 Returns: 包含最近交易的DataFrame """ try: trades = self.client.get_recent_trades(symbol=symbol, limit=limit) return pd.DataFrame(trades) except BinanceAPIException as e: print(f"获取最近交易时出错: {e}") return pd.DataFrame() def get_order_book(self, symbol: str, limit: int = 100) -> Dict[str, Any]: """ 获取订单簿 Args: symbol: 交易对符号,例如 'BTCUSDT' limit: 返回的订单数量 Returns: 订单簿数据字典 """ try: return self.client.get_order_book(symbol=symbol, limit=limit) except BinanceAPIException as e: print(f"获取订单簿时出错: {e}") return {} def get_ticker(self, symbol: str = None) -> Dict[str, Any]: """ 获取当前价格 Args: symbol: 交易对符号,例如 'BTCUSDT',如果为None,则获取所有交易对 Returns: 当前价格数据 """ try: if symbol: return self.client.get_symbol_ticker(symbol=symbol) else: return self.client.get_all_tickers() except BinanceAPIException as e: print(f"获取当前价格时出错: {e}") return {} def place_order(self, symbol: str, side: str, type: str, quantity: float, price: float = None) -> Dict[str, Any]: """ 下单 Args: symbol: 交易对符号,例如 'BTCUSDT' side: 买入或卖出,'BUY' 或 'SELL' type: 订单类型,例如 'LIMIT', 'MARKET' quantity: 数量 price: 价格(对于限价单) Returns: 订单响应 """ if self.test_mode: print(f"测试模式: 模拟下单 {side} {quantity} {symbol} @ {price if price else 'MARKET'}") return { "symbol": symbol, "orderId": "test_order_id", "status": "TEST", "side": side, "type": type, "quantity": quantity, "price": price } try: if type == 'LIMIT': return self.client.create_order( symbol=symbol, side=side, type=type, timeInForce='GTC', quantity=quantity, price=price ) elif type == 'MARKET': return self.client.create_order( symbol=symbol, side=side, type=type, quantity=quantity ) except BinanceAPIException as e: print(f"下单时出错: {e}") return {} from cryptoai.utils.config_loader import ConfigLoader def get_binance_api() -> BinanceAPI: """ 获取Binance API实例 Returns: BinanceAPI实例 """ config = ConfigLoader() api_key = config.get_binance_config()['api_key'] api_secret = config.get_binance_config()['api_secret'] test_mode = config.get_binance_config()['test_mode'] return BinanceAPI(api_key, api_secret, test_mode)