Skill: hyy2099/aegisclaw (version 1.0.0)

--- name: aegisclaw description: "Use this skill when the user asks to manage Binance assets, check account security, scan for arbitrage opportunities, or perform automated dust sweeps. Commands: init, check, scan, arbitrage, dust, report, status. Requires BINANCE_API_KEY and BINANCE_API_SECRET environment variables." license: MIT metadata: author: hyy2099 version: "1.0.0" homepage: "https://github.com/hyy2099/aegisclaw" --- # AegisClaw - 金甲龙虾 (Binance Security & Profit Guardian) 🦞 A defensive AI agent based on the **principle of least privilege** and Binance sub-account ecosystem, focusing on low-risk automated asset management and arbitrage. ## When to Use This Skill Use this skill when the user asks to: - Check Binance account security status - Scan for idle assets and dust - Monitor funding rate arbitrage opportunities - Perform dust sweeps (convert small balances to BNB) - Generate weekly profit reports - Initialize or configure Binance API connection ## Commands | Command | Description | Example | |---------|-------------|---------| | `init <api_key> <api_secret>` | Initialize plugin with Binance API credentials | `/aegisclaw init key secret` | | `check` | Run security fence check | `/aegisclaw check` | | `scan` | Scan idle assets and dust | `/aegisclaw scan` | | `arbitrage` | Scan funding rate arbitrage opportunities | `/aegisclaw arbitrage` | | `dust [assets]` | Execute dust sweep (convert small balances) | `/aegisclaw dust` | | `report` | Generate weekly profit report | `/aegisclaw report` | | `status` | View current status | `/aegisclaw status` | | `help` | Display help information | `/aegisclaw help` | ## Required Environment Variables The skill requires the following environment variables (set via `.env` file or system environment): - `BINANCE_API_KEY` - Binance API Key (required) - `BINANCE_API_SECRET` - Binance API Secret (required) - `BINANCE_TESTNET` - Whether to use testnet (optional, default: false) ## Key Features ### 🛡️ Security Fence - **Sub-account sandbox isolation** - Recommended to use independent sub-accounts - **API permission self-check** - Automatically detect and warn of dangerous permission configurations - **Operation firewall** - Slippage limits, trading frequency control ### 💰 Profit Engine - **Launchpool/Megadrop monitoring** - Intelligent scan for new mining opportunities - **Automatic dust conversion** - Automatically convert small assets to BNB (Dust Sweeper) - **Funding rate arbitrage** - Risk-free arbitrage between spot and futures ### 📊 Data Statistics - **Balance snapshot recording** - Automatically save daily asset snapshots - **Trade history tracking** - SQLite database persistence - **Weekly profit reports** - One-click generate and share profit reports ## Security Recommendations 1. **Use Sub-accounts**: Create a sub-account with only 500-1000 USDT for operations. Do not use main accounts. 2. **Limit API Permissions**: - ✅ Enable: Spot Trading (SPOT) - ❌ Disable: Withdrawals (WITHDRAW) - ❌ Disable: Futures Trading (FUTURES) 3. **Bind IP Whitelist**: Restrict API to access from specific IPs only. Regularly check IP whitelist. 4. **Control Fund Scale**: Sub-account funds recommended within 1000 USDT. Use idle funds that won't affect daily life. ## Usage Flow ### Initial Setup 1. Initialize with API credentials: `/aegisclaw init <api_key> <api_secret>` 2. Run security check: `/aegisclaw check` 3. Verify account type and permissions ### Daily Operations 1. Scan assets: `/aegisclaw scan` 2. Check arbitrage opportunities: `/aegisclaw arbitrage` 3. Execute dust sweep if needed: `/aegisclaw dust` ### Weekly Review 1. Generate weekly report: `/aegisclaw report` 2. Review profit/loss and asset distribution ## Error Handling - **Invalid API credentials**: The skill will report initialization failure and prompt to check API key and secret - **Permission denied**: If API lacks required permissions, the skill will warn and suggest adjusting settings - **Rate limit exceeded**: The skill will notify you to retry later - **Network error**: The skill will attempt one retry before asking user to try again later ## Integration Notes This skill integrates with OpenClaw through the plugin interface in `openclaw_plugin/plugin.py`. It can be called via: - Direct commands in chat interfaces - Scheduled tasks via cron jobs - Automated workflows with other skills ## Key Safety Points - Never share or expose API keys or secrets in logs or user-facing messages - Always validate permissions before executing trading operations - Use sub-accounts with limited funds for safety - Monitor account balance regularly and set reasonable limits - This skill is designed for low-risk operations - avoid high-risk trading strategies ## Repository & Support - **GitHub**: https://github.com/hyy2099/aegisclaw - **License**: MIT - **Author**: hyy2099 🦞 **AegisClaw** - Your Binance risk-free profit guardian and asset protector

path: clawhub.json
content: {
  "name": "aegisclaw",
  "version": "1.0.0",
  "description": "🦞 金甲龙虾 - 币安安全赚币与护境神将。基于最小权限原则的防御型 AI 代理，专注低风险套利与全自动赚取 BNB。",
  "author": "hyy2099",
  "repository": "https://github.com/hyy2099/aegisclaw",
  "main": "openclaw_plugin/plugin.py",
  "entry": "main.py",
  "dependencies": [
    "requests>=2.31.0",
    "python-dotenv>=1.0.0",
    "python-dateutil>=2.8.2"
  ],
  "keywords": [
    "binance",
    "trading",
    "arbitrage",
    "security",
    "ai",
    "cryptocurrency",
    "bnb",
    "launchpool",
    "funding-rate"
  ],
  "commands": {
    "init": "初始化插件: /aegisclaw init <api_key> <api_secret>",
    "check": "运行安全围栏检查",
    "scan": "扫描闲置资产和零钱",
    "arbitrage": "扫描资金费率套利机会",
    "dust": "执行零钱兑换",
    "report": "生成周收益战报",
    "status": "查看当前状态",
    "help": "显示帮助信息"
  },
  "environment": {
    "BINANCE_API_KEY": "Binance API Key（必需）",
    "BINANCE_API_SECRET": "Binance API Secret（必需）",
    "BINANCE_TESTNET": "是否使用测试网（可选，默认false）"
  },
  "permissions": [
    "network",
    "storage"
  ]
}


path: CLAWHUB.md
content: # 🦞 金甲龙虾 - ClawHub 上传指南

## 📋 上传前准备

### 1. 安装 ClawHub CLI

如果你还没有安装 clawhub CLI，请先安装：

```bash
# 通过 npm 安装
npm install -g @openclaw/cli

# 或通过 pip 安装
pip install clawhub
```

### 2. 登录 ClawHub

```bash
clawhub login
```

输入你的账号：
- 用户名: ``
- 密码: （你的密码）

或者使用 token 登录：
```bash
clawhub login --token=
```

## 📤 上传项目

### 方法一：通过命令行上传

```bash
cd C:\Users\Administrator\aegisclaw

# 发布到 ClawHub
clawhub publish
```

### 方法二：通过网页上传

1. 访问：https://clawhub.ai
2. 登录（使用 ``）
3. 点击 "Upload Plugin"
4. 填写信息：
   - **Name**: aegisclaw
   - **Version**: 1.0.0
   - **Description**: 🦞 金甲龙虾 - 币安安全赚币与护境神将。基于最小权限原则的防御型 AI 代理，专注低风险套利与全自动赚取 BNB。
   - **Repository URL**: https://github.com/hyy2099/aegisclaw （或留空）
   - **Main File**: openclaw_plugin/plugin.py
   - **Entry Point**: main.py
   - **Keywords**: binance, trading, arbitrage, security, ai, cryptocurrency, bnb, launchpool
   - **Permissions**: network, storage
5. 上传项目文件夹（包含所有源代码）
6. 点击 "Publish"

## 📂 项目文件清单

确保以下文件在项目根目录：

```
aegisclaw/
├── clawhub.json          # ClawHub 配置文件（必需）
├── setup.py              # Python 安装配置
├── requirements.txt       # Python 依赖
├── README.md             # 项目文档
├── .env.example          # 环境变量模板
├── main.py              # CLI 入口
├── config.py            # 配置管理
├── core/                # 核心模块
│   ├── __init__.py
│   ├── api_client.py
│   ├── security_checker.py
│   ├── asset_scanner.py
│   ├── funding_arbitrage.py
│   └── report_generator.py
├── db/                  # 数据库模块
│   ├── __init__.py
│   └── database.py
└── openclaw_plugin/     # OpenClaw 插件
    ├── __init__.py
    └── plugin.py
```

## 🚀 安装方式

### 在 OpenClaw 中安装

用户可以通过以下命令一键安装：

```bash
# 在 OpenClaw CLI 中
plugin install aegisclaw

# 或搜索安装
plugin search aegisclaw
plugin install
```

### 独立安装

```bash
# 克隆项目
git clone https://github.com/hyy2099/aegisclaw.git

# 安装依赖
pip install -r requirements.txt

# 运行
python main.py --help
```

## 📖 使用说明

### 环境变量配置

用户需要在 `.env` 文件中配置：

```env
BINANCE_API_KEY=你的_api_key
BINANCE_API_SECRET=你的_api_secret
BINANCE_TESTNET=false
```

### 命令列表

| 命令 | 说明 |
|--------|------|
| `init <key> <secret>` | 初始化插件 |
| `check` | 运行安全围栏检查 |
| `scan` | 扫描闲置资产和零钱 |
| `arbitrage` | 扫描资金费率套利机会 |
| `dust [assets]` | 执行零钱兑换 |
| `report` | 生成周收益战报 |
| `status` | 查看当前状态 |
| `help` | 显示帮助信息 |

## 🎯 上传后的推广

### 社交媒体分享

```
🦞 金甲龙虾 - 币安安全赚币与护境神将

✨ 核心功能：
🛡️ 安全围栏检查 - AI 主动拒绝越权
💰 资产管理 - 闲置资金扫描、零钱兑换
📈 套利检测 - 资金费率无风险套利
📊 收益统计 - 周报生成与分享

🚀 一键安装: plugin install aegisclaw

#AIBinance #币安 #BNB #AI套利 #金甲龙虾

链接: https://clawhub.ai/plugins/aegisclaw
```

