«

币安自动量化脚本

Jason 发布于 阅读:64


模拟账户余额5000美金实测,2.16下午7时至次日上午10时,总收益990美金。

"""
🐜 蚂蚁搬家 v3.0 PRO - 专业版
===============================================
✨ 现代化科技感界面
✅ 修复手续费计算
✅ 实时数据可视化
✅ 性能监控仪表板
===============================================
"""

import os
import time
import json
import hmac
import hashlib
import requests
import threading
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Set
from dataclasses import dataclass
from urllib.parse import urlencode
from decimal import Decimal, ROUND_DOWN

# ============ 配置 ============
BINANCE_API_KEY = 'KEY'
BINANCE_SECRET_KEY = 'KEY'

SYMBOL = 'ETHUSDT'
LEVERAGE = 8
GRID_SPREAD = 0.002  # 0.2%
NUM_GRIDS = 10
ORDER_AMOUNT_USDT = 200

# 手续费设置
MAKER_FEE = 0.0002  # 0.02% Maker费用
TAKER_FEE = 0.0004  # 0.04% Taker费用
DEFAULT_FEE = TAKER_FEE  # 保守估计使用Taker费用

CHECK_INTERVAL = 5.0
DISPLAY_INTERVAL = 15

BINANCE_BASE_URL = 'https://testnet.binancefuture.com' # 模拟账户
PRICE_PRECISION = 2
QUANTITY_PRECISION = 3

# ANSI颜色代码
class Colors:
    RESET = '\033[0m'
    BOLD = '\033[1m'
    DIM = '\033[2m'

    # 前景色
    BLACK = '\033[30m'
    RED = '\033[31m'
    GREEN = '\033[32m'
    YELLOW = '\033[33m'
    BLUE = '\033[34m'
    MAGENTA = '\033[35m'
    CYAN = '\033[36m'
    WHITE = '\033[37m'

    # 亮色
    BRIGHT_BLACK = '\033[90m'
    BRIGHT_RED = '\033[91m'
    BRIGHT_GREEN = '\033[92m'
    BRIGHT_YELLOW = '\033[93m'
    BRIGHT_BLUE = '\033[94m'
    BRIGHT_MAGENTA = '\033[95m'
    BRIGHT_CYAN = '\033[96m'
    BRIGHT_WHITE = '\033[97m'

    # 背景色
    BG_BLACK = '\033[40m'
    BG_BLUE = '\033[44m'
    BG_GREEN = '\033[42m'
    BG_RED = '\033[41m'