### README 添加到项目

在你的 GitHub 仓库 README.md 中添加：

```markdown
## 📦 安装

### OpenClaw (推荐)
```bash
plugin install aegisclaw
```

### 独立运行
```bash
pip install -r requirements.txt
python main.py --help
```
```

---

**上传完成后，用户就可以在 OpenClaw 中通过 `plugin install aegisclaw` 一键安装了！** 🎉


path: config.py
content: """
金甲龙虾 (AegisClaw) 配置文件
"""

import os
from pathlib import Path
from dataclasses import dataclass, field
from typing import List

# 加载 .env 文件
env_path = Path(__file__).parent / ".env"
if env_path.exists():
    from dotenv import load_dotenv
    load_dotenv(env_path)

@dataclass
class BinanceConfig:
    """币安 API 配置"""
    api_key: str = os.getenv("BINANCE_API_KEY", "")
    api_secret: str = os.getenv("BINANCE_API_SECRET", "")
    testnet: bool = False
    # 安全配置
    max_daily_trades: int = 10
    max_price_slippage: float = 0.01  # 1%
    allowed_ip_whitelist: List[str] = field(default_factory=list)
    # 禁用的危险权限
    forbidden_permissions: List[str] = field(default_factory=lambda: ["ENABLE_WITHDRAWALS", "PERMIT_UNIVERSAL_TRANSFER"])

@dataclass
class StrategyConfig:
    """策略配置"""
    # 资金费率套利阈值
    funding_rate_threshold: float = 0.0001  # 0.01%
    min_arbitrage_profit: float = 0.001  # 0.1%
    # Launchpool 最小参与金额
    min_launchpool_amount: float = 10.0  # USDT
    # Dust Sweeper 最小兑换阈值
    min_dust_threshold: float = 10.0  # USDT 等值

@dataclass
class DatabaseConfig:
    """数据库配置"""
    path: str = "db/aegisclaw.db"

@dataclass
class TelegramConfig:
    """Telegram 配置"""
    bot_token: str = os.getenv("TELEGRAM_BOT_TOKEN", "")
    chat_id: str = os.getenv("TELEGRAM_CHAT_ID", "")

class Config:
    """主配置类"""
    binance = BinanceConfig()
    strategy = StrategyConfig()
    database = DatabaseConfig()
    telegram = TelegramConfig()

    @classmethod
    def validate(cls) -> bool:
        """验证必要配置"""
        if not cls.binance.api_key or not cls.binance.api_secret:
            return False
        return True

# 默认配置
config = Config()


path: core/api_client.py
content: """
币安 API 客户端 - 封装币安 API 调用
"""

import hmac
import hashlib
import os
import time
import requests
from typing import Dict, List, Optional, Any
from config import BinanceConfig


class BinanceAPIClient:
    """币安 API 客户端"""

    def __init__(self, config: BinanceConfig):
        self.[REDACTED_SECRET]
        self.api_secret = config.api_secret
        self.testnet = config.testnet

        # 支持多个 API URL 配置
        self.api_urls = {
            "main": "https://api.binance.com",
            "main_futures": "https://fapi.binance.com",
            "test": "https://testnet.binance.vision",
            "test_futures": "https://testnet.binancefuture.com"
        }

        # 根据配置选择 base_url
        if self.testnet:
            self.base_url = self.api_urls["test"]
        else:
            self.base_url = self.api_urls["main"]

        # 创建多个 session
        self.session = requests.Session()
        self.futures_session = requests.Session()

        # 设置 headers
        headers = {
            "X-MBX-APIKEY": self.api_key,
            "Content-Type": "application/json"
        }

        self.session.headers.update(headers)
        self.futures_session.headers.update(headers)

        # 配置代理和超时
        self._setup_session(self.session)
        self._setup_session(self.futures_session)

        # 超时设置
        self.timeout = 30

    def _setup_session(self, session):
        """设置 session 参数"""
        proxies = self._get_proxies()
        if proxies:
            session.proxies = proxies

        # 重试配置
        from requests.adapters import HTTPAdapter
        from urllib3.util.retry import Retry

        retry = Retry(
            total=3,
            backoff_factor=1,
            status_forcelist=[500, 502, 503, 504]
        )
        adapter = HTTPAdapter(max_retries=retry)
        session.mount('http://', adapter)
        session.mount('https://', adapter)

    def _get_proxies(self):
        """获取代理配置"""
        # 1. 从环境变量获取
        env_proxies = os.getenv("HTTPS_PROXY") or os.getenv("HTTP_PROXY")
        if env_proxies:
            return {
                "http": env_proxies,
                "https": env_proxies
            }

        # 2. 从配置文件获取（新增）
        proxy_config = getattr(self, 'proxy_url', None)
        if proxy_config:
            return {
                "http": proxy_config,
                "https": proxy_config
            }

        return None

    def _generate_signature(self, params: Dict) -> str:
        """生成签名"""
        # 创建参数字符串，按照字母顺序排列
        sorted_params = sorted(params.items())
        query_string = "&".join([f"{k}={v}" for k, v in sorted_params])
        signature = hmac.new(
            self.api_secret.encode(),
            query_string.encode(),
            hashlib.sha256
        ).hexdigest()
        return signature

    def _request(self, method: str, endpoint: str, params: Dict = None, signed: bool = False, use_futures: bool = False) -> Dict:
        """发送 API 请求"""
        if params is None:
            params = {}

        if signed:
            params["timestamp"] = int(time.time() * 1000)
            params["signature"] = self._generate_signature(params)

        url = f"{self.base_url}{endpoint}"
        session = self.futures_session if use_futures else self.session

        try:
            if method == "GET":
                response = session.get(url, params=params, timeout=self.timeout)
            elif method == "POST":
                response = session.post(url, params=params, timeout=self.timeout)
            elif method == "DELETE":
                response = session.delete(url, params=params, timeout=self.timeout)
            else:
                raise ValueError(f"Unsupported method: {method}")

            response.raise_for_status()
            return response.json()

        except requests.exceptions.HTTPError as e:
            error_detail = e.response.json() if e.response.content else {}
            raise Exception(f"API Error: {e} - {error_detail}")
        except requests.exceptions.Timeout:
            raise Exception(f"Request timeout: {self.timeout} seconds")
        except requests.exceptions.ProxyError:
            raise Exception("Proxy error - check proxy configuration")
        except requests.exceptions.ConnectionError as e:
            raise Exception(f"Connection error: {e}")
        except Exception as e:
            raise Exception(f"Request failed: {e}")

    # ========== 公共接口 ==========

    def get_server_time(self) -> int:
        """获取服务器时间"""
        return self._request("GET", "/api/v3/time")["serverTime"]

    def ping(self) -> bool:
        """测试连接"""
        try:
            self._request("GET", "/api/v3/ping")
            return True
        except:
            return False

    def get_exchange_info(self, symbol: str = None) -> Dict:
        """获取交易规则和交易对信息"""
        params = {}
        if symbol:
            params["symbol"] = symbol
        return self._request("GET", "/api/v3/exchangeInfo", params)

    def get_symbol_ticker(self, symbol: str) -> Dict:
        """获取最新价格"""
        return self._request("GET", "/api/v3/ticker/price", {"symbol": symbol})

    def get_24h_ticker(self, symbol: str = None) -> Dict:
        """24小时价格变化情况"""
        params = {}
        if symbol:
            params["symbol"] = symbol
        return self._request("GET", "/api/v3/ticker/24hr", params)

    def get_orderbook(self, symbol: str, limit: int = 20) -> Dict:
        """获取订单簿深度"""
        return self._request("GET", "/api/v3/depth", {"symbol": symbol, "limit": limit})

    def get_klines(self, symbol: str, interval: str = "1h", limit: int = 100) -> List:
        """获取K线数据"""
        return self._request("GET", "/api/v3/klines", {
            "symbol": symbol,
            "interval": interval,
            "limit": limit
        })

    # ========== 需要签名的接口 ==========

    def get_account(self) -> Dict:
        """获取账户信息"""
        return self._request("GET", "/api/v3/account", signed=True)

    def get_balances(self) -> List[Dict]:
        """获取所有资产余额"""
        account = self.get_account()
        balances = []
        for b in account["balances"]:
            # 安全转换，处理字符串和数字格式
            try:
                free = float(b["free"]) if b["free"] else 0
                locked = float(b["locked"]) if b["locked"] else 0
                total = free + locked
            except (ValueError, TypeError):
                # 如果转换失败，跳过该资产
                continue

            if total > 0:
                balances.append({
                    "asset": b["asset"],
                    "free": free,
                    "locked": locked,
                    "total": total
                })
        return balances

    def get_trade_fee(self, symbol: str = None) -> Dict:
        """获取交易手续费"""
        params = {}
        if symbol:
            params["symbol"] = symbol
        return self._request("GET", "/sapi/v1/asset/tradeFee", params, signed=True)

    def get_asset_detail(self) -> Dict:
        """获取资产详情（最小交易量等）"""
        return self._request("GET", "/sapi/v1/asset/assetDetail", signed=True)

    def dust_transfer(self, assets: List[str]) -> Dict:
        """小额资产兑换 BNB (Dust Sweep)"""
        return self._request("POST", "/sapi/v1/asset/dust", {
            "asset": ",".join(assets)
        }, signed=True)

    def dust_btc(self, assets: List[str]) -> Dict:
        """小额资产兑换 BTC"""
        return self._request("POST", "/sapi/v1/asset/dust-btc", {
            "assets": ",".join(assets)
        }, signed=True)

    # ========== 资金费率相关 (合约) ==========

    def get_funding_rate(self, symbol: str = None) -> List[Dict]:
        """获取资金费率"""
        params = {}
        if symbol:
            params["symbol"] = symbol
        # 使用专门的 futures session
        url = f"{self.api_urls['main_futures']}/fapi/v1/fundingRate"
        response = self.futures_session.get(url, params=params, timeout=self.timeout)
        response.raise_for_status()
        return response.json()

    def get_premium_index(self, symbol: str = None) -> Dict:
        """获取标记价格和资金费率"""
        params = {}
        if symbol:
            params["symbol"] = symbol
        url = f"{self.api_urls['main_futures']}/fapi/v1/premiumIndex"
        response = self.futures_session.get(url, params=params, timeout=self.timeout)
        response.raise_for_status()
        return response.json()

    # ========== 现货交易 ==========

    def new_order(self, symbol: str, side: str, order_type: str, quantity: float,
                  price: float = None, time_in_force: str = "GTC") -> Dict:
        """下单"""
        params = {
            "symbol": symbol,
            "side": side,
            "type": order_type,
            "quantity": quantity,
            "newOrderRespType": "FULL"
        }
        if price:
            params["price"] = price
            params["timeInForce"] = time_in_force

        return self._request("POST", "/api/v3/order", params, signed=True)

    def cancel_order(self, symbol: str, order_id: int = None, client_order_id: str = None) -> Dict:
        """取消订单"""
        params = {"symbol": symbol}
        if order_id:
            params["orderId"] = order_id
        if client_order_id:
            params["origClientOrderId"] = client_order_id
        return self._request("DELETE", "/api/v3/order", params, signed=True)

    def get_open_orders(self, symbol: str = None) -> List[Dict]:
        """获取当前挂单"""
        params = {}
        if symbol:
            params["symbol"] = symbol
        return self._request("GET", "/api/v3/openOrders", params, signed=True)

    def get_my_trades(self, symbol: str, limit: int = 100) -> List[Dict]:
        """获取历史成交"""
        return self._request("GET", "/api/v3/myTrades", {
            "symbol": symbol,
            "limit": limit
        }, signed=True)


path: core/asset_scanner.py
content: """
资产扫描模块 - 检测闲置资金和零钱兑换
"""

from typing import Dict, List, Optional
from core.api_client import BinanceAPIClient
from config import StrategyConfig


class AssetScanner:
    """资产扫描器 - 检测闲置资金和零钱"""

    def __init__(self, api_client: BinanceAPIClient, config: StrategyConfig):
        self.api_client = api_client
        self.config = config

    def scan_idle_assets(self, min_idle_usdt: float = 5.0) -> Dict[str, any]:
        """扫描闲置资产"""
        result = {
            "idle_usdt": 0.0,
            "idle_fdusd": 0.0,
            "idle_total": 0.0,
            "dust_assets": [],
            "dust_total_value": 0.0,
            "suggestions": []
        }

        try:
            balances = self.api_client.get_balances()
            asset_detail = self.api_client.get_asset_detail()

            # 扫描闲置稳定币
            for b in balances:
                if b["asset"] == "USDT":
                    idle = b["free"]
                    if idle >= min_idle_usdt:
                        result["idle_usdt"] = idle
                        result["idle_total"] += idle
                        if idle >= self.config.min_launchpool_amount:
                            result["suggestions"].append({
                                "type": "launchpool",
                                "asset": "USDT",
                                "amount": idle,
                                "message": f"检测到 {idle:.2f} USDT 闲置，可参与 Launchpool 赚取新币"
                            })

                elif b["asset"] == "FDUSD":
                    idle = b["free"]
                    if idle >= min_idle_usdt:
                        result["idle_fdusd"] = idle
                        result["idle_total"] += idle
                        if idle >= self.config.min_launchpool_amount:
                            result["suggestions"].append({
                                "type": "launchpool",
                                "asset": "FDUSD",
                                "amount": idle,
                                "message": f"检测到 {idle:.2f} FDUSD 闲置，可参与 Launchpool 赚取新币"
                            })

            # 扫描零钱（小额资产）
            dust_assets = self._scan_dust_assets(balances, asset_detail)
            result["dust_assets"] = dust_assets["assets"]
            result["dust_total_value"] = dust_assets["total_value"]

            if result["dust_total_value"] >= self.config.min_dust_threshold:
                result["suggestions"].append({
                    "type": "dust_sweep",
                    "assets": dust_assets["asset_list"],
                    "total_value": result["dust_total_value"],
                    "message": f"发现 {len(dust_assets['asset_list'])} 种零钱，总价值约 ${result['dust_total_value']:.2f}，建议兑换为 BNB"
                })

        except Exception as e:
            result["error"] = str(e)

        return result

    def _scan_dust_assets(self, balances: List[Dict], asset_detail: Dict) -> Dict:
        """扫描可兑换的零钱资产"""
        dust_assets = {
            "assets": [],
            "asset_list": [],
            "total_value": 0.0
        }

        # 获取 BNB/USDT 价格用于估值
        try:
            bnb_price = float(self.api_client.get_symbol_ticker("BNBUSDT")["price"])
        except:
            bnb_price = 300.0  # 默认估值

        for b in balances:
            asset = b["asset"]
            total = b["total"]

            # 跳过主要资产
            if asset in ["USDT", "FDUSD", "BNB", "BTC", "ETH"]:
                continue

            # 检查是否为零钱（通过资产详情获取最小交易量）
            asset_info = asset_detail.get(asset, {})
            min_trade = float(asset_info.get("minTradeAmount", 5))

            if total < min_trade:
                # 获取当前价格估算价值
                try:
                    price = float(self.api_client.get_symbol_ticker(f"{asset}USDT")["price"])
                    usdt_value = total * price
                except:
                    # 尝试通过 BNB 交易对
                    try:
                        price = float(self.api_client.get_symbol_ticker(f"{asset}BNB")["price"])
                        usdt_value = total * price * bnb_price
                    except:
                        usdt_value = 0

                if usdt_value > 0:
                    dust_assets["assets"].append({
                        "asset": asset,
                        "amount": total,
                        "usdt_value": usdt_value
                    })
                    dust_assets["asset_list"].append(asset)
                    dust_assets["total_value"] += usdt_value

        return dust_assets

    def execute_dust_sweep(self, assets: List[str] = None) -> Dict:
        """执行零钱兑换"""
        if assets is None:
            scan = self.scan_idle_assets()
            assets = [a["asset"] for a in scan.get("dust_assets", [])]

        if not assets:
            return {"success": False, "message": "没有可兑换的零钱"}

        try:
            # 使用 dust_transfer 接口兑换为 BNB
            result = self.api_client.dust_transfer(assets)
            return {
                "success": True,
                "result": result,
                "message": f"已将 {', '.join(assets)} 兑换为 BNB"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"兑换失败: {str(e)}"
            }

    def get_launchpool_opportunities(self) -> List[Dict]:
        """获取 Launchpool 机会（需要调用 Launchpool API）"""
        opportunities = []

        try:
            # 币安 Launchpool API
            url = f"{self.api_client.base_url}/sapi/v1/launchpool/project/list"
            response = self.api_client.session.get(url)
            if response.status_code == 200:
                data = response.json()
                for project in data:
                    # 只返回进行中的项目
                    if project.get("status") == "ongoing":
                        opportunities.append({
                            "id": project.get("id"),
                            "name": project.get("projectName"),
                            "token": project.get("token"),
                            "start_time": project.get("startTime"),
                            "end_time": project.get("endTime"),
                            "total_reward": project.get("totalReward"),
                            "quotas": project.get("quotas", [])
                        })
        except Exception as e:
            print(f"获取 Launchpool 信息失败: {e}")

        return opportunities

    def format_report(self, scan_result: Dict) -> str:
        """格式化资产扫描报告"""
        report = "📊 资产扫描报告\n"
        report += "=" * 40 + "\n\n"

        if scan_result.get("error"):
            report += f"❌ 扫描失败: {scan_result['error']}\n"
            return report

        # 闲置资金
        report += "💰 闲置资金:\n"
        if scan_result["idle_usdt"] > 0:
            report += f"  • USDT: ${scan_result['idle_usdt']:.2f}\n"
        if scan_result["idle_fdusd"] > 0:
            report += f"  • FDUSD: ${scan_result['idle_fdusd']:.2f}\n"
        report += f"  • 总计: ${scan_result['idle_total']:.2f}\n\n"

        # 零钱资产
        if scan_result["dust_assets"]:
            report += "🧹 零钱资产:\n"
            for d in scan_result["dust_assets"]:
                report += f"  • {d['asset']}: {d['amount']:.6f} (~${d['usdt_value']:.2f})\n"
            report += f"  • 总价值: ${scan_result['dust_total_value']:.2f}\n\n"

        # 建议
        if scan_result["suggestions"]:
            report += "💡 建议:\n"
            for s in scan_result["suggestions"]:
                if s["type"] == "launchpool":
                    report += f"  🚀 {s['message']}\n"
                elif s["type"] == "dust_sweep":
                    report += f"  🧹 {s['message']}\n"
                    report += f"     资产: {', '.join(s['assets'])}\n"

        return report


path: core/funding_arbitrage.py
content: """
资金费率套利模块 - 检测套利机会
"""

from typing import Dict, List, Optional
from core.api_client import BinanceAPIClient
from config import StrategyConfig