class UI:
    """现代化UI组件"""

    @staticmethod
    def clear_screen():
        """清屏"""
        os.system('clear' if os.name != 'nt' else 'cls')

    @staticmethod
    def box(text: str, color=Colors.CYAN, width=80):
        """绘制边框盒子"""
        lines = text.split('\n')
        print(f"{color}╔{'═' * (width-2)}╗{Colors.RESET}")
        for line in lines:
            padding = width - len(line) - 4
            print(f"{color}║{Colors.RESET} {line}{' ' * padding} {color}║{Colors.RESET}")
        print(f"{color}╚{'═' * (width-2)}╝{Colors.RESET}")

    @staticmethod
    def separator(char='─', width=80, color=Colors.BRIGHT_BLACK):
        """分隔线"""
        print(f"{color}{char * width}{Colors.RESET}")

    @staticmethod
    def header(text: str, color=Colors.BRIGHT_CYAN):
        """标题"""
        print(f"\n{color}{Colors.BOLD}▶ {text}{Colors.RESET}")

    @staticmethod
    def success(text: str):
        """成功消息"""
        print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} {text}")

    @staticmethod
    def error(text: str):
        """错误消息"""
        print(f"{Colors.BRIGHT_RED}✗{Colors.RESET} {text}")

    @staticmethod
    def warning(text: str):
        """警告消息"""
        print(f"{Colors.BRIGHT_YELLOW}⚠{Colors.RESET} {text}")

    @staticmethod
    def info(text: str):
        """信息消息"""
        print(f"{Colors.BRIGHT_BLUE}ℹ{Colors.RESET} {text}")

    @staticmethod
    def metric(label: str, value: str, color=Colors.BRIGHT_WHITE):
        """指标显示"""
        print(f"{Colors.DIM}{label}:{Colors.RESET} {color}{value}{Colors.RESET}")

    @staticmethod
    def progress_bar(percentage: float, width=30, color=Colors.BRIGHT_GREEN):
        """进度条"""
        filled = int(width * percentage)
        bar = '█' * filled + '░' * (width - filled)
        print(f"{color}{bar}{Colors.RESET} {percentage*100:.1f}%")

    @staticmethod
    def price_change(current: float, previous: float):
        """价格变化显示"""
        change = current - previous
        change_pct = (change / previous * 100) if previous > 0 else 0

        if change > 0:
            return f"{Colors.BRIGHT_GREEN}↑ ${current:.2f} (+{change_pct:.2f}%){Colors.RESET}"
        elif change < 0:
            return f"{Colors.BRIGHT_RED}↓ ${current:.2f} ({change_pct:.2f}%){Colors.RESET}"
        else:
            return f"{Colors.BRIGHT_WHITE}→ ${current:.2f} (0.00%){Colors.RESET}"

    @staticmethod
    def sparkline(values: List[float], width=20, height=5):
        """迷你图表"""
        if not values or len(values) < 2:
            return

        min_val = min(values)
        max_val = max(values)
        range_val = max_val - min_val if max_val > min_val else 1

        # 简化版本:使用ASCII字符
        chars = ['_', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█']

        line = ""
        for val in values[-width:]:
            normalized = (val - min_val) / range_val
            idx = int(normalized * (len(chars) - 1))
            line += chars[idx]

        print(f"{Colors.BRIGHT_CYAN}{line}{Colors.RESET}")

@dataclass
class Order:
    order_id: str
    side: str
    price: float
    quantity: float

@dataclass
class TradeStats:
    """交易统计"""
    total_trades: int = 0
    win_trades: int = 0
    loss_trades: int = 0
    total_profit: float = 0.0
    total_fees: float = 0.0
    net_profit: float = 0.0
    max_profit: float = 0.0
    max_loss: float = 0.0

    # 价格历史
    price_history: List[float] = None
    profit_history: List[float] = None

    def __post_init__(self):
        if self.price_history is None:
            self.price_history = []
        if self.profit_history is None:
            self.profit_history = []

    def add_price(self, price: float):
        self.price_history.append(price)
        if len(self.price_history) > 50:
            self.price_history.pop(0)

    def add_profit(self, profit: float):
        self.profit_history.append(self.net_profit)
        if len(self.profit_history) > 50:
            self.profit_history.pop(0)

class OptimizedClient:
    """优化客户端"""

    def __init__(self, api_key: str, secret_key: str, base_url: str):
        self.api_key = api_key
        self.secret_key = secret_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({'X-MBX-APIKEY': api_key})
        self.symbol_info = {}

        # 本地缓存
        self.price_cache = 0.0
        self.price_cache_time = 0
        self.balance_cache = {}
        self.balance_cache_time = 0

        # API权重监控
        self.api_weight = 0
        self.api_weight_reset_time = time.time() + 60

    def _sign(self, params: Dict) -> str:
        query_string = urlencode(params)
        return hmac.new(
            self.secret_key.encode('utf-8'),
            query_string.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()

    def _request(self, method: str, endpoint: str, params: Dict = None, signed: bool = False):
        if params is None:
            params = {}

        if signed:
            params['timestamp'] = int(time.time() * 1000)
            params['signature'] = self._sign(params)

        try:
            url = f"{self.base_url}{endpoint}"

            if method == 'GET':
                response = self.session.get(url, params=params, timeout=5)
            elif method == 'POST':
                response = self.session.post(url, params=params, timeout=5)
            elif method == 'DELETE':
                response = self.session.delete(url, params=params, timeout=5)
            else:
                return None

            # 监控API权重
            if 'x-mbx-used-weight-1m' in response.headers:
                self.api_weight = int(response.headers['x-mbx-used-weight-1m'])
                if self.api_weight > 1000:
                    UI.warning(f"API权重高: {self.api_weight}/1200")
                    time.sleep(1)

            response.raise_for_status()
            return response.json()

        except Exception as e:
            if 'marginType' not in endpoint:
                UI.error(f"API错误: {e}")
            return None

    def get_exchange_info(self, symbol: str) -> bool:
        data = self._request('GET', '/fapi/v1/exchangeInfo')
        if not data:
            return False

        for s in data.get('symbols', []):
            if s['symbol'] == symbol:
                self.symbol_info[symbol] = {
                    'pricePrecision': s['pricePrecision'],
                    'quantityPrecision': s['quantityPrecision'],
                }
                return True
        return False

    def format_price(self, symbol: str, price: float) -> str:
        precision = self.symbol_info.get(symbol, {}).get('pricePrecision', PRICE_PRECISION)
        price_decimal = Decimal(str(price))
        quantize_str = '0.' + '0' * (precision - 1) + '1'
        formatted = price_decimal.quantize(Decimal(quantize_str), rounding=ROUND_DOWN)
        return str(formatted)

    def format_quantity(self, symbol: str, quantity: float) -> str:
        precision = self.symbol_info.get(symbol, {}).get('quantityPrecision', QUANTITY_PRECISION)
        qty_decimal = Decimal(str(quantity))
        quantize_str = '0.' + '0' * (precision - 1) + '1'
        formatted = qty_decimal.quantize(Decimal(quantize_str), rounding=ROUND_DOWN)
        result = str(formatted).rstrip('0').rstrip('.')
        return result

    def set_leverage(self, symbol: str, leverage: int) -> bool:
        result = self._request('POST', '/fapi/v1/leverage', 
                              {'symbol': symbol, 'leverage': leverage}, signed=True)
        return result is not None

    def get_current_price(self, symbol: str) -> float:
        """带缓存的价格获取"""
        now = time.time()

        if now - self.price_cache_time < 5 and self.price_cache > 0:
            return self.price_cache

        data = self._request('GET', '/fapi/v1/ticker/price', {'symbol': symbol})
        if data:
            self.price_cache = float(data['price'])
            self.price_cache_time = now
            return self.price_cache

        return self.price_cache if self.price_cache > 0 else 0.0

    def get_account_balance(self) -> Dict:
        """带缓存的余额获取"""
        now = time.time()

        if now - self.balance_cache_time < 30 and self.balance_cache:
            return self.balance_cache

        data = self._request('GET', '/fapi/v2/balance', signed=True)
        if not data:
            return self.balance_cache

        for item in data:
            if item['asset'] == 'USDT':
                self.balance_cache = {
                    'total': float(item['balance']),
                    'available': float(item['availableBalance'])
                }
                self.balance_cache_time = now
                return self.balance_cache

        return {}

    def get_position(self, symbol: str) -> Dict:
        data = self._request('GET', '/fapi/v2/positionRisk', {'symbol': symbol}, signed=True)
        if not data or len(data) == 0:
            return {}

        pos = data[0]
        return {
            'positionAmt': float(pos['positionAmt']),
            'entryPrice': float(pos['entryPrice']),
            'unRealizedProfit': float(pos['unRealizedProfit'])
        }

    def place_limit_order(self, symbol: str, side: str, price: float, quantity: float) -> Optional[str]:
        formatted_price = self.format_price(symbol, price)
        formatted_qty = self.format_quantity(symbol, quantity)

        params = {
            'symbol': symbol,
            'side': side,
            'type': 'LIMIT',
            'timeInForce': 'GTC',
            'quantity': formatted_qty,
            'price': formatted_price,
        }

        result = self._request('POST', '/fapi/v1/order', params, signed=True)
        time.sleep(0.05)

        return str(result['orderId']) if result else None

    def place_batch_orders(self, orders: List[Dict]) -> List[Optional[str]]:
        """批量下单"""
        if len(orders) == 0:
            return []

        if len(orders) > 5:
            result_ids = []
            for i in range(0, len(orders), 5):
                batch = orders[i:i+5]
                ids = self._place_batch_internal(batch)
                result_ids.extend(ids)
                time.sleep(0.1)
            return result_ids
        else:
            return self._place_batch_internal(orders)

    def _place_batch_internal(self, orders: List[Dict]) -> List[Optional[str]]:
        batch_orders = []
        for order in orders:
            formatted_price = self.format_price(order['symbol'], order['price'])
            formatted_qty = self.format_quantity(order['symbol'], order['quantity'])

            batch_orders.append({
                'symbol': order['symbol'],
                'side': order['side'],
                'type': 'LIMIT',
                'timeInForce': 'GTC',
                'quantity': formatted_qty,
                'price': formatted_price,
            })

        params = {'batchOrders': json.dumps(batch_orders)}
        result = self._request('POST', '/fapi/v1/batchOrders', params, signed=True)

        if not result:
            return [None] * len(orders)

        return [str(r['orderId']) if 'orderId' in r else None for r in result]

    def get_open_orders(self, symbol: str) -> List[Dict]:
        data = self._request('GET', '/fapi/v1/openOrders', {'symbol': symbol}, signed=True)
        return data if data else []

    def cancel_order(self, symbol: str, order_id: str) -> bool:
        result = self._request('DELETE', '/fapi/v1/order',
                              {'symbol': symbol, 'orderId': order_id}, signed=True)
        return result is not None

    def cancel_all_orders(self, symbol: str) -> bool:
        result = self._request('DELETE', '/fapi/v1/allOpenOrders',
                              {'symbol': symbol}, signed=True)
        return result is not None

class SmartGridEngine:
    """智能网格引擎 - 带手续费计算"""

    def __init__(self, client: OptimizedClient, symbol: str):
        self.client = client
        self.symbol = symbol

        self.active_orders: Dict[str, Order] = {}
        self.pending_orders: List[Dict] = []

        # 统计数据
        self.stats = TradeStats()

        self.last_buy_price = 0.0
        self.last_sell_price = 0.0
        self.previous_price = 0.0

    def setup_grid(self, center_price: float):
        """设置网格"""
        UI.info(f"设置网格中心: ${center_price:.2f}")

        self.client.cancel_all_orders(self.symbol)
        self.active_orders.clear()

        quantity = ORDER_AMOUNT_USDT / center_price

        orders_to_place = []

        for i in range(1, NUM_GRIDS + 1):
            # 买单
            buy_price = center_price * (1 - GRID_SPREAD * i)
            orders_to_place.append({
                'symbol': self.symbol,
                'side': 'BUY',
                'price': buy_price,
                'quantity': quantity
            })

            # 卖单
            sell_price = center_price * (1 + GRID_SPREAD * i)
            orders_to_place.append({
                'symbol': self.symbol,
                'side': 'SELL',
                'price': sell_price,
                'quantity': quantity
            })

        UI.info(f"批量下单 {len(orders_to_place)} 个订单...")
        order_ids = self.client.place_batch_orders(orders_to_place)

        success_count = 0
        for i, order_id in enumerate(order_ids):
            if order_id:
                order_data = orders_to_place[i]
                self.active_orders[order_id] = Order(
                    order_id=order_id,
                    side=order_data['side'],
                    price=order_data['price'],
                    quantity=order_data['quantity']
                )
                success_count += 1

        UI.success(f"网格设置完成: {success_count}/{len(orders_to_place)} 订单激活")

    def check_and_refill(self):
        """检查并补充订单"""
        open_orders = self.client.get_open_orders(self.symbol)
        open_order_ids = {str(o['orderId']) for o in open_orders}

        filled_orders = []
        for order_id, order in list(self.active_orders.items()):
            if order_id not in open_order_ids:
                filled_orders.append(order)
                del self.active_orders[order_id]

        if filled_orders:
            self._handle_filled(filled_orders)

        if len(self.pending_orders) >= 4:
            self._flush_pending_orders()

    def _calculate_fees(self, price: float, quantity: float) -> float:
        """计算手续费"""
        trade_value = price * quantity
        return trade_value * DEFAULT_FEE

    def _handle_filled(self, filled: List[Order]):
        """处理成交 - 带手续费计算"""
        for order in filled:
            # 计算手续费
            fee = self._calculate_fees(order.price, order.quantity)
            self.stats.total_fees += fee

            self.stats.total_trades += 1

            side_icon = f"{Colors.BRIGHT_GREEN}BUY{Colors.RESET}" if order.side == 'BUY' else f"{Colors.BRIGHT_MAGENTA}SELL{Colors.RESET}"
            print(f"\n{side_icon} @ ${order.price:.2f} | 手续费: ${fee:.4f}")

            if order.side == 'BUY':
                self.last_buy_price = order.price

                if self.last_sell_price > 0:
                    # 毛利润
                    gross_profit = (self.last_sell_price - order.price) * order.quantity

                    # 扣除两次手续费 (之前的SELL + 现在的BUY)
                    previous_sell_fee = self._calculate_fees(self.last_sell_price, order.quantity)
                    net_profit = gross_profit - fee - previous_sell_fee

                    self.stats.total_profit += gross_profit
                    self.stats.net_profit += net_profit

                    if net_profit > 0:
                        self.stats.win_trades += 1
                        self.stats.max_profit = max(self.stats.max_profit, net_profit)
                        print(f"   {Colors.BRIGHT_GREEN}💰 净利润: ${net_profit:.4f}{Colors.RESET} (毛利: ${gross_profit:.4f}, 费用: ${fee + previous_sell_fee:.4f})")
                    else:
                        self.stats.loss_trades += 1
                        self.stats.max_loss = min(self.stats.max_loss, net_profit)
                        print(f"   {Colors.BRIGHT_RED}📉 亏损: ${net_profit:.4f}{Colors.RESET}")

                # 加入待补充队列
                self.pending_orders.append({
                    'symbol': self.symbol,
                    'side': 'SELL',
                    'price': order.price * (1 + GRID_SPREAD),
                    'quantity': order.quantity
                })

                self.pending_orders.append({
                    'symbol': self.symbol,
                    'side': 'BUY',
                    'price': order.price,
                    'quantity': order.quantity
                })

            elif order.side == 'SELL':
                self.last_sell_price = order.price

                if self.last_buy_price > 0:
                    # 毛利润
                    gross_profit = (order.price - self.last_buy_price) * order.quantity

                    # 扣除两次手续费 (之前的BUY + 现在的SELL)
                    previous_buy_fee = self._calculate_fees(self.last_buy_price, order.quantity)
                    net_profit = gross_profit - fee - previous_buy_fee

                    self.stats.total_profit += gross_profit
                    self.stats.net_profit += net_profit

                    if net_profit > 0:
                        self.stats.win_trades += 1
                        self.stats.max_profit = max(self.stats.max_profit, net_profit)
                        print(f"   {Colors.BRIGHT_GREEN}💰 净利润: ${net_profit:.4f}{Colors.RESET} (毛利: ${gross_profit:.4f}, 费用: ${fee + previous_buy_fee:.4f})")
                    else:
                        self.stats.loss_trades += 1
                        self.stats.max_loss = min(self.stats.max_loss, net_profit)
                        print(f"   {Colors.BRIGHT_RED}📉 亏损: ${net_profit:.4f}{Colors.RESET}")

                # 加入待补充队列
                self.pending_orders.append({
                    'symbol': self.symbol,
                    'side': 'BUY',
                    'price': order.price * (1 - GRID_SPREAD),
                    'quantity': order.quantity
                })

                self.pending_orders.append({
                    'symbol': self.symbol,
                    'side': 'SELL',
                    'price': order.price,
                    'quantity': order.quantity
                })

        # 立即批量补充
        self._flush_pending_orders()

        # 更新统计
        self.stats.add_profit(self.stats.net_profit)

        # 显示简要统计
        win_rate = (self.stats.win_trades / self.stats.total_trades * 100) if self.stats.total_trades > 0 else 0
        print(f"{Colors.BRIGHT_CYAN}📊 {self.stats.total_trades}笔 | 净利: ${self.stats.net_profit:.2f} | 胜率: {win_rate:.1f}% | {len(self.active_orders)}单{Colors.RESET}")

    def _flush_pending_orders(self):
        """批量补充订单"""
        if not self.pending_orders:
            return

        print(f"   {Colors.DIM}↻ 批量补充{len(self.pending_orders)}单...{Colors.RESET}")

        order_ids = self.client.place_batch_orders(self.pending_orders)

        for i, order_id in enumerate(order_ids):
            if order_id:
                order_data = self.pending_orders[i]
                self.active_orders[order_id] = Order(
                    order_id=order_id,
                    side=order_data['side'],
                    price=order_data['price'],
                    quantity=order_data['quantity']
                )

        self.pending_orders.clear()

class ProBot:
    """专业机器人"""

    def __init__(self, client: OptimizedClient, grid: SmartGridEngine):
        self.client = client
        self.grid = grid
        self.is_running = False
        self.session_start = datetime.now()
        self.last_rebalance = time.time()

    def initialize(self) -> bool:
        UI.header("初始化系统")

        if not self.client.get_exchange_info(SYMBOL):
            UI.error("无法获取交易对信息")
            return False

        # 检查持仓模式
        current_mode = self.client._request('GET', '/fapi/v1/positionSide/dual', signed=True)
        if current_mode:
            is_dual = current_mode.get('dualSidePosition', False)
            UI.success(f"持仓模式: {'双向' if is_dual else '单向'}")

        # 设置杠杆
        if self.client.set_leverage(SYMBOL, LEVERAGE):
            UI.success(f"杠杆设置: {LEVERAGE}x")

        # 检查余额
        balance = self.client.get_account_balance()
        if balance.get('total', 0) < 100:
            UI.error("余额不足 $100")
            return False
        UI.success(f"账户余额: ${balance['total']:.2f} USDT")

        # 获取当前价格
        price = self.client.get_current_price(SYMBOL)
        if price == 0:
            UI.error("无法获取价格")
            return False
        UI.success(f"{SYMBOL} 当前价格: ${price:.2f}")

        # 设置网格
        self.grid.setup_grid(price)
        self.grid.previous_price = price

        return True

    def display_dashboard(self):
        """显示仪表板"""
        UI.clear_screen()

        # 标题
        print(f"\n{Colors.BOLD}{Colors.BRIGHT_CYAN}╔════════════════════════════════════════════════════════════════════════════╗")
        print(f"║                    🐜 蚂蚁搬家 v3.0 PRO - 交易仪表板                       ║")
        print(f"╚════════════════════════════════════════════════════════════════════════════╝{Colors.RESET}\n")

        # 获取数据
        balance = self.client.get_account_balance()
        position = self.client.get_position(SYMBOL)
        price = self.client.get_current_price(SYMBOL)

        # 更新价格历史
        self.grid.stats.add_price(price)

        runtime = datetime.now() - self.session_start
        hours = runtime.total_seconds() / 3600

        # 系统状态
        UI.header("系统状态")
        UI.metric("运行时间", str(runtime).split('.')[0])
        UI.metric("API权重", f"{self.client.api_weight}/1200")

        # API权重进度条
        weight_pct = self.client.api_weight / 1200
        if weight_pct > 0.8:
            bar_color = Colors.BRIGHT_RED
        elif weight_pct > 0.6:
            bar_color = Colors.BRIGHT_YELLOW
        else:
            bar_color = Colors.BRIGHT_GREEN
        UI.progress_bar(weight_pct, width=40, color=bar_color)

        print()
        UI.separator()

        # 市场数据
        UI.header("市场数据")
        print(f"{Colors.DIM}当前价格:{Colors.RESET} {UI.price_change(price, self.grid.previous_price)}")

        # 价格迷你图
        if len(self.grid.stats.price_history) > 1:
            print(f"{Colors.DIM}价格趋势:{Colors.RESET} ", end="")
            UI.sparkline(self.grid.stats.price_history, width=30)

        self.grid.previous_price = price

        print()
        UI.separator()

        # 账户信息
        UI.header("账户信息")
        UI.metric("总余额", f"${balance.get('total', 0):.2f} USDT")
        UI.metric("可用余额", f"${balance.get('available', 0):.2f} USDT")
        UI.metric("持仓数量", f"{position.get('positionAmt', 0):.4f} ETH")
        UI.metric("持仓均价", f"${position.get('entryPrice', 0):.2f}")

        unrealized = position.get('unRealizedProfit', 0)
        if unrealized > 0:
            print(f"{Colors.DIM}未实现盈亏:{Colors.RESET} {Colors.BRIGHT_GREEN}+${unrealized:.2f}{Colors.RESET}")
        elif unrealized < 0:
            print(f"{Colors.DIM}未实现盈亏:{Colors.RESET} {Colors.BRIGHT_RED}${unrealized:.2f}{Colors.RESET}")
        else:
            print(f"{Colors.DIM}未实现盈亏:{Colors.RESET} ${unrealized:.2f}")

        print()
        UI.separator()

        # 交易统计
        UI.header("交易统计")
        UI.metric("总交易次数", f"{self.grid.stats.total_trades}")

        win_rate = (self.grid.stats.win_trades / self.grid.stats.total_trades * 100) if self.grid.stats.total_trades > 0 else 0
        if win_rate >= 60:
            wr_color = Colors.BRIGHT_GREEN
        elif win_rate >= 40:
            wr_color = Colors.BRIGHT_YELLOW
        else:
            wr_color = Colors.BRIGHT_RED

        print(f"{Colors.DIM}盈利/亏损:{Colors.RESET} {Colors.BRIGHT_GREEN}{self.grid.stats.win_trades}{Colors.RESET} / {Colors.BRIGHT_RED}{self.grid.stats.loss_trades}{Colors.RESET} ({wr_color}{win_rate:.1f}%{Colors.RESET})")

        # 利润显示
        gross = self.grid.stats.total_profit
        fees = self.grid.stats.total_fees
        net = self.grid.stats.net_profit

        if gross > 0:
            print(f"{Colors.DIM}毛利润:{Colors.RESET} {Colors.BRIGHT_GREEN}+${gross:.4f}{Colors.RESET}")
        else:
            print(f"{Colors.DIM}毛利润:{Colors.RESET} {Colors.BRIGHT_RED}${gross:.4f}{Colors.RESET}")

        print(f"{Colors.DIM}总手续费:{Colors.RESET} {Colors.BRIGHT_RED}-${fees:.4f}{Colors.RESET}")

        if net > 0:
            print(f"{Colors.DIM}净利润:{Colors.RESET} {Colors.BOLD}{Colors.BRIGHT_GREEN}+${net:.4f}{Colors.RESET}")
        else:
            print(f"{Colors.DIM}净利润:{Colors.RESET} {Colors.BOLD}{Colors.BRIGHT_RED}${net:.4f}{Colors.RESET}")

        # 利润趋势
        if len(self.grid.stats.profit_history) > 1:
            print(f"{Colors.DIM}利润趋势:{Colors.RESET} ", end="")
            UI.sparkline(self.grid.stats.profit_history, width=30)

        UI.metric("最大单笔盈利", f"${self.grid.stats.max_profit:.4f}")
        UI.metric("最大单笔亏损", f"${self.grid.stats.max_loss:.4f}")

        print()
        UI.separator()

        # 网格状态
        UI.header("网格状态")
        UI.metric("活跃订单", f"{len(self.grid.active_orders)}/{NUM_GRIDS * 2}")

        # 订单健康度
        order_health = len(self.grid.active_orders) / (NUM_GRIDS * 2)
        if order_health > 0.8:
            health_color = Colors.BRIGHT_GREEN
            health_text = "健康"
        elif order_health > 0.5:
            health_color = Colors.BRIGHT_YELLOW
            health_text = "良好"
        else:
            health_color = Colors.BRIGHT_RED
            health_text = "需要重新平衡"

        print(f"{Colors.DIM}网格健康度:{Colors.RESET} {health_color}{health_text}{Colors.RESET}")
        UI.progress_bar(order_health, width=40, color=health_color)

        print()
        UI.separator()

        # 性能指标
        if hours > 0:
            UI.header("性能指标")
            trades_per_hour = self.grid.stats.total_trades / hours
            profit_per_hour = net / hours

            UI.metric("交易频率", f"{trades_per_hour:.2f} 笔/小时")

            if profit_per_hour > 0:
                print(f"{Colors.DIM}时均利润:{Colors.RESET} {Colors.BRIGHT_GREEN}+${profit_per_hour:.4f}/小时{Colors.RESET}")
            else:
                print(f"{Colors.DIM}时均利润:{Colors.RESET} {Colors.BRIGHT_RED}${profit_per_hour:.4f}/小时{Colors.RESET}")

            # 预估日收益
            daily_profit = profit_per_hour * 24
            if daily_profit > 0:
                print(f"{Colors.DIM}预估日收益:{Colors.RESET} {Colors.BRIGHT_GREEN}+${daily_profit:.4f}{Colors.RESET}")
            else:
                print(f"{Colors.DIM}预估日收益:{Colors.RESET} {Colors.BRIGHT_RED}${daily_profit:.4f}{Colors.RESET}")

        print(f"\n{Colors.BRIGHT_BLACK}{'─' * 80}{Colors.RESET}")
        print(f"{Colors.DIM}最后更新: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | 按 Ctrl+C 停止{Colors.RESET}\n")

    def run(self):
        if not self.initialize():
            return

        self.is_running = True

        # 显示启动信息
        UI.clear_screen()
        UI.box(
            f"🚀 蚂蚁搬家 v3.0 PRO 已启动\n\n"
            f"交易对: {SYMBOL}\n"
            f"杠杆: {LEVERAGE}x\n"
            f"网格间距: {GRID_SPREAD*100:.2f}%\n"
            f"网格数量: {NUM_GRIDS}\n"
            f"订单金额: ${ORDER_AMOUNT_USDT}\n\n"
            f"✅ 手续费已计入计算 (Taker: {TAKER_FEE*100:.2f}%)\n"
            f"✅ 批量下单优化\n"
            f"✅ 智能缓存\n\n"
            f"正在运行...",
            color=Colors.BRIGHT_GREEN,
            width=80
        )

        time.sleep(3)

        last_check = time.time()
        last_display = time.time()

        while self.is_running:
            try:
                current_time = time.time()

                # 检查订单
                if current_time - last_check >= CHECK_INTERVAL:
                    last_check = current_time
                    self.grid.check_and_refill()

                # 更新显示
                if current_time - last_display >= DISPLAY_INTERVAL:
                    last_display = current_time
                    self.display_dashboard()

                # 重新平衡
                if current_time - self.last_rebalance >= 60:
                    self.last_rebalance = current_time
                    if len(self.grid.active_orders) < NUM_GRIDS:
                        UI.warning("网格订单不足,重新平衡...")
                        price = self.client.get_current_price(SYMBOL)
                        self.grid.setup_grid(price)

                time.sleep(0.5)

            except KeyboardInterrupt:
                print(f"\n\n{Colors.BRIGHT_YELLOW}⚠ 收到停止信号...{Colors.RESET}")
                break
            except Exception as e:
                UI.error(f"错误: {e}")
                time.sleep(5)

        self.stop()

    def stop(self):
        UI.header("停止交易")

        self.is_running = False
        self.client.cancel_all_orders(SYMBOL)

        runtime = datetime.now() - self.session_start

        # 最终统计
        print()
        UI.box(
            f"交易会话结束\n\n"
            f"运行时间: {str(runtime).split('.')[0]}\n"
            f"总交易: {self.grid.stats.total_trades} 笔\n"
            f"盈利交易: {self.grid.stats.win_trades} 笔\n"
            f"亏损交易: {self.grid.stats.loss_trades} 笔\n\n"
            f"毛利润: ${self.grid.stats.total_profit:.4f}\n"
            f"手续费: ${self.grid.stats.total_fees:.4f}\n"
            f"净利润: ${self.grid.stats.net_profit:.4f}",
            color=Colors.BRIGHT_CYAN,
            width=80
        )

        UI.success("系统已安全停止")

def main():
    UI.clear_screen()

    # 欢迎界面
    print(f"""
{Colors.BRIGHT_CYAN}{Colors.BOLD}
╔════════════════════════════════════════════════════════════════════════════╗
║                                                                            ║
║                     🐜 蚂蚁搬家 v3.0 PRO 专业版                            ║
║                                                                            ║
║                         现代化 · 可视化 · 智能化                           ║
║                                                                            ║
╚════════════════════════════════════════════════════════════════════════════╝
{Colors.RESET}
""")

    UI.header("系统特性")
    print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} 现代化科技感界面")
    print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} 实时数据可视化")
    print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} 手续费精确计算 (Maker: {MAKER_FEE*100:.2f}%, Taker: {TAKER_FEE*100:.2f}%)")
    print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} 批量下单优化 (降低90% API调用)")
    print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} 智能缓存机制")
    print(f"{Colors.BRIGHT_GREEN}✓{Colors.RESET} 性能监控仪表板")

    print()
    UI.separator()

    client = OptimizedClient(BINANCE_API_KEY, BINANCE_SECRET_KEY, BINANCE_BASE_URL)
    grid = SmartGridEngine(client, SYMBOL)

    UI.header("连接测试")
    price = client.get_current_price(SYMBOL)
    if price == 0:
        UI.error("无法连接到交易所")
        return

    UI.success(f"连接成功 - {SYMBOL} 价格: ${price:.2f}")

    print()
    UI.separator()

    UI.header("交易配置")
    UI.metric("交易对", SYMBOL)
    UI.metric("杠杆", f"{LEVERAGE}x")
    UI.metric("网格间距", f"{GRID_SPREAD*100:.2f}%")
    UI.metric("网格数量", f"{NUM_GRIDS}")
    UI.metric("订单金额", f"${ORDER_AMOUNT_USDT}")
    UI.metric("Maker手续费", f"{MAKER_FEE*100:.2f}%")
    UI.metric("Taker手续费", f"{TAKER_FEE*100:.2f}%")

    print()
    UI.separator()
    print()

    confirm = input(f"{Colors.BRIGHT_YELLOW}启动交易机器人? (yes/no): {Colors.RESET}")
    if confirm.lower() != 'yes':
        UI.info("已取消")
        return

    bot = ProBot(client, grid)

    try:
        bot.run()
    except KeyboardInterrupt:
        pass
    finally:
        print(f"\n{Colors.BRIGHT_GREEN}✓ 程序退出{Colors.RESET}\n")

if __name__ == '__main__':
    main()