class FundingArbitrage:
    """资金费率套利检测器"""

    def __init__(self, api_client: BinanceAPIClient, config: StrategyConfig):
        self.api_client = api_client
        self.config = config

    def scan_arbitrage_opportunities(self, symbols: List[str] = None) -> List[Dict]:
        """扫描套利机会"""
        opportunities = []

        try:
            # 获取资金费率数据
            funding_data = self.api_client.get_funding_rate()

            for item in funding_data:
                symbol = item["symbol"]
                funding_rate = float(item["fundingRate"])
                mark_price = float(item["markPrice"])

                # 筛选高费率机会
                if abs(funding_rate) >= self.config.funding_rate_threshold:
                    # 获取现货价格
                    try:
                        ticker = self.api_client.get_symbol_ticker(symbol.replace("USDT", "USDT"))
                        spot_price = float(ticker["price"])

                        # 计算价格偏差
                        price_diff_pct = (mark_price - spot_price) / spot_price * 100

                        # 计算预计利润
                        estimated_profit = abs(funding_rate) * 100  # 转换为百分比

                        # 判断是否有套利价值
                        if estimated_profit >= self.config.min_arbitrage_profit * 100:
                            opportunities.append({
                                "symbol": symbol,
                                "spot_price": spot_price,
                                "mark_price": mark_price,
                                "funding_rate": funding_rate,
                                "funding_rate_pct": funding_rate * 100,
                                "price_diff_pct": price_diff_pct,
                                "estimated_profit_pct": estimated_profit,
                                "direction": "long_funding" if funding_rate > 0 else "short_funding",
                                "next_funding_time": item.get("nextFundingTime"),
                                "recommendation": self._get_recommendation(funding_rate, price_diff_pct)
                            })
                    except Exception:
                        # 单个交易对获取失败时跳过
                        pass
        except Exception as e:
            print(f"扫描套利机会失败: {e}")

        # 按利润排序
        opportunities.sort(key=lambda x: x["estimated_profit_pct"], reverse=True)
        return opportunities

    def _get_recommendation(self, funding_rate: float, price_diff_pct: float) -> str:
        """获取操作建议"""
        if funding_rate > 0:
            return f"做多现货，做空合约，收取 {funding_rate*100:.4f}% 资金费"
        else:
            return f"做空现货，做多合约，收取 {-funding_rate*100:.4f}% 资金费"

    def format_report(self, opportunities: List[Dict], top_n: int = 10) -> str:
        """格式化套利报告"""
        report = "📈 资金费率套利机会\n"
        report += "=" * 50 + "\n\n"

        if not opportunities:
            report += "暂无高价值套利机会\n"
            report += f"当前检测阈值: 资金费率 ≥ {self.config.funding_rate_threshold*100:.2f}%\n"
            report += f"最小利润要求: {self.config.min_arbitrage_profit*100:.2f}%\n"
            return report

        top = opportunities[:top_n]
        for i, opp in enumerate(top, 1):
            direction_emoji = "📈" if opp["funding_rate"] > 0 else "📉"

            report += f"{i}. {direction_emoji} {opp['symbol']}\n"
            report += f"   资金费率: {opp['funding_rate_pct']:+.4f}%\n"
            report += f"   现货价格: ${opp['spot_price']:.4f}\n"
            report += f"   标记价格: ${opp['mark_price']:.4f}\n"
            report += f"   价格偏差: {opp['price_diff_pct']:+.2f}%\n"
            report += f"   预计收益: {opp['estimated_profit_pct']:.4f}%\n"
            report += f"   操作建议: {opp['recommendation']}\n\n"

        report += f"⚠️ 提醒: 套利有风险，请使用子账户并控制仓位\n"

        return report


path: core/report_generator.py
content: """
战报生成模块 - 生成收益统计和海报
"""

from typing import Dict, List, Optional
from datetime import datetime, timedelta
from core.api_client import BinanceAPIClient
from db.database import Database


class ReportGenerator:
    """战报生成器 - 生成收益统计和分享内容"""

    def __init__(self, api_client: BinanceAPIClient, database: Database):
        self.api_client = api_client
        self.db = database

    def generate_weekly_report(self) -> Dict:
        """生成周报"""
        now = datetime.now()
        week_ago = now - timedelta(days=7)

        # 获取当前余额
        current_balances = self.api_client.get_balances()
        bnb_balance = next((b for b in current_balances if b["asset"] == "BNB"), {"total": 0})["total"]

        # 从数据库获取历史数据
        history = self.db.get_balance_history(week_ago, now)

        # 计算收益
        bnb_start = history[-1]["bnb_amount"] if history else bnb_balance
        bnb_profit = bnb_balance - bnb_start
        bnb_profit_pct = (bnb_profit / bnb_start * 100) if bnb_start > 0 else 0

        # 获取交易记录
        trades = self.db.get_trades(week_ago, now)

        # 计算用户排名（模拟）
        user_rank = self._calculate_user_rank(bnb_profit_pct)

        report = {
            "period": f"{week_ago.strftime('%m/%d')} - {now.strftime('%m/%d')}",
            "bnb_start": bnb_start,
            "bnb_current": bnb_balance,
            "bnb_profit": bnb_profit,
            "bnb_profit_pct": bnb_profit_pct,
            "trade_count": len(trades),
            "user_rank": user_rank,
            "highlights": self._generate_highlights(trades, bnb_profit),
            "recommendations": self._generate_recommendations(current_balances)
        }

        return report

    def _calculate_user_rank(self, profit_pct: float) -> int:
        """模拟用户排名（实际需要真实数据对比）"""
        # 简单模拟：收益率越高排名越好
        if profit_pct < 0:
            return 90 + int(abs(profit_pct) * 10)
        elif profit_pct < 1:
            return 60 + int((1 - profit_pct) * 30)
        elif profit_pct < 3:
            return 30 + int((3 - profit_pct) * 15)
        elif profit_pct < 5:
            return 10 + int((5 - profit_pct) * 5)
        else:
            return max(1, 10 - int((profit_pct - 5) * 2))

    def _generate_highlights(self, trades: List[Dict], bnb_profit: float) -> List[str]:
        """生成亮点"""
        highlights = []

        if bnb_profit > 0:
            highlights.append(f"🎉 本周净赚 {bnb_profit:.4f} BNB")

        # 统计操作类型
        dust_sweeps = sum(1 for t in trades if t.get("type") == "dust_sweep")
        arbitrages = sum(1 for t in trades if t.get("type") == "arbitrage")

        if dust_sweeps > 0:
            highlights.append(f"🧹 执行了 {dust_sweeps} 次零钱兑换")
        if arbitrages > 0:
            highlights.append(f"📈 执行了 {arbitrages} 次资金费率套利")

        return highlights

    def _generate_recommendations(self, balances: List[Dict]) -> List[str]:
        """生成建议"""
        recommendations = []

        # 检查闲置资金
        idle_usdt = next((b for b in balances if b["asset"] == "USDT"), {"free": 0})["free"]
        if idle_usdt > 50:
            recommendations.append(f"💡 有 ${idle_usdt:.2f} USDT 闲置，考虑参与 Launchpool")

        # 检查 BNB 余额
        bnb = next((b for b in balances if b["asset"] == "BNB"), {"total": 0})["total"]
        if bnb < 0.5:
            recommendations.append("🦞 BNB 余额不足 0.5，建议增加持有")

        return recommendations

    def format_text_report(self, report: Dict) -> str:
        """格式化文本报告"""
        text = "🦞 金甲龙虾 - 周收益战报\n"
        text += "=" * 40 + "\n\n"

        text += f"📅 统计周期: {report['period']}\n\n"

        text += "💰 收益汇总:\n"
        text += f"  • 本期初 BNB: {report['bnb_start']:.4f}\n"
        text += f"  • 本期末 BNB: {report['bnb_current']:.4f}\n"

        if report['bnb_profit'] >= 0:
            text += f"  • 净增 BNB: +{report['bnb_profit']:.4f} ({report['bnb_profit_pct']:+.2f}%)\n"
        else:
            text += f"  • 净减 BNB: {report['bnb_profit']:.4f} ({report['bnb_profit_pct']:+.2f}%)\n"

        text += f"  • 用户排名: 超越 {report['user_rank']}% 用户\n\n"

        text += "📊 操作统计:\n"
        text += f"  • 交易次数: {report['trade_count']}\n\n"

        if report['highlights']:
            text += "✨ 本周亮点:\n"
            for h in report['highlights']:
                text += f"  {h}\n"
            text += "\n"

        if report['recommendations']:
            text += "💡 建议:\n"
            for r in report['recommendations']:
                text += f"  {r}\n"

        text += "\n🚀 #AIBinance #金甲龙虾 #BNB本位\n"

        return text

    def generate_poster_data(self, report: Dict) -> Dict:
        """生成海报数据（可用于生成图片）"""
        return {
            "title": "🦞 金甲龙虾周报",
            "period": report["period"],
            "bnb_profit": f"{report['bnb_profit']:+.4f}",
            "bnb_profit_pct": f"{report['bnb_profit_pct']:+.2f}%",
            "bnb_current": f"{report['bnb_current']:.4f}",
            "user_rank": f"超越 {report['user_rank']}% 用户",
            "highlights": report["highlights"],
            "hashtags": "#AIBinance #金甲龙虾 #BNB本位",
            "footer": "Powered by AegisClaw - AI守护您的加密资产"
        }

    def save_snapshot(self, balances: List[Dict]) -> bool:
        """保存余额快照到数据库"""
        try:
            bnb = next((b for b in balances if b["asset"] == "BNB"), {"total": 0})["total"]
            usdt = next((b for b in balances if b["asset"] == "USDT"), {"total": 0})["total"]

            self.db.save_balance_snapshot({
                "bnb_amount": bnb,
                "usdt_amount": usdt,
                "total_assets": len(balances),
                "timestamp": datetime.now()
            })
            return True
        except Exception as e:
            print(f"保存快照失败: {e}")
            return False


path: core/security_checker.py
content: """
安全检查模块 - AI 主动式"安全围栏"
"""

from typing import Dict, List, Tuple
from core.api_client import BinanceAPIClient
from config import BinanceConfig


class SecurityChecker:
    """安全检查器 - AI 拒绝越权的核心模块"""

    def __init__(self, api_client: BinanceAPIClient, config: BinanceConfig):
        self.api_client = api_client
        self.config = config

    def run_full_check(self) -> Dict[str, any]:
        """运行完整的安全检查"""
        results = {
            "api_connection": False,
            "account_type": "unknown",
            "permissions": [],
            "dangerous_permissions": [],
            "balance_summary": {},
            "security_score": 0,
            "warnings": [],
            "recommendations": []
        }

        try:
            # 1. 测试 API 连接
            if not self.api_client.ping():
                results["warnings"].append("❌ API 连接失败，请检查 API Key 和网络")
                return results
            results["api_connection"] = True

            # 2. 获取账户信息
            account = self.api_client.get_account()
            balances = self.api_client.get_balances()

            # 判断账户类型（通过余额特征）
            results["balance_summary"] = self._analyze_balances(balances)
            results["account_type"] = self._detect_account_type(balances, account)

            # 3. 检测危险权限
            perm_check = self._check_permissions(account)
            results["permissions"] = perm_check["all_permissions"]
            results["dangerous_permissions"] = perm_check["dangerous"]

            # 4. 计算安全评分
            results["security_score"] = self._calculate_security_score(results)

            # 5. 生成建议
            results["recommendations"] = self._generate_recommendations(results)

        except Exception as e:
            results["warnings"].append(f"⚠️ 检查过程中出错: {str(e)}")

        return results

    def _analyze_balances(self, balances: List[Dict]) -> Dict:
        """分析余额情况"""
        total_value = 0.0
        assets = {}

        for b in balances:
            if b["asset"] == "USDT":
                assets["USDT"] = b["total"]
                total_value += b["total"]
            elif b["asset"] == "FDUSD":
                assets["FDUSD"] = b["total"]
                total_value += b["total"]
            elif b["asset"] == "BNB":
                assets["BNB"] = b["total"]
                # BNB 价格估算
                try:
                    bnb_price = float(self.api_client.get_symbol_ticker("BNBUSDT")["price"])
                    total_value += b["total"] * bnb_price
                except:
                    pass

        return {
            "total_assets": len([b for b in balances if b["total"] > 0]),
            "stablecoin_balance": assets.get("USDT", 0) + assets.get("FDUSD", 0),
            "bnb_balance": assets.get("BNB", 0),
            "estimated_total_usdt": total_value
        }

    def _detect_account_type(self, balances: List[Dict], account: Dict) -> str:
        """检测账户类型（主账户 vs 子账户）"""
        # 通过账户权限特征判断
        permissions = account.get("permissions", [])

        if "SPOT" in permissions:
            # 如果余额较小，可能是子账户
            total_stable = sum(b["total"] for b in balances if b["asset"] in ["USDT", "FDUSD"])
            if total_stable < 1000:
                return "sub_account_recommended"
            elif total_stable > 10000:
                return "main_account_detected"

        return "sub_account"

    def _check_permissions(self, account: Dict) -> Dict:
        """检查 API 权限"""
        # 币安 API 不会直接返回权限信息
        # 我们需要通过尝试调用受限接口来判断

        permissions = ["SPOT"]  # 假设有现货权限（否则无法获取账户信息）
        dangerous = []

        # 检查是否有提现权限（通过接口尝试）
        # 注意：这里只是模拟检查，实际不应该调用提现接口
        # 实际情况需要用户手动配置时说明

        # 检查是否有合约权限
        try:
            # 尝试获取合约账户信息
            url = f"{self.api_client.base_url.replace('api', 'fapi')}/fapi/v2/account"
            response = self.api_client.session.get(url)
            if response.status_code == 200:
                permissions.append("FUTURES")
        except:
            pass

        # 标记危险权限
        for forbidden in self.config.forbidden_permissions:
            dangerous.append(forbidden)

        return {
            "all_permissions": permissions,
            "dangerous": dangerous
        }

    def _calculate_security_score(self, results: Dict) -> int:
        """计算安全评分 (0-100)"""
        score = 100

        # 账户类型扣分
        if results["account_type"] == "main_account_detected":
            score -= 40

        # 危险权限扣分
        if results["dangerous_permissions"]:
            score -= 50

        # 余额过大的子账户扣分
        if results["account_type"] == "sub_account":
            if results["balance_summary"].get("estimated_total_usdt", 0) > 2000:
                score -= 20

        return max(0, score)

    def _generate_recommendations(self, results: Dict) -> List[str]:
        """生成安全建议"""
        recommendations = []

        if results["account_type"] == "main_account_detected":
            recommendations.append(
                "⚠️ 检测到主账户！为了安全，建议创建一个仅含 500-1000 USDT 的子账户，"
                "并为此子账户创建专用 API Key。"
            )

        if results["dangerous_permissions"]:
            recommendations.append(
                "🚨 您的 API Key 可能包含危险权限！请确保关闭以下权限：\n"
                + "\n".join([f"   - {p}" for p in results["dangerous_permissions"]])
            )

        if results["balance_summary"].get("estimated_total_usdt", 0) > 2000:
            recommendations.append(
                "💡 建议：子账户资金建议控制在 500-1000 USDT 以内，最大风险可控。"
            )

        recommendations.append(
            "🛡️ 建议为 API Key 绑定 IP 白名单，只允许运行 AI 的服务器访问。"
        )

        return recommendations

    def format_report(self, results: Dict) -> str:
        """格式化安全检查报告"""
        report = "🦞 金甲龙虾 - 安全围栏检查报告\n"
        report += "=" * 50 + "\n\n"

        # 连接状态
        if results["api_connection"]:
            report += "✅ API 连接成功\n\n"
        else:
            report += "❌ API 连接失败\n\n"
            return report

        # 账户类型
        account_type_map = {
            "sub_account": "✅ 子账户",
            "sub_account_recommended": "✅ 子账户（推荐配置）",
            "main_account_detected": "⚠️ 检测到主账户"
        }
        report += f"账户类型: {account_type_map.get(results['account_type'], results['account_type'])}\n\n"

        # 余额摘要
        summary = results["balance_summary"]
        report += "资产摘要:\n"
        report += f"  • 资产种类: {summary['total_assets']} 种\n"
        report += f"  • 稳定币: ${summary['stablecoin_balance']:.2f}\n"
        report += f"  • BNB: {summary['bnb_balance']:.4f}\n"
        if summary.get('estimated_total_usdt'):
            report += f"  • 估算总值: ${summary['estimated_total_usdt']:.2f}\n"
        report += "\n"

        # API 权限
        report += "API 权限:\n"
        if results["permissions"]:
            report += "  • 已启用: " + ", ".join(results["permissions"]) + "\n"
        if results["dangerous_permissions"]:
            report += f"  • 🚨 危险权限: {', '.join(results['dangerous_permissions'])}\n"
        report += "\n"

        # 安全评分
        score = results["security_score"]
        if score >= 80:
            score_emoji = "🟢"
        elif score >= 50:
            score_emoji = "🟡"
        else:
            score_emoji = "🔴"
        report += f"{score_emoji} 安全评分: {score}/100\n\n"

        # 警告
        if results["warnings"]:
            report += "⚠️ 警告:\n"
            for w in results["warnings"]:
                report += f"  {w}\n"
            report += "\n"

        # 建议
        if results["recommendations"]:
            report += "💡 建议:\n"
            for r in results["recommendations"]:
                report += f"  {r}\n"

        return report


path: core/__init__.py
content: # Core module


path: db/database.py
content: """
数据库模块 - SQLite 数据存储
"""

import sqlite3
import json
from datetime import datetime
from typing import Dict, List, Optional
from pathlib import Path


class Database:
    """SQLite 数据库管理"""

    def __init__(self, db_path: str = "db/aegisclaw.db"):
        self.db_path = db_path
        Path(db_path).parent.mkdir(parents=True, exist_ok=True)
        self._init_db()

    def _init_db(self):
        """初始化数据库表"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()

            # 余额快照表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS balance_snapshots (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    bnb_amount REAL NOT NULL,
                    usdt_amount REAL NOT NULL,
                    total_assets INTEGER NOT NULL,
                    timestamp DATETIME NOT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            """)

            # 交易记录表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS trades (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    type TEXT NOT NULL,
                    symbol TEXT,
                    side TEXT,
                    quantity REAL NOT NULL,
                    price REAL,
                    order_id TEXT,
                    status TEXT NOT NULL,
                    profit REAL,
                    details TEXT,
                    timestamp DATETIME NOT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            """)

            # 安全检查记录表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS security_checks (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    account_type TEXT NOT NULL,
                    security_score INTEGER NOT NULL,
                    permissions TEXT,
                    warnings TEXT,
                    timestamp DATETIME NOT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            """)

            # 套利机会记录表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS arbitrage_opportunities (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    symbol TEXT NOT NULL,
                    funding_rate REAL NOT NULL,
                    spot_price REAL NOT NULL,
                    mark_price REAL NOT NULL,
                    estimated_profit_pct REAL NOT NULL,
                    executed BOOLEAN DEFAULT 0,
                    timestamp DATETIME NOT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            """)

            # 操作日志表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS operation_logs (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    operation_type TEXT NOT NULL,
                    status TEXT NOT NULL,
                    message TEXT,
                    details TEXT,
                    timestamp DATETIME NOT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            """)

            conn.commit()

    # ========== 余额快照 ==========

    def save_balance_snapshot(self, snapshot: Dict) -> int:
        """保存余额快照"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                INSERT INTO balance_snapshots
                (bnb_amount, usdt_amount, total_assets, timestamp)
                VALUES (?, ?, ?, ?)
            """, (
                snapshot["bnb_amount"],
                snapshot["usdt_amount"],
                snapshot["total_assets"],
                snapshot["timestamp"]
            ))
            conn.commit()
            return cursor.lastrowid

    def get_balance_history(self, start_time: datetime, end_time: datetime) -> List[Dict]:
        """获取余额历史"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT bnb_amount, usdt_amount, total_assets, timestamp
                FROM balance_snapshots
                WHERE timestamp BETWEEN ? AND ?
                ORDER BY timestamp ASC
            """, (start_time, end_time))
            rows = cursor.fetchall()

        return [{
            "bnb_amount": r[0],
            "usdt_amount": r[1],
            "total_assets": r[2],
            "timestamp": r[3]
        } for r in rows]

    # ========== 交易记录 ==========

    def save_trade(self, trade: Dict) -> int:
        """保存交易记录"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                INSERT INTO trades
                (type, symbol, side, quantity, price, order_id, status, profit, details, timestamp)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """, (
                trade["type"],
                trade.get("symbol"),
                trade.get("side"),
                trade["quantity"],
                trade.get("price"),
                trade.get("order_id"),
                trade["status"],
                trade.get("profit"),
                json.dumps(trade.get("details", {})),
                trade.get("timestamp", datetime.now())
            ))
            conn.commit()
            return cursor.lastrowid

    def get_trades(self, start_time: datetime, end_time: datetime) -> List[Dict]:
        """获取交易记录"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT type, symbol, side, quantity, price, order_id, status, profit, details, timestamp
                FROM trades
                WHERE timestamp BETWEEN ? AND ?
                ORDER BY timestamp DESC
            """, (start_time, end_time))
            rows = cursor.fetchall()

        return [{
            "type": r[0],
            "symbol": r[1],
            "side": r[2],
            "quantity": r[3],
            "price": r[4],
            "order_id": r[5],
            "status": r[6],
            "profit": r[7],
            "details": json.loads(r[8]) if r[8] else {},
            "timestamp": r[9]
        } for r in rows]

    # ========== 安全检查 ==========

    def save_security_check(self, check: Dict) -> int:
        """保存安全检查结果"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            # 添加 timestamp 字段
            timestamp = check.get("timestamp", datetime.now())
            cursor.execute("""
                INSERT INTO security_checks
                (account_type, security_score, permissions, warnings, timestamp)
                VALUES (?, ?, ?, ?, ?)
            """, (
                check["account_type"],
                check["security_score"],
                json.dumps(check["permissions"]),
                json.dumps(check["warnings"]),
                timestamp
            ))
            conn.commit()
            return cursor.lastrowid

    # ========== 套利机会 ==========

    def save_arbitrage_opportunity(self, opportunity: Dict) -> int:
        """保存套利机会"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                INSERT INTO arbitrage_opportunities
                (symbol, funding_rate, spot_price, mark_price, estimated_profit_pct, timestamp)
                VALUES (?, ?, ?, ?, ?, ?)
            """, (
                opportunity["symbol"],
                opportunity["funding_rate"],
                opportunity["spot_price"],
                opportunity["mark_price"],
                opportunity["estimated_profit_pct"],
                opportunity.get("timestamp", datetime.now())
            ))
            conn.commit()
            return cursor.lastrowid

    # ========== 操作日志 ==========

    def log_operation(self, operation_type: str, status: str, message: str, details: Dict = None):
        """记录操作日志"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                INSERT INTO operation_logs
                (operation_type, status, message, details, timestamp)
                VALUES (?, ?, ?, ?, ?)
            """, (
                operation_type,
                status,
                message,
                json.dumps(details) if details else None,
                datetime.now()
            ))
            conn.commit()

    def get_recent_logs(self, limit: int = 50) -> List[Dict]:
        """获取最近的操作日志"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT operation_type, status, message, details, timestamp
                FROM operation_logs
                ORDER BY timestamp DESC
                LIMIT ?
            """, (limit,))
            rows = cursor.fetchall()

        return [{
            "operation_type": r[0],
            "status": r[1],
            "message": r[2],
            "details": json.loads(r[3]) if r[3] else {},
            "timestamp": r[4]
        } for r in rows]


path: db/__init__.py
content: # Database module


path: install.py
content: #!/usr/bin/env python3
"""
金甲龙虾安装脚本
"""

import os
import sys
import subprocess


def run_command(cmd, description):
    """运行命令"""
    print(f"📦 {description}...")
    try:
        result = subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True)
        print(f"✅ {description} 完成")
        return True
    except subprocess.CalledProcessError as e:
        print(f"❌ {description} 失败: {e}")
        print(f"   {e.stderr}")
        return False


def main():
    print("🦞 金甲龙虾 - 安装向导")
    print("=" * 40)

    # 检查 Python 版本
    if sys.version_info < (3, 8):
        print("❌ 需要 Python 3.8 或更高版本")
        return

    print(f"✅ Python 版本: {sys.version_info.major}.{sys.version_info.minor}")

    # 安装依赖
    print("\n正在安装依赖...")
    success = run_command(
        sys.executable + " -m pip install -r requirements.txt",
        "安装 Python 依赖"
    )

    if not success:
        print("\n⚠️ 部分依赖安装失败，可能需要手动安装")

    # 创建 .env 文件（如果不存在）
    env_file = ".env"
    if not os.path.exists(env_file):
        print(f"\n📝 创建 {env_file} 模板...")
        try:
            import shutil
            shutil.copy(".env.example", env_file)
            print(f"✅ 已创建 {env_file}")
            print(f"⚠️ 请编辑 {env_file} 填入你的币安 API Key")
        except Exception as e:
            print(f"❌ 创建 {env_file} 失败: {e}")

    print("\n🎉 安装完成！")
    print("\n下一步:")
    print("1. 编辑 .env 文件，填入你的币安 API Key 和 Secret")
    print("2. 运行: python main.py --check  (进行安全检查)")
    print("   或运行: python main.py --all    (运行所有检查)")
    print("\n💡 提示: 建议使用子账户，并绑定 IP 白名单")


if __name__ == "__main__":
    main()


path: main.py
content: #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
金甲龙虾 (AegisClaw) - 主入口
既可作为 CLI 运行，也可作为 OpenClaw 插件使用
"""

import os
import sys
import argparse
from typing import Optional

# 设置输出编码为 UTF-8
if sys.platform == "win32":
    import codecs
    # 只在第一次输出时设置编码
    if sys.stdout.encoding != 'utf-8':
        sys.stdout.reconfigure(encoding='utf-8')
        sys.stderr.reconfigure(encoding='utf-8')

# 添加项目根目录到路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from config import config
from core.api_client import BinanceAPIClient
from core.security_checker import SecurityChecker
from core.asset_scanner import AssetScanner
from core.funding_arbitrage import FundingArbitrage
from core.report_generator import ReportGenerator
from db.database import Database


class AegisClaw:
    """金甲龙虾主类"""

    def __init__(self, api_key: str = None, api_secret: str = None, testnet: bool = False):
        # 从环境变量或参数读取配置
        self.[REDACTED_SECRET] or config.binance.api_key
        self.api_secret = api_secret or config.binance.api_secret
        self.testnet = testnet or config.binance.testnet

        # 初始化组件
        self.api_client = None
        self.database = None
        self.security_checker = None
        self.asset_scanner = None
        self.arbitrage = None
        self.report_generator = None

    def initialize(self):
        """初始化组件"""
        if not self.api_key or not self.api_secret:
            raise ValueError("缺少 API Key 或 Secret。请设置环境变量或传入参数。")

        # 更新配置
        config.binance.[REDACTED_SECRET]
        config.binance.api_secret = self.api_secret
        config.binance.testnet = self.testnet

        # 初始化客户端和组件
        self.api_client = BinanceAPIClient(config.binance)
        self.database = Database(config.database.path)
        self.security_checker = SecurityChecker(self.api_client, config.binance)
        self.asset_scanner = AssetScanner(self.api_client, config.strategy)
        self.arbitrage = FundingArbitrage(self.api_client, config.strategy)
        self.report_generator = ReportGenerator(self.api_client, self.database)

        print("🦞 金甲龙虾已初始化")
        print("=" * 40)

    # ========== 核心功能 ==========

    def security_check(self) -> str:
        """运行安全检查"""
        print("\n🛡️ 运行安全围栏检查...\n")
        result = self.security_checker.run_full_check()
        self.database.save_security_check(result)
        return self.security_checker.format_report(result)

    def scan_assets(self) -> str:
        """扫描资产"""
        print("\n📊 扫描资产...\n")
        result = self.asset_scanner.scan_idle_assets()
        return self.asset_scanner.format_report(result)

    def scan_arbitrage(self, symbols: Optional[list] = None) -> str:
        """扫描套利机会"""
        print("\n📈 扫描套利机会...\n")
        opportunities = self.arbitrage.scan_arbitrage_opportunities(symbols)
        return self.arbitrage.format_report(opportunities)

    def dust_sweep(self, assets: Optional[list] = None) -> str:
        """零钱兑换"""
        print("\n🧹 执行零钱兑换...\n")
        result = self.asset_scanner.execute_dust_sweep(assets)
        return result.get("message", "")

    def weekly_report(self) -> str:
        """生成周报"""
        print("\n📊 生成周收益战报...\n")
        report = self.report_generator.generate_weekly_report()
        return self.report_generator.format_text_report(report)

    def status(self) -> str:
        """查看状态"""
        print("\n📌 查看状态...\n")
        balances = self.api_client.get_balances()
        self.report_generator.save_snapshot(balances)

        bnb = next((b for b in balances if b["asset"] == "BNB"), {"total": 0})["total"]
        usdt = next((b for b in balances if b["asset"] == "USDT"), {"free": 0})["free"]

        status = f"""
🦞 金甲龙虾状态
{'='*30}

🔌 API 连接: ✅ 正常
📊 资产数量: {len(balances)}
💎 BNB 余额: {bnb:.4f}
💵 USDT 余额: {usdt:.2f}
"""
        return status

    def run_all_checks(self) -> str:
        """运行所有检查"""
        output = []
        output.append(self.security_check())
        output.append(self.scan_assets())
        output.append(self.scan_arbitrage())
        return "\n".join(output)


def main():
    """CLI 入口"""
    parser = argparse.ArgumentParser(
        description="🦞 金甲龙虾 - 币安安全赚币与护境神将",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  python main.py --check              # 运行安全检查
  python main.py --scan               # 扫描资产
  python main.py --arbitrage          # 扫描套利
  python main.py --dust               # 兑换零钱
  python main.py --report             # 生成周报
  python main.py --all                # 运行所有检查
  python main.py --testnet            # 使用测试网
        """
    )

    parser.add_argument("--key", help="Binance API Key")
    parser.add_argument("--secret", help="Binance API Secret")
    parser.add_argument("--testnet", action="store_true", help="使用测试网")
    parser.add_argument("--check", action="store_true", help="运行安全检查")
    parser.add_argument("--scan", action="store_true", help="扫描资产")
    parser.add_argument("--arbitrage", action="store_true", help="扫描套利机会")
    parser.add_argument("--dust", action="store_true", help="兑换零钱")
    parser.add_argument("--report", action="store_true", help="生成周报")
    parser.add_argument("--status", action="store_true", help="查看状态")
    parser.add_argument("--all", action="store_true", help="运行所有检查")

    args = parser.parse_args()

    # 如果没有指定任何操作，显示帮助
    if not any([args.check, args.scan, args.arbitrage, args.dust, args.report, args.status, args.all]):
        parser.print_help()
        return

    # 初始化
    try:
        claw = AegisClaw(args.key, args.secret, args.testnet)
        claw.initialize()
    except Exception as e:
        print(f"❌ 初始化失败: {e}")
        return

    # 执行命令
    try:
        if args.all:
            print(claw.run_all_checks())
        elif args.check:
            print(claw.security_check())
        elif args.scan:
            print(claw.scan_assets())
        elif args.arbitrage:
            print(claw.scan_arbitrage())
        elif args.dust:
            print(claw.dust_sweep())
        elif args.report:
            print(claw.weekly_report())
        elif args.status:
            print(claw.status())
    except Exception as e:
        import traceback
        print(f"❌ 执行失败: {e}")
        traceback.print_exc()


if __name__ == "__main__":
    main()


path: openclaw_plugin/plugin.py
content: """
OpenClaw 插件接口
让 AegisClaw 可以通过 OpenClaw 调用
"""

import os
import sys
from typing import Dict, Any, Optional

# 添加项目根目录到路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from config import config
from core.api_client import BinanceAPIClient
from core.security_checker import SecurityChecker
from core.asset_scanner import AssetScanner
from core.funding_arbitrage import FundingArbitrage
from core.report_generator import ReportGenerator
from db.database import Database


class AegisClawPlugin:
    """金甲龙虾 OpenClaw 插件"""

    name = "aegisclaw"
    version = "1.0.0"
    description = "🦞 金甲龙虾 - 币安安全赚币与护境神将"
    author = "AegisClaw Team"

    def __init__(self):
        self.initialized = False
        self.api_client = None
        self.security_checker = None
        self.asset_scanner = None
        self.arbitrage = None
        self.report_generator = None
        self.database = None

    def initialize(self, api_key: str = None, api_secret: str = None, testnet: bool = False):
        """初始化插件"""
        if [REDACTED_SECRET] = api_key
        if api_secret:
            config.binance.api_secret = api_secret
        config.binance.testnet = testnet

        if not config.binance.api_key or not config.binance.api_secret:
            return {
                "success": False,
                "error": "缺少 API Key 或 Secret。请使用: /aegisclaw init <api_key> <api_secret>"
            }

        try:
            self.api_client = BinanceAPIClient(config.binance)
            self.database = Database(config.database.path)
            self.security_checker = SecurityChecker(self.api_client, config.binance)
            self.asset_scanner = AssetScanner(self.api_client, config.strategy)
            self.arbitrage = FundingArbitrage(self.api_client, config.strategy)
            self.report_generator = ReportGenerator(self.api_client, self.database)
            self.initialized = True

            return {
                "success": True,
                "message": "🦞 金甲龙虾已就绪！主人，我将开始帮您安全地赚取 BNB。"
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"初始化失败: {str(e)}"
            }

    def check_initialized(self):
        """检查是否已初始化"""
        if not self.initialized:
            return {
                "success": False,
                "error": "请先初始化: /aegisclaw init <api_key> <api_secret>"
            }
        return None

    # ========== 命令处理 ==========

    def handle_command(self, command: str, args: list = None) -> Dict[str, Any]:
        """处理命令"""
        if args is None:
            args = []

        cmd_map = {
            "init": self.cmd_init,
            "check": self.cmd_security_check,
            "scan": self.cmd_scan_assets,
            "arbitrage": self.cmd_scan_arbitrage,
            "dust": self.cmd_dust_sweep,
            "report": self.cmd_weekly_report,
            "help": self.cmd_help,
            "status": self.cmd_status
        }

        cmd_func = cmd_map.get(command)
        if cmd_func:
            return cmd_func(args)
        else:
            return {
                "success": False,
                "error": f"未知命令: {command}\n使用 /aegisclaw help 查看帮助"
            }

    # ========== 命令实现 ==========

    def cmd_init(self, args: list) -> Dict:
        """初始化命令"""
        if len(args) < 2:
            return {
                "success": False,
                "error": "用法: /aegisclaw init <api_key> <api_secret> [testnet]"
            }
        [REDACTED_SECRET]
        api_secret = args[1]
        testnet = len(args) > 2 and args[2].lower() == "testnet"

        return self.initialize(api_key, api_secret, testnet)

    def cmd_security_check(self, args: list) -> Dict:
        """安全检查命令"""
        check = self.check_initialized()
        if check:
            return check

        try:
            result = self.security_checker.run_full_check()
            self.database.save_security_check(result)
            return {
                "success": True,
                "message": self.security_checker.format_report(result)
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"安全检查失败: {str(e)}"
            }

    def cmd_scan_assets(self, args: list) -> Dict:
        """资产扫描命令"""
        check = self.check_initialized()
        if check:
            return check

        try:
            result = self.asset_scanner.scan_idle_assets()
            return {
                "success": True,
                "message": self.asset_scanner.format_report(result)
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"资产扫描失败: {str(e)}"
            }

    def cmd_scan_arbitrage(self, args: list) -> Dict:
        """套利扫描命令"""
        check = self.check_initialized()
        if check:
            return check

        try:
            symbols = args if args else None
            opportunities = self.arbitrage.scan_arbitrage_opportunities(symbols)
            return {
                "success": True,
                "message": self.arbitrage.format_report(opportunities)
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"套利扫描失败: {str(e)}"
            }

    def cmd_dust_sweep(self, args: list) -> Dict:
        """零钱兑换命令"""
        check = self.check_initialized()
        if check:
            return check

        try:
            result = self.asset_scanner.execute_dust_sweep(args)
            if result["success"]:
                self.database.save_trade({
                    "type": "dust_sweep",
                    "status": "completed",
                    "quantity": 0,
                    "details": {"assets": args}
                })
            return {
                "success": result["success"],
                "message": result.get("message", "")
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"零钱兑换失败: {str(e)}"
            }

    def cmd_weekly_report(self, args: list) -> Dict:
        """周报命令"""
        check = self.check_initialized()
        if check:
            return check

        try:
            report = self.report_generator.generate_weekly_report()
            return {
                "success": True,
                "message": self.report_generator.format_text_report(report)
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"生成周报失败: {str(e)}"
            }

    def cmd_status(self, args: list) -> Dict:
        """状态命令"""
        check = self.check_initialized()
        if check:
            return check

        try:
            balances = self.api_client.get_balances()
            self.report_generator.save_snapshot(balances)

            status = f"""
🦞 金甲龙虾状态
{'='*30}

🔌 API 连接: ✅ 正常
📊 资产数量: {len(balances)}
💎 BNB 余额: {next((b['total'] for b in balances if b['asset']=='BNB'), 0):.4f}
💵 USDT 余额: {next((b['free'] for b in balances if b['asset']=='USDT'), 0):.2f}
"""
            return {
                "success": True,
                "message": status
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"获取状态失败: {str(e)}"
            }

    def cmd_help(self, args: list) -> Dict:
        """帮助命令"""
        help_text = """
🦞 金甲龙虾命令帮助

🔐 /aegisclaw init <key> <secret> [testnet]
    初始化插件（首次使用必填）

🛡️ /aegisclaw check
    运行安全围栏检查

💰 /aegisclaw scan
    扫描闲置资产和零钱

📈 /aegisclaw arbitrage
    扫描资金费率套利机会

🧹 /aegisclaw dust [资产列表]
    执行零钱兑换（不传参数自动扫描）

📊 /aegisclaw report
    生成周收益战报

📌 /aegisclaw status
    查看当前状态

💡 /aegisclaw help
    显示此帮助信息
"""
        return {
            "success": True,
            "message": help_text
        }


# OpenClaw 插件入口
plugin = AegisClawPlugin()

# OpenClaw 会调用以下函数
def get_plugin_info() -> Dict:
    """返回插件信息"""
    return {
        "name": plugin.name,
        "version": plugin.version,
        "description": plugin.description,
        "author": plugin.author
    }

def handle_command(command: str, args: list = None) -> Dict:
    """处理命令"""
    return plugin.handle_command(command, args)

def get_commands() -> list:
    """返回支持的命令列表"""
    return [
        "init",
        "check",
        "scan",
        "arbitrage",
        "dust",
        "report",
        "status",
        "help"
    ]


path: openclaw_plugin/__init__.py
content: # OpenClaw plugin module


path: README.md
content: # 🦞 金甲龙虾 (AegisClaw)

> 币安安全赚币与护境神将 — 既有破浪赚取 Alpha 的双钳，又有绝对守护资产的金甲

**AegisClaw** 是一个基于**最小权限原则**和**币安子账户生态**的防御型 AI 代理，专注于低风险、自动化的资产管理与套利。

## ✨ 核心特性

### 🛡️ 安全围栏
- **子账户沙盒隔离** — 推荐使用独立的子账户进行操作
- **API 权限自检** — 自动检测并警告危险权限配置
- **操作防火墙** — 滑点限制、交易频次控制

### 💰 赚币引擎
- **Launchpool/Megadrop 监控** — 智能扫描新币挖矿机会
- **零钱自动兑换** — 将小额资产自动兑换为 BNB (Dust Sweeper)
- **资金费率套利** — 现货与合约之间的无风险套利机会

### 📊 数据统计
- **余额快照记录** — 自动保存每日资产快照
- **交易历史追踪** — SQLite 数据库持久化存储
- **周收益战报** — 一键生成并分享收益报告

---

## 🚀 快速开始

### 方式一：CLI 命令行

```bash
# 1. 克隆项目
git clone https://github.com/hyy2099/aegisclaw.git
cd aegisclaw

# 2. 安装依赖
pip install -r requirements.txt

# 3. 配置环境变量
# Windows: 复制 .env.example 为 .env 并编辑
# Linux/Mac:
cp .env.example .env
# 编辑 .env 填入你的币安 API Key

# 4. 运行
python main.py --check      # 安全检查
python main.py --scan       # 扫描资产
python main.py --arbitrage  # 套利扫描
python main.py --all        # 运行所有检查
```

### 方式二：OpenClaw 插件

```bash
# 1. 安装 OpenClaw
# 参考: https://clawhub.io

# 2. 安装插件
openclaw plugin install aegisclaw

# 3. 初始化
/aegisclaw init <api_key> <api_secret> [testnet]

# 4. 使用命令
/aegisclaw check       # 安全检查
/aegisclaw scan        # 扫描资产
/aegisclaw arbitrage   # 套利扫描
/aegisclaw dust        # 零钱兑换
/aegisclaw report      # 生成周报
/aegisclaw status      # 查看状态
```

### 方式三：Claude Code

Claude Code 是 Anthropic 的 CLI 工具，可以直接与 AegisClaw 集成：

**安装 Claude Code**
```bash
# macOS/Linux
curl -fsSL https://cdn.anthropic.com/install.sh | sh

# Windows (使用 scoop)
scoop install claude-code
```

**使用方式**

在 Claude Code 中：

```python
# 1. 导入并初始化
from openclaw_plugin.plugin import plugin

# 2. 初始化插件
result = plugin.initialize("your_api_key", "your_api_secret", testnet=False)
print(result["message"])

# 3. 执行命令
result = plugin.handle_command("check")
print(result["message"])

result = plugin.handle_command("scan")
print(result["message"])

result = plugin.handle_command("arbitrage")
print(result["message"])

# 4. 生成报告
result = plugin.handle_command("report")
print(result["message"])
```

**Claude Code 交互式使用**

你也可以让 Claude Code 自动帮你操作：

```
用户: 帮我检查币安账户安全状态
Claude: [自动执行] plugin.handle_command("check")

用户: 扫描一下资产，看看有没有零钱可以兑换
Claude: [自动执行] plugin.handle_command("scan"); plugin.handle_command("dust")

用户: 有没有什么套利机会？
Claude: [自动执行] plugin.handle_command("arbitrage")
```

**高级用法 - 让 AI 自动分析**

```
用户: 每天早上 8 点帮我检查套利机会，如果有大于 0.1% 的机会就告诉我
Claude: [使用 Cron 或循环自动监控]
```

---

## 📋 详细命令说明

### CLI 命令

```bash
python main.py --help                    # 显示帮助
python main.py --testnet                 # 使用测试网
python main.py --key <key> --secret <secret>  # 使用命令行参数
```

### 可用操作

| 命令 | 说明 | 示例 |
|------|------|------|
| `--check` | 运行安全围栏检查 | `python main.py --check` |
| `--scan` | 扫描闲置资产和零钱 | `python main.py --scan` |
| `--arbitrage` | 扫描资金费率套利机会 | `python main.py --arbitrage` |
| `--dust` | 执行零钱兑换 | `python main.py --dust` |
| `--report` | 生成周收益战报 | `python main.py --report` |
| `--status` | 查看当前状态 | `python main.py --status` |
| `--all` | 运行所有检查 | `python main.py --all` |

### OpenClaw 命令

| 命令 | 说明 | 示例 |
|------|------|------|
| `init` | 初始化插件 | `/aegisclaw init <key> <secret>` |
| `check` | 安全检查 | `/aegisclaw check` |
| `scan` | 资产扫描 | `/aegisclaw scan` |
| `arbitrage` | 套利扫描 | `/aegisclaw arbitrage` |
| `dust` | 零钱兑换 | `/aegisclaw dust [BTC,ETH]` |
| `report` | 周报 | `/aegisclaw report` |
| `status` | 状态 | `/aegisclaw status` |
| `help` | 帮助 | `/aegisclaw help` |

---

## 💡 使用案例

### 案例 1：新用户安全检查

```bash
# 首次使用，运行完整检查
python main.py --all
```

**输出示例：**
```
🦞 金甲龙虾 - 币安安全赚币与护境神将
========================================

🛡️ 运行安全围栏检查...

🦞 金甲龙虾 - 安全围栏检查报告
==================================================

✅ API 连接成功

账户类型: ✅ 子账户（推荐配置）

资产摘要:
  • 资产种类: 5 种
  • 稳定币: $500.00
  • BNB: 2.5000

API 权限:
  • 已启用: SPOT
  • 🚨 危险权限: 无 (安全)

🟢 安全评分: 100/100

💡 建议:
  • 建议为 API Key 绑定 IP 白名单
```

### 案例 2：资产扫描与零钱兑换

```bash
# 扫描资产
python main.py --scan

# 兑换零钱
python main.py --dust
```

**输出示例：**
```
📊 资产扫描报告
========================================

💰 闲置资金:
  • USDT: $500.00
  • 总计: $500.00

🧹 零钱资产:
  • ETH: 0.0005 (~$2.50)
  • DOGE: 50.5 (~$7.20)

💡 建议:
  🚀 检测到 $500.00 USDT 闲置，可参与 Launchpool
  🧹 发现 2 种零钱，总价值约 $9.70

🦞 零钱兑换执行中...
✅ 兑换完成! 获得 0.0323 BNB
```

### 案例 3：资金费率套利

```bash
python main.py --arbitrage
```

**输出示例：**
```
📈 资金费率套利机会
==================================================

1. 📈 BTCUSDT
   资金费率: +0.0150%
   现货价格: $65000.00
   标记价格: $65015.00
   价格偏差: +0.02%
   预计收益: 0.0150%
   操作建议: 做多现货，做空合约，收取 0.0150% 资金费

2. 📈 ETHUSDT
   资金费率: +0.0200%
   现货价格: $3500.00
   标记价格: $3508.00
   预计收益: 0.0200%
   操作建议: 做多现货，做空合约，收取 0.0200% 资金费

⚠️ 提醒: 套利有风险，请控制仓位
```

### 案例 4：使用 Claude Code 自动化

让 Claude Code 每天早上 8 点检查并通知：

```
用户: 帮我设置一个定时任务，每天早上8点检查套利机会，如果有大于0.1%的机会就通知我

Claude: [使用 Cron 或其他调度工具设置自动化监控]
```

---

## 🔒 安全建议

### 1. 使用子账户
- 创建仅含 500-1000 USDT 的子账户
- 不要使用主账户进行操作

### 2. 限制 API 权限
```
✅ 启用: 现货交易 (SPOT)
❌ 禁用: 提现 (WITHDRAW)
❌ 禁用: 期货交易 (FUTURES)
```

### 3. 绑定 IP 白名单
- 限制 API 只能从特定 IP 访问
- 定期检查 IP 白名单

### 4. 控制资金规模
- 子账户资金建议在 1000 USDT 以内
- 使用闲置资金，不影响正常生活

---

## 📁 项目结构

```
aegisclaw/
├── main.py                    # CLI 入口
├── config.py                  # 配置文件
├── requirements.txt           # Python 依赖
├── .env.example               # 环境变量示例
├── start.bat                  # Windows 快速启动脚本
├── core/                      # 核心模块
│   ├── api_client.py          # 币安 API 客户端
│   ├── security_checker.py    # 安全检查器
│   ├── asset_scanner.py       # 资产扫描器
│   ├── funding_arbitrage.py    # 资金费率套利
│   └── report_generator.py    # 报告生成器
├── db/                        # 数据库模块
│   └── database.py            # SQLite 数据库
└── openclaw_plugin/           # OpenClaw 插件接口
    └── plugin.py              # 插件入口
```

---

## 🔧 配置说明

### .env 配置

```bash
# 币安 API 配置
BINANCE_API_KEY=your_api_key_here
BINANCE_API_SECRET=your_api_secret_here
BINANCE_TESTNET=false

# Telegram 配置（可选）
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=

# 安全配置
MAX_DAILY_TRADES=10          # 每日最大交易次数
MAX_PRICE_SLIPPAGE=0.01      # 最大价格滑点 (1%)

# 策略配置
FUNDING_RATE_THRESHOLD=0.0001  # 资金费率阈值
MIN_ARBITRAGE_PROFIT=0.001     # 最小套利利润 (0.1%)
MIN_LAUNCHPOOL_AMOUNT=10.0      # Launchpool 最小金额
MIN_DUST_THRESHOLD=10.0         # 零钱兑换最小阈值
```

---

## 🎯 项目亮点

本项目为币安「AI 建设加密」活动参赛作品，核心亮点：

1. **将安全短板转化为核心武器** — AI 主动拒绝越权操作
2. **一切收益换成 BNB** — 完美契合币安生态利益
3. **极低的落地门槛** — 使用原生 API，无需复杂模型
4. **多种使用方式** — CLI、OpenClaw、Claude Code

---

## 📜 许可证

MIT License

---

## 🤝 贡献

欢迎提交 Issue 和 Pull Request！

---

🦞 **金甲龙虾** — 您的币安无风险赚币与护境神将


path: requirements.txt
content: # 金甲龙虾 (AegisClaw) 依赖

# HTTP 请求
requests>=2.31.0

# 环境变量
python-dotenv>=1.0.0

# 日期处理
python-dateutil>=2.8.2

# 数据可视化（可选，用于海报生成）
matplotlib>=3.8.0


path: setup.py
content: #!/usr/bin/env python3
"""
金甲龙虾 (AegisClaw) - 安装配置
"""

from setuptools import setup, find_packages

with open("README.md", "r", encoding="utf-8") as f:
    long_description = f.read()

setup(
    name="aegisclaw",
    version="1.0.0",
    author="AegisClaw Team",
    author_email="",
    description="🦞 金甲龙虾 - 币安安全赚币与护境神将",
    long_description=long_description,
    url="https://github.com/hyy2099/aegisclaw",
    packages=find_packages(),
    include_package_data=True,
    install_requires=[
        "requests>=2.31.0",
        "python-dotenv>=1.0.0",
        "python-dateutil>=2.8.2",
    ],
    keywords=[
        "binance",
        "trading",
        "arbitrage",
        "security",
        "ai",
        "cryptocurrency",
        "bnb",
        "launchpool",
        "funding-rate"
    ],
    classifiers=[
        "Development Status :: 4 - Beta",
        "Intended Audience :: Developers",
        "Topic :: Office/Business :: Financial :: Investment",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.8",
    entry_points={
        "console_scripts": [
            "aegisclaw=main:main",
        ],
    },
)


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